Skip to content

Instantly share code, notes, and snippets.

@oeway
Last active December 7, 2020 11:32
Show Gist options
  • Save oeway/7a5313eb4fb7ed09a5f6d60adb561d59 to your computer and use it in GitHub Desktop.
Save oeway/7a5313eb4fb7ed09a5f6d60adb561d59 to your computer and use it in GitHub Desktop.
<config lang="json">
{
"name": "MicroManagerControl",
"type": "native-python",
"version": "0.1.0",
"description": "Microscope control with MicroManager(pymmcore)",
"tags": [],
"ui": "",
"cover": "",
"inputs": null,
"outputs": null,
"flags": [],
"icon": "extension",
"api_version": "0.1.8",
"env": [{"type": "binder", "spec": "imjoy-team/micro-manager-imjoy/master", "skip_requirements": true}],
"permissions": [],
"requirements": ["repo:https://github.com/imjoy-team/micro-manager-imjoy", "pip:-r micro-manager-imjoy/requirements.txt"],
"dependencies": []
}
</config>
<script lang="python">
import time
from imjoy import api
import numpy as np
import pymmcore
import os.path
import os
import re
class DotDict(dict):
__getattr__ = dict.__getitem__
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
def to_camel_case(snake_str):
components = snake_str.split('_')
# We capitalize the first letter of each component except the first one
# with the 'title' method and join them together.
return components[0] + ''.join(x.title() for x in components[1:])
class MMCoreWrapper():
'''
make a wrapper to mmcore so the function calls are more pythonic
meaning, all the camel case are converted into snake case
for example: mmc.setExposure are converted into mmc.set_exposure
'''
def __init__(self, obj):
self._wrapped_obj = obj
def get_tagged_image(self):
img = self.get_image()
return DotDict({"pix": img, "tags": {"Height": img.shape[0], "Width": img.shape[1]}})
def __getattr__(self, attr):
if attr in self.__dict__:
return getattr(self, attr)
attr = to_camel_case(attr)
return getattr(self._wrapped_obj, attr)
class MyMicroscope():
async def setup(self):
MM_DIR = "./mmcore"
MM_CONFIG_FILE = os.path.join(MM_DIR, "MMConfig_demo.cfg")
if not os.path.exists(MM_DIR) or not os.path.exists(MM_CONFIG_FILE):
MM_DIR = await api.prompt("Please input the root path for your micro-manager installation:", './mmcore')
if not os.path.exists(MM_DIR):
await api.alert("Invalid micromanager folder.")
return
else:
MM_CONFIG_FILE = await api.prompt("Please input the microscope configuration", os.path.join(MM_DIR, "MMConfig_demo.cfg"))
mmc = pymmcore.CMMCore()
mmc.setDeviceAdapterSearchPaths([MM_DIR])
mmc.loadSystemConfiguration(MM_CONFIG_FILE)
self._core = MMCoreWrapper(mmc)
exposure = self._core.get_exposure()
api.showMessage('MMcore loaded, exposure: ' + str(exposure))
def snap_image(self):
if self._core.is_sequence_running():
self._core.stop_sequence_acquisition()
self._core.snap_image()
tagged_image = self._core.get_tagged_image()
image_array = np.reshape(tagged_image.pix, newshape=[-1, tagged_image.tags['Height'], tagged_image.tags['Width']])
image_array = (image_array/image_array.max()*255).astype('uint8')
return image_array
def get_image(self):
# we can also check remaining with getRemainingImageCount()
tagged_image = self._core.get_tagged_image()
image_array = np.reshape(tagged_image.pix, newshape=[-1, tagged_image.tags['Height'], tagged_image.tags['Width']])
image_array = (image_array/image_array.max()*255).astype('uint8')
return image_array
def get_device_properties(self):
core = self._core
devices = core.get_loaded_devices()
if not isinstance(devices, tuple):
devices = [devices.get(i) for i in range(devices.size())]
device_items = []
for device in devices:
props = core.get_device_property_names(device)
if not isinstance(props, tuple):
props = [props.get(i) for i in range(props.size())]
property_items = []
for prop in props:
value = core.get_property(device, prop)
is_read_only = core.is_property_read_only(device, prop)
if core.has_property_limits(device, prop):
lower = core.get_property_lower_limit(device, prop)
upper = core.get_property_upper_limit(device, prop)
allowed = {"type": "range", "min": lower, "max": upper, "readOnly": is_read_only}
else:
allowed = core.get_allowed_property_values(device, prop)
if not isinstance(allowed, tuple):
allowed = [allowed.get(i) for i in range(allowed.size())]
allowed = {"type": "enum", "options": allowed, "readOnly": is_read_only}
property_items.append({"device": device, "name": prop, "value": value, "allowed": allowed})
# print('===>', device, prop, value, allowed)
if len(property_items) > 0:
device_items.append({"name": device, "value": "{} properties".format(len(props)), "items": property_items})
return device_items
async def run(self, ctx):
mmcore_api = {
"_rintf": True,
"snapImage": self.snap_image,
"getImage": self.get_image,
"getDeviceProperties": self.get_device_properties,
"getCameraDevice": self._core.get_camera_device,
"setCameraDevice": self._core.set_camera_device,
"startContinuousSequenceAcquisition": self._core.start_continuous_sequence_acquisition,
"stopSequenceAcquisition": self._core.stop_sequence_acquisition,
"setExposure": self._core.set_exposure,
"getExposure": self._core.get_exposure,
"setProperty": self._core.set_property,
"getProperty": self._core.get_property
}
viewer = await api.createWindow(src="https://gist.github.com/oeway/f59c1d1c49c94a831e5e21ba4c6111dd", data={'mmcore': mmcore_api})
api.export(MyMicroscope())
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment