From ce1b0280da11ac51381ab2171ccc44f1726be293 Mon Sep 17 00:00:00 2001 From: Henry Pinkard <7969470+henrypinkard@users.noreply.github.com> Date: Tue, 9 Jul 2024 18:23:17 +0200 Subject: [PATCH] revert accidental changes --- pycromanager/acquisition/RAMStorage_java.py | 6 +-- .../acquisition/acq_eng_py/internal/hooks.py | 17 ------- pycromanager/headless.py | 47 +++++++++++++++---- pycromanager/mm_java_classes.py | 6 +-- pycromanager/napari_util.py | 6 +-- pycromanager/test/conftest.py | 4 +- pycromanager/test/test_callback_functions.py | 2 +- pycromanager/test/test_notifications.py | 4 +- 8 files changed, 53 insertions(+), 39 deletions(-) delete mode 100644 pycromanager/acquisition/acq_eng_py/internal/hooks.py diff --git a/pycromanager/acquisition/RAMStorage_java.py b/pycromanager/acquisition/RAMStorage_java.py index e568fcac..6f54cbec 100644 --- a/pycromanager/acquisition/RAMStorage_java.py +++ b/pycromanager/acquisition/RAMStorage_java.py @@ -3,10 +3,10 @@ class NDRAMDatasetJava(NDStorageBase): """ - A python class that wraps a Java-backend RAM data storage_implementations. + A python class that wraps a Java-backend RAM data storage. This class maintains an index of which images have been saved, but otherwise routes all calls to the Java - implementation of the RAM data storage_implementations. + implementation of the RAM data storage. """ def __init__(self, java_RAM_data_storage): @@ -22,7 +22,7 @@ def close(self): def add_available_axes(self, image_coordinates): """ - The Java RAM storage_implementations has received a execution_engine image with the given axes. Add these axes to the index. + The Java RAM storage has received a new image with the given axes. Add these axes to the index. """ self._index_keys.add(frozenset(image_coordinates.items())) # update information about the available images diff --git a/pycromanager/acquisition/acq_eng_py/internal/hooks.py b/pycromanager/acquisition/acq_eng_py/internal/hooks.py deleted file mode 100644 index e9ea5c54..00000000 --- a/pycromanager/acquisition/acq_eng_py/internal/hooks.py +++ /dev/null @@ -1,17 +0,0 @@ - -EVENT_GENERATION_HOOK = 0 -# This hook runs before changes to the hardware (corresponding to the instructions in the -# event) are made -BEFORE_HARDWARE_HOOK = 1 -# This hook runs after all changes to the hardware except dor setting th Z drive have been -# made. This is useful for things such as autofocus. -BEFORE_Z_DRIVE_HOOK = 2 -# This hook runs after changes to the hardware took place, but before camera exposure -# (either a snap or a sequence) is started -AFTER_HARDWARE_HOOK = 3 -# Hook runs after the camera sequence acquisition has started. This can be used for -# external triggering of the camera -AFTER_CAMERA_HOOK = 4 -# Hook runs after the camera exposure ended (when possible, before readout of the camera -# and availability of the images in memory). -AFTER_EXPOSURE_HOOK = 5 \ No newline at end of file diff --git a/pycromanager/headless.py b/pycromanager/headless.py index 2243851d..84b3658a 100644 --- a/pycromanager/headless.py +++ b/pycromanager/headless.py @@ -6,7 +6,7 @@ import types import os -# from pycromanager.acquisition.acq_eng_py.kernel.engine import Engine +from pycromanager.acquisition.acq_eng_py.internal.engine import Engine from pymmcore import CMMCore import pymmcore from pyjavaz import DEFAULT_BRIDGE_PORT, server_terminated @@ -36,7 +36,7 @@ def _create_pymmcore_instance(): 2. add convenience methods to match the MMCoreJ API: """ - # Create a execution_engine dictionary for the class attributes + # Create a new dictionary for the class attributes new_attributes = {} # Iterate through the original attributes @@ -49,9 +49,42 @@ def _create_pymmcore_instance(): new_attr_name = _camel_to_snake(attr_name) new_attributes[new_attr_name] = attr_value - # Create and return a execution_engine class that subclasses the original class and has the execution_engine attributes + # Create and return a new class that subclasses the original class and has the new attributes clz = type(CMMCore.__name__ + "SnakeCase", (CMMCore,), new_attributes) + instance = clz() + + def pop_next_tagged_image(self): + md = pymmcore.Metadata() + pix = self.pop_next_image_md(0, 0, md) + tags = {key: md.GetSingleTag(key).GetValue() for key in md.GetKeys()} + return TaggedImage(tags, pix) + + def get_tagged_image(core, cam_index, camera, height, width, binning=None, pixel_type=None, roi_x_start=None, + roi_y_start=None): + """ + Different signature than the Java version because of difference in metadata handling in the swig layers + """ + pix = core.get_image() + md = pymmcore.Metadata() + # most of the same tags from pop_next_tagged_image, which may not be the same as the MMCoreJ version of this function + tags = {'Camera': camera, 'Height': height, 'Width': width, 'PixelType': pixel_type, + 'CameraChannelIndex': cam_index} + # Could optionally add these for completeness but there might be a performance hit + if binning is not None: + tags['Binning'] = binning + if roi_x_start is not None: + tags['ROI-X-start'] = roi_x_start + if roi_y_start is not None: + tags['ROI-Y-start'] = roi_y_start + + return TaggedImage(tags, pix) + + instance.get_tagged_image = types.MethodType(get_tagged_image, instance) + instance.pop_next_tagged_image = types.MethodType(pop_next_tagged_image, instance) + + # attach TaggedImage class + instance.TaggedImage = TaggedImage return instance @@ -79,9 +112,8 @@ def stop_headless(debug=False): logger.debug('Stopping pymmcore instance') c.unloadAllDevices() if debug: - logger.debug('Unloaded all device_implementations.py') - # TODO: shutdown execution_engine engine - # Engine.get_instance().shutdown() + logger.debug('Unloaded all devices') + Engine.get_instance().shutdown() if debug: logger.debug('Engine shut down') _PYMMCORES.clear() @@ -137,8 +169,7 @@ def start_headless( mmc.load_system_configuration(config_file) mmc.set_circular_buffer_memory_footprint(buffer_size_mb) _PYMMCORES.append(mmc) # Store so it doesn't get garbage collected - # TODO: startup execution_engine engine - # Engine(mmc) + Engine(mmc) else: classpath = mm_app_path + '/plugins/Micro-Manager/*' if java_loc is None: diff --git a/pycromanager/mm_java_classes.py b/pycromanager/mm_java_classes.py index 55a1a7e3..ac5bf87a 100644 --- a/pycromanager/mm_java_classes.py +++ b/pycromanager/mm_java_classes.py @@ -74,7 +74,7 @@ def __new__( port: int The port of the Bridge used to create the object new_socket: bool - If True, will create execution_engine java object on a execution_engine port so that blocking calls will not interfere + If True, will create new java object on a new port so that blocking calls will not interfere with the bridges main port debug: print debug messages @@ -117,7 +117,7 @@ def __new__( port: int The port of the Bridge used to create the object new_socket: bool - If True, will create execution_engine java object on a execution_engine port so that blocking calls will not interfere + If True, will create new java object on a new port so that blocking calls will not interfere with the bridges main port debug: bool print debug messages @@ -142,7 +142,7 @@ def __new__( port: int The port of the Bridge used to create the object new_socket: bool - If True, will create execution_engine java object on a execution_engine port so that blocking calls will not interfere + If True, will create new java object on a new port so that blocking calls will not interfere with the bridges main port debug: bool print debug messages diff --git a/pycromanager/napari_util.py b/pycromanager/napari_util.py index 6fe4eb1b..03aba724 100644 --- a/pycromanager/napari_util.py +++ b/pycromanager/napari_util.py @@ -8,7 +8,7 @@ def start_napari_signalling(viewer, dataset): """ - Start up a threadworker, which will check for execution_engine images arrived in the dataset + Start up a threadworker, which will check for new images arrived in the dataset and then signal to napari to update or refresh as needed :param viewer: the napari Viewer :param dataset: the Datatset being acquired @@ -17,7 +17,7 @@ def start_napari_signalling(viewer, dataset): def update_layer(image): """ - update the napari layer with the execution_engine image + update the napari layer with the new image """ if image is not None: try: @@ -29,7 +29,7 @@ def update_layer(image): @thread_worker(connect={'yielded': update_layer}) def napari_signaller(): """ - Monitor for signals that Acquisition has a execution_engine image ready, and when that happens + Monitor for signals that Acquisition has a new image ready, and when that happens update napari appropriately """ # don't update faster than the display can handle diff --git a/pycromanager/test/conftest.py b/pycromanager/test/conftest.py index d2dc28ee..e59fd501 100644 --- a/pycromanager/test/conftest.py +++ b/pycromanager/test/conftest.py @@ -72,7 +72,7 @@ def install_mm(): # find pycro-manager/java path if os.path.isdir('java'): java_path = os.path.abspath('java') - # in case cwd is '/pycromanager/integration_tests' + # in case cwd is '/pycromanager/test' elif os.path.isdir('../../java'): java_path = os.path.abspath('../../java') else: @@ -86,7 +86,7 @@ def install_mm(): print(f'Removed {file_path}') # Copy the pycromanagerjava.jar file that was compiled by the github action - # into the nightly build so that it will integration_tests with the latest code + # into the nightly build so that it will test with the latest code compiled_jar_path = os.path.join(java_path, 'target', 'PycromanagerJava-*.jar') destination_path = os.path.join(mm_install_dir, 'plugins', 'Micro-Manager', 'PycromanagerJava.jar') diff --git a/pycromanager/test/test_callback_functions.py b/pycromanager/test/test_callback_functions.py index e39b3531..123a227b 100644 --- a/pycromanager/test/test_callback_functions.py +++ b/pycromanager/test/test_callback_functions.py @@ -90,7 +90,7 @@ def hook_fn(event): return None # cancel the event with Acquisition(show_display=False, pre_hardware_hook_fn=hook_fn) as acq: - # copy list of event_implementations to avoid popping from original + # copy list of events to avoid popping from original events_copy = [e for e in events] for test_event in events: acq.acquire(test_event) diff --git a/pycromanager/test/test_notifications.py b/pycromanager/test/test_notifications.py index 437c990d..0b725f19 100644 --- a/pycromanager/test/test_notifications.py +++ b/pycromanager/test/test_notifications.py @@ -8,9 +8,9 @@ # TODO: add tests for timing of blocking until different parts of the hardware sequence # def test_async_images_read(launch_mm_headless, setup_data_folder): # start = time.time() -# event_implementations = multi_d_acquisition_events(num_time_points=10, time_interval_s=0.5) +# events = multi_d_acquisition_events(num_time_points=10, time_interval_s=0.5) # with Acquisition(directory=setup_data_folder, show_display=False) as acq: -# future = acq.acquire(event_implementations) +# future = acq.acquire(events) # # future.await_execution({'time': 5}, AcqNotification.Hardware.POST_HARDWARE)