def main(): bridge = Bridge() mmc = bridge.get_core() # Data set parameters path = Path('E://20201023//') name = 'test' # z stack parameters start_end_pos = -5 mid_pos = 5 step_size = .25 relative = True # time series parameters exposure_time = 200 # in milliseconds num_z_positions = int(abs(mid_pos - start_end_pos)/step_size + 1) z_idx = list(range(num_z_positions)) num_time_points = 10 # setup cameras mmc.set_exposure(exposure_time) # setup z stage z_stage = mmc.get_focus_device() z_pos, pos_sequence = upload_stage_sequence(bridge, start_end_pos, mid_pos, step_size, relative) num_z_positions = len(pos_sequence) print(pos_sequence) # move to first position mmc.set_position(z_stage, pos_sequence[0]) events = [] z_idx_ = z_idx.copy() for i in range(num_time_points): for j in z_idx_: events.append({'axes': {'time':i, 'z': j}}) z_idx_.reverse() with Acquisition(directory=path, name=name) as acq: acq.acquire(events) # turn off sequencing mmc.set_property(z_stage, "UseFastSequence", "No") mmc.set_property(z_stage, "UseSequence", "No")
def main(): #------------------------------------------------------------------------------------------------------------------------------------ #----------------------------------------------Begin setup of scan parameters-------------------------------------------------------- #------------------------------------------------------------------------------------------------------------------------------------ # lasers to use # 0 -> inactive # 1 -> active state_405 = 1 state_488 = 0 state_561 = 0 state_635 = 1 state_730 = 0 # laser powers (0 -> 100%) power_405 = 10 power_488 = 0 power_561 = 0 power_635 = 10 power_730 = 0 # exposure time exposure_ms = 5. # scan axis limits. Use stage positions reported by MM scan_axis_start_um = -26000. #unit: um scan_axis_end_um = -25500. #unit: um # tile axis limits. Use stage positions reported by MM tile_axis_start_um = -7000 #unit: um tile_axis_end_um = -6500. #unit: um # height axis limits. Use stage positions reported by MM height_axis_start_um = 345. #unit: um height_axis_end_um = 375. #unit: um # FOV parameters # ONLY MODIFY IF NECESSARY ROI = [0, 1024, 1599, 255] #unit: pixels # setup file name save_directory = Path('E:/20201130/') save_name = Path('shaffer_lung_v1.h5') #------------------------------------------------------------------------------------------------------------------------------------ #----------------------------------------------End setup of scan parameters---------------------------------------------------------- #------------------------------------------------------------------------------------------------------------------------------------ # instantiate the Python-Java bridge to MM bridge = Bridge() core = bridge.get_core() # turn off lasers core.set_config('Coherent-State', 'off') core.wait_for_config('Coherent-State', 'off') # set camera into 16bit readout mode core.set_property('Camera', 'ReadoutRate', '100MHz 16bit') time.sleep(1) # set camera into low noise readout mode core.set_property('Camera', 'Gain', '2-CMS') time.sleep(1) # set camera to trigger first mode # TO DO: photometrics claims this setting doesn't exist in PVCAM. Why is it necessary then? core.set_property('Camera', 'Trigger Timeout (secs)', 300) time.sleep(1) # set camera to internal trigger core.set_property('Camera', 'TriggerMode', 'Internal Trigger') time.sleep(1) # change core timeout for long stage moves core.set_property('Core', 'TimeoutMs', 100000) # crop FOV #core.set_roi(*ROI) # set exposure core.set_exposure(exposure_ms) # grab one image to determine actual framerate # get actual framerate from micromanager properties actual_readout_ms = float(core.get_property( 'Camera', 'ActualInterval-ms')) #unit: ms # camera pixel size pixel_size_um = .115 # unit: um # scan axis setup scan_axis_step_um = 0.4 # unit: um scan_axis_step_mm = scan_axis_step_um / 1000. #unit: mm scan_axis_start_mm = scan_axis_start_um / 1000. #unit: mm scan_axis_end_mm = scan_axis_end_um / 1000. #unit: mm scan_axis_range_um = np.abs(scan_axis_end_um - scan_axis_start_um) # unit: um scan_axis_range_mm = scan_axis_range_um / 1000 #unit: mm actual_exposure_s = actual_readout_ms / 1000. #unit: s scan_axis_speed = np.round(scan_axis_step_mm / actual_exposure_s, 2) #unit: mm/s scan_axis_positions = np.rint(scan_axis_range_mm / scan_axis_step_mm).astype( int) #unit: number of positions # tile axis setup tile_axis_overlap = 0.2 #unit: percentage tile_axis_range_um = np.abs(tile_axis_end_um - tile_axis_start_um) #unit: um tile_axis_range_mm = tile_axis_range_um / 1000 #unit: mm tile_axis_ROI = ROI[2] * pixel_size_um #unit: um tile_axis_step_um = np.round((tile_axis_ROI) * (1 - tile_axis_overlap), 2) #unit: um tile_axis_step_mm = tile_axis_step_um / 1000 #unit: mm tile_axis_positions = np.rint(tile_axis_range_mm / tile_axis_step_mm).astype( int) #unit: number of positions # if tile_axis_positions rounded to zero, make sure we acquire at least one position if tile_axis_positions == 0: tile_axis_positions = 1 # height axis setup # this is more complicated, since we have an oblique light sheet # the height of the scan is the length of the ROI in the tilted direction * sin(tilt angle) height_axis_overlap = 0.2 #unit: percentage height_axis_range_um = np.abs(height_axis_end_um - height_axis_start_um) #unit: um height_axis_range_mm = height_axis_range_um / 1000 #unit: mm height_axis_ROI = ROI[3] * pixel_size_um * np.sin( 30 * (np.pi / 180.)) #unit: um height_axis_step_um = np.round( (height_axis_ROI) * (1 - height_axis_overlap), 2) #unit: um height_axis_step_mm = height_axis_step_um / 1000 #unit: mm height_axis_positions = np.rint(height_axis_range_mm / height_axis_step_mm).astype( int) #unit: number of positions # if height_axis_positions rounded to zero, make sure we acquire at least one position if height_axis_positions == 0: height_axis_positions = 1 # get handle to xy and z stages xy_stage = core.get_xy_stage_device() z_stage = core.get_focus_device() # Setup PLC card to give start trigger plcName = 'PLogic:E:36' propPosition = 'PointerPosition' propCellConfig = 'EditCellConfig' #addrOutputBNC3 = 35 addrOutputBNC1 = 33 addrStageSync = 46 # TTL5 on Tiger backplane = stage sync signal # connect stage sync signal to BNC output core.set_property(plcName, propPosition, addrOutputBNC1) core.set_property(plcName, propCellConfig, addrStageSync) # turn on 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No') # set tile axis speed for all moves command = 'SPEED Y=.1' core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # set scan axis speed for large move to initial position command = 'SPEED X=.1' core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # turn off 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes') # move scan scan stage to initial position core.set_xy_position(scan_axis_start_um, tile_axis_start_um) core.wait_for_device(xy_stage) core.set_position(height_axis_start_um) core.wait_for_device(z_stage) # turn on 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No') # set scan axis speed to correct speed for continuous stage scan # expects mm/s command = 'SPEED X=' + str(scan_axis_speed) core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # set scan axis to true 1D scan with no backlash command = '1SCAN X? Y=0 Z=9 F=0' core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # set range and return speed (10% of max) for scan axis # expects mm command = '1SCANR X=' + str(scan_axis_start_mm) + ' Y=' + str( scan_axis_end_mm) + ' R=10' core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # turn off 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes') # construct boolean array for lasers to use channel_states = [state_405, state_488, state_561, state_635, state_730] channel_powers = [power_405, power_488, power_561, power_635, power_730] # set lasers to user defined power core.set_property('Coherent-Scientific Remote', 'Laser 405-100C - PowerSetpoint (%)', channel_powers[0]) core.set_property('Coherent-Scientific Remote', 'Laser 488-150C - PowerSetpoint (%)', channel_powers[1]) core.set_property('Coherent-Scientific Remote', 'Laser OBIS LS 561-150 - PowerSetpoint (%)', channel_powers[2]) core.set_property('Coherent-Scientific Remote', 'Laser 637-140C - PowerSetpoint (%)', channel_powers[3]) core.set_property('Coherent-Scientific Remote', 'Laser 730-30C - PowerSetpoint (%)', channel_powers[4]) # calculate total tiles total_tiles = tile_axis_positions * height_axis_positions # output acquisition metadata print('Number of X positions: ' + str(scan_axis_positions)) print('Number of Y tiles: ' + str(tile_axis_positions)) print('Number of Z slabs: ' + str(height_axis_positions)) print('Number of channels:' + str(np.sum(channel_states))) print('Number of BDV H5 tiles: ' + str(total_tiles)) # define unit tranformation matrix unit_matrix = np.array(( (1.0, 0.0, 0.0, 0.0), # change the 4. value for x_translation (px) (0.0, 1.0, 0.0, 0.0), # change the 4. value for y_translation (px) (0.0, 0.0, 1.0, 0.0))) # change the 4. value for z_translation (px) # create BDV H5 using npy2bdv fname = save_directory / save_name bdv_writer = npy2bdv.BdvWriter(fname, nchannels=np.sum(channel_states), ntiles=total_tiles, subsamp=((1, 1, 1), ), blockdim=((1, 128, 256), )) # reset tile index for BDV H5 file tile_index = 0 for y in range(tile_axis_positions): # calculate tile axis position tile_position_um = tile_axis_start_um + (tile_axis_step_um * y) # move XY stage to new tile axis position core.set_xy_position(scan_axis_start_um, tile_position_um) core.wait_for_device(xy_stage) for z in range(height_axis_positions): print('Tile index: ' + str(tile_index)) # calculate height axis position height_position_um = height_axis_start_um + (height_axis_step_um * z) # move Z stage to new height axis position core.set_position(height_position_um) core.wait_for_device(z_stage) # reset channel index for BDV H5 file channel_index = 0 for c in range(len(channel_states)): # determine active channel if channel_states[c] == 1: if (c == 0): core.set_config('Coherent-State', '405nm') core.wait_for_config('Coherent-State', '405nm') elif (c == 1): core.set_config('Coherent-State', '488nm') core.wait_for_config('Coherent-State', '488nm') elif (c == 2): core.set_config('Coherent-State', '561nm') core.wait_for_config('Coherent-State', '561nm') elif (c == 3): core.set_config('Coherent-State', '637nm') core.wait_for_config('Coherent-State', '637nm') elif (c == 4): core.set_config('Coherent-State', '730nm') core.wait_for_config('Coherent-State', '730nm') print('Channel index: ' + str(channel_index)) print('Active channel: ' + str(c)) # set camera to trigger first mode for stage synchronization core.set_property('Camera', 'TriggerMode', 'Trigger first') time.sleep(1) # get current X, Y, and Z stage positions for translation transformation point = core.get_xy_stage_position() x_now = point.get_x() y_now = point.get_y() z_now = core.get_position(z_stage) # calculate affine matrix components for translation transformation affine_matrix = unit_matrix affine_matrix[ 0, 3] = y_now / pixel_size_um # x axis in BDV H5 (tile axis on scope). affine_matrix[1, 3] = z_now / ( pixel_size_um * np.sin(30. * np.pi / 180.) ) # y axis in BDV H5 (height axis on scope). affine_matrix[2, 3] = x_now / ( pixel_size_um * np.cos(30. * np.pi / 180.) ) # z axis in BDV H5 (scan axis on scope). # turn off 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No') # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # turn off 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes') # start acquistion core.start_sequence_acquisition(int(scan_axis_positions), float(0.0), True) # tell stage to execute scan command = '1SCAN' core.set_property('TigerCommHub', 'SerialCommand', command) # reset image counter image_counter = 0 # place stack into BDV H5 bdv_writer.append_view( stack=None, virtual_stack_dim=(scan_axis_positions, ROI[3], ROI[2]), time=0, channel=channel_index, tile=tile_index, m_affine=affine_matrix, name_affine='stage translation', voxel_size_xyz=(.115, .115, .200), voxel_units='um') # grab images from buffer while (image_counter < scan_axis_positions): # if there are images in the buffer, grab and process if (core.get_remaining_image_count() > 0): # grab top image in buffer tagged_image = core.pop_next_tagged_image() # grab metadata to convert 1D array to 2D image image_height = tagged_image.tags['Height'] image_width = tagged_image.tags['Width'] # convert to 2D image and place into virtual stack in BDV H5 bdv_writer.append_plane(plane=np.flipud( tagged_image.pix.reshape( (image_height, image_width))), plane_index=image_counter, time=0, channel=channel_index) # increment image counter image_counter = image_counter + 1 # no images in buffer, wait for another image to arrive. else: time.sleep(np.minimum(.01 * exposure_ms, 1) / 1000) # clean up acquistion core.stop_sequence_acquisition() # turn off lasers core.set_config('Coherent-State', 'off') core.wait_for_config('Coherent-State', 'off') # set camera to internal trigger # this is necessary to avoid PVCAM driver issues that we keep having for long acquisitions. core.set_property('Camera', 'TriggerMode', 'Internal Trigger') time.sleep(1) # increment channel index for BDV H5 file channel_index = channel_index + 1 # turn off 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No') # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # turn off 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes') # increment tile index for BDV H5 tile_index = tile_index + 1 # write BDV XML and close BDV H5 bdv_writer.write_xml_file(ntimes=1) bdv_writer.close()
from skimage import morphology from shared.analysis import central_pixel_without_cells, bleach_location from shared.find_blobs import select # variables from shared.find_organelles import find_organelle nr = 40 nr_between_projector_checks = 2 cal_exposure = 200 cal_offset = 5 n_curve = 500 # build up pycromanager bridge bridge = Bridge() mmc = bridge.get_core() mm = bridge.get_studio() projector = bridge.construct_java_object( "org.micromanager.projector.ProjectorAPI") projector_device = projector.get_projection_device() def snap_and_get_bleach_location(exposure, cutoff): """ Takes an image with the current settings. Finds a location close to the center where there are no objects (as defined in function central_picel_without_cells). If no such location is found, returns -1. Targets bleacher to this location, exposes and takes an image of that exposure. Finds the center of the actual bleach spot. When the square of the distance between the intended target and the actual bleach spot is greater than provided offset, will execute a full calibration. :param exposure: exposure time to use for bleaching
""" https://pycro-manager.readthedocs.io/en/latest/core.html This example shows how to use pycromanager to interact with the micro-manager core. Aside from the setup section, each following section can be run independently """ from pycromanager import Bridge import numpy as np import matplotlib.pyplot as plt #### Setup #### with Bridge() as bridge: #get object representing micro-manager core core = bridge.get_core() #### Calling core functions ### exposure = core.get_exposure() #### Setting and getting properties #### #Here we set a property of the core itself, but same code works for device properties auto_shutter = core.get_property('Core', 'AutoShutter') core.set_property('Core', 'AutoShutter', 0) #### Acquiring images #### #The micro-manager core exposes several mechanisms foor acquiring images. In order to #not interfere with other pycromanager functionality, this is the one that should be used core.snap_image() tagged_image = core.get_tagged_image() #If using micro-manager multi-camera adapter, use core.getTaggedImage(i), where i is #the camera index
from pycromanager import Bridge, Acquisition import numpy as np bridge = Bridge() # get object representing micro-magellan API magellan = bridge.get_magellan() def hook_fn(event): coordinates = np.array([event["x"], event["y"], event["z"]]) return event if __name__ == "__main__": # magellan example acq = Acquisition(magellan_acq_index=0, post_hardware_hook_fn=hook_fn) acq.await_completion() pass
from pycromanager import Acquisition, multi_d_acquisition_events, Bridge, start_headless import time mm_app_path = '/Applications/Micro-Manager-2.0.0-gamma1' # mm_app_path = 'C:/Program Files/Micro-Manager-2.0gamma' config_file = mm_app_path + "/MMConfig_demo.cfg" #Optional: specify your own version of java to run with java_loc = "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java" # java_loc = None start_headless(mm_app_path, config_file, java_loc=java_loc, port=5000) with Bridge(port=5000) as b: b.get_core().snap_image() print(b.get_core().get_image()) save_dir = "/Users/henrypinkard/tmp" # save_dir = "C:/Users/Henry Pinkard/Desktop/datadump" with Acquisition(directory=save_dir, name="tcz_acq", port=5000) as acq: # Generate the events for a single z-stack events = multi_d_acquisition_events( num_time_points=5, time_interval_s=0, channel_group="Channel", channels=["DAPI", "FITC"], z_start=0, z_end=6, z_step=0.4, order="tcz",
def main(): #------------------------------------------------------------------------------------------------------------------------------------ #----------------------------------------------Begin setup of scan parameters-------------------------------------------------------- #------------------------------------------------------------------------------------------------------------------------------------ # lasers to use # 0 -> inactive # 1 -> active state_405 = 1 state_488 = 0 state_561 = 0 state_635 = 1 state_730 = 0 # laser powers (0 -> 100%) power_405 = 10 power_488 = 0 power_561 = 0 power_635 = 5 power_730 = 0 # exposure time exposure_ms = 5. # scan axis limits. Use stage positions reported by MM scan_axis_start_um = 6000. #unit: um scan_axis_end_um = 16000. #unit: um # tile axis limits. Use stage positions reported by MM tile_axis_start_um = -1300 #unit: um tile_axis_end_um = -1350. #unit: um # height axis limits. Use stage positions reported by MM height_axis_start_um = 320. #unit: um height_axis_end_um = 360. #unit: um # FOV parameters # ONLY MODIFY IF NECESSARY ROI = [0, 1024, 1599, 255] #unit: pixels # setup file name save_directory = Path('E:/20201211/') save_name = 'shaffer_lung' #------------------------------------------------------------------------------------------------------------------------------------ #----------------------------------------------End setup of scan parameters---------------------------------------------------------- #------------------------------------------------------------------------------------------------------------------------------------ bridge = Bridge() core = bridge.get_core() # turn off lasers core.set_config('Coherent-State', 'off') core.wait_for_config('Coherent-State', 'off') # set camera into 16bit readout mode # give camera time to change modes if necessary core.set_property('Camera', 'ReadoutRate', '100MHz 16bit') time.sleep(1) # set camera into low noise readout mode # give camera time to change modes if necessary core.set_property('Camera', 'Gain', '2-CMS') time.sleep(1) # set camera to trigger first mode # give camera time to change modes if necessary core.set_property('Camera', 'Trigger Timeout (secs)', 300) time.sleep(1) # set camera to internal trigger # give camera time to change modes if necessary core.set_property('Camera', 'TriggerMode', 'Internal Trigger') time.sleep(1) # change core timeout for long stage moves time.sleep(1) # crop FOV #core.set_roi(*ROI) # set exposure core.set_exposure(exposure_ms) # get actual framerate from micromanager properties # TO DO: fix need for user to have manually run an exposure with correct crop to get this value actual_readout_ms = float(core.get_property( 'Camera', 'ActualInterval-ms')) #unit: ms # camera pixel size pixel_size_um = .115 # unit: um # scan axis setup scan_axis_step_um = 0.2 # unit: um scan_axis_step_mm = scan_axis_step_um / 1000. #unit: mm scan_axis_start_mm = scan_axis_start_um / 1000. #unit: mm scan_axis_end_mm = scan_axis_end_um / 1000. #unit: mm scan_axis_range_um = np.abs(scan_axis_end_um - scan_axis_start_um) # unit: um scan_axis_range_mm = scan_axis_range_um / 1000 #unit: mm actual_exposure_s = actual_readout_ms / 1000. #unit: s scan_axis_speed = np.round(scan_axis_step_mm / actual_exposure_s, 2) #unit: mm/s scan_axis_positions = np.rint(scan_axis_range_mm / scan_axis_step_mm).astype( int) #unit: number of positions # tile axis setup tile_axis_overlap = 0.2 #unit: percentage tile_axis_range_um = np.abs(tile_axis_end_um - tile_axis_start_um) #unit: um tile_axis_range_mm = tile_axis_range_um / 1000 #unit: mm tile_axis_ROI = ROI[2] * pixel_size_um #unit: um tile_axis_step_um = np.round((tile_axis_ROI) * (1 - tile_axis_overlap), 2) #unit: um tile_axis_step_mm = tile_axis_step_um / 1000 #unit: mm tile_axis_positions = np.rint(tile_axis_range_mm / tile_axis_step_mm).astype( int) #unit: number of positions # if tile_axis_positions rounded to zero, make sure we acquire at least one position if tile_axis_positions == 0: tile_axis_positions = 1 # height axis setup height_axis_overlap = 0.2 #unit: percentage height_axis_range_um = np.abs(height_axis_end_um - height_axis_start_um) #unit: um height_axis_range_mm = height_axis_range_um / 1000 #unit: mm #height_axis_ROI = ROI[3]*pixel_size_um*np.sin(30*(np.pi/180.)) #unit: um TO DO: Why is overlap so large when using oblique pixel height?? height_axis_ROI = ROI[3] * pixel_size_um #unit: um height_axis_step_um = np.round( (height_axis_ROI) * (1 - height_axis_overlap), 2) #unit: um height_axis_step_mm = height_axis_step_um / 1000 #unit: mm height_axis_positions = np.rint(height_axis_range_mm / height_axis_step_mm).astype( int) #unit: number of positions # if height_axis_positions rounded to zero, make sure we acquire at least one position if height_axis_positions == 0: height_axis_positions = 1 # get handle to xy and z stages xy_stage = core.get_xy_stage_device() z_stage = core.get_focus_device() # Setup Tiger controller to pass signal when the scan stage cross the start position to the PLC plcName = 'PLogic:E:36' propPosition = 'PointerPosition' propCellConfig = 'EditCellConfig' #addrOutputBNC3 = 35 # BNC3 on the PLC front panel addrOutputBNC1 = 33 # BNC1 on the PLC front panel addrStageSync = 46 # TTL5 on Tiger backplane = stage sync signal # connect stage sync signal to BNC output core.set_property(plcName, propPosition, addrOutputBNC1) core.set_property(plcName, propCellConfig, addrStageSync) # turn on 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No') # set tile axis speed for all moves command = 'SPEED Y=.1' core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # set scan axis speed for large move to initial position command = 'SPEED X=.1' core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # turn off 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes') # move scan scan stage to initial position core.set_xy_position(scan_axis_start_um, tile_axis_start_um) core.wait_for_device(xy_stage) core.set_position(height_axis_start_um) core.wait_for_device(z_stage) # turn on 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No') # set scan axis speed to correct speed for continuous stage scan # expects mm/s command = 'SPEED X=' + str(scan_axis_speed) core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # set scan axis to true 1D scan with no backlash command = '1SCAN X? Y=0 Z=9 F=0' core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # set range and return speed (5% of max) for scan axis # expects mm command = '1SCANR X=' + str(scan_axis_start_mm) + ' Y=' + str( scan_axis_end_mm) + ' R=10' core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # turn off 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes') # construct boolean array for lasers to use channel_states = [state_405, state_488, state_561, state_635, state_730] channel_powers = [power_405, power_488, power_561, power_635, power_730] # set lasers to user defined power core.set_property('Coherent-Scientific Remote', 'Laser 405-100C - PowerSetpoint (%)', channel_powers[0]) core.set_property('Coherent-Scientific Remote', 'Laser 488-150C - PowerSetpoint (%)', channel_powers[1]) core.set_property('Coherent-Scientific Remote', 'Laser OBIS LS 561-150 - PowerSetpoint (%)', channel_powers[2]) core.set_property('Coherent-Scientific Remote', 'Laser 637-140C - PowerSetpoint (%)', channel_powers[3]) core.set_property('Coherent-Scientific Remote', 'Laser 730-30C - PowerSetpoint (%)', channel_powers[4]) print('Number of X positions: ' + str(scan_axis_positions)) print('Number of Y tiles: ' + str(tile_axis_positions)) print('Number of Z slabs: ' + str(height_axis_positions)) #time.sleep(10) for y in range(tile_axis_positions): # calculate tile axis position tile_position_um = tile_axis_start_um + (tile_axis_step_um * y) # move XY stage to new tile axis position core.set_xy_position(scan_axis_start_um, tile_position_um) core.wait_for_device(xy_stage) for z in range(height_axis_positions): # calculate height axis position height_position_um = height_axis_start_um + (height_axis_step_um * z) # move Z stage to new height axis position core.set_position(height_position_um) core.wait_for_device(z_stage) # create events to execute scan across this z plane events = [] for c in range(len(channel_states)): for x in range( scan_axis_positions + 10 ): #TO DO: Fix need for extra frames in ASI setup, not here. if channel_states[c] == 1: if (c == 0): evt = { 'axes': { 'z': x }, 'channel': { 'group': 'Coherent-State', 'config': '405nm' } } elif (c == 1): evt = { 'axes': { 'z': x }, 'channel': { 'group': 'Coherent-State', 'config': '488nm' } } elif (c == 2): evt = { 'axes': { 'z': x }, 'channel': { 'group': 'Coherent-State', 'config': '561nm' } } elif (c == 3): evt = { 'axes': { 'z': x }, 'channel': { 'group': 'Coherent-State', 'config': '637nm' } } elif (c == 4): evt = { 'axes': { 'z': x }, 'channel': { 'group': 'Coherent-State', 'config': '730nm' } } events.append(evt) # set camera to trigger first mode for stage synchronization # give camera time to change modes core.set_property('Camera', 'TriggerMode', 'Trigger first') time.sleep(1) # update save_name with current Z plane save_name_z = save_name + '_y' + str(y).zfill(4) + '_z' + str( z).zfill(4) # run acquisition at this Z plane with Acquisition(directory=save_directory, name=save_name_z, post_hardware_hook_fn=post_hook_fn, post_camera_hook_fn=camera_hook_fn, show_display=False, max_multi_res_index=0) as acq: acq.acquire(events) # added this code in an attempt to clean up resources, given the ZMQ error we are getting when using two hooks acq.acquire(None) acq.await_completion() # try to clean up acquisition so that AcqEngJ releases directory. This way we can move it to the network storage # in the background. acq = None # turn off lasers core.set_config('Coherent-State', 'off') core.wait_for_config('Coherent-State', 'off') # set camera to internal trigger # this is necessary to avoid PVCAM driver issues that we keep having for long acquisitions. # give camera time to change modes core.set_property('Camera', 'TriggerMode', 'Internal Trigger') time.sleep(1)
def main(): #------------------------------------------------------------------------------------------------------------------------------------ #----------------------------------------------Begin setup of scan parameters-------------------------------------------------------- #------------------------------------------------------------------------------------------------------------------------------------ # set up lasers channel_labels = ["405", "488", "561", "635", "730"] channel_states = [False, False, True, False, False] # true -> active, false -> inactive channel_powers = [30, 30, 100, 100, 0] # (0 -> 100%) do_ind = [0, 1, 2, 3, 4] # digital output line corresponding to each channel # parse which channels are active active_channel_indices = [ ind for ind, st in zip(do_ind, channel_states) if st ] n_active_channels = len(active_channel_indices) print("%d active channels: " % n_active_channels, end="") for ind in active_channel_indices: print("%s " % channel_labels[ind], end="") print("") # exposure time exposure_ms = 2.0 #unit: ms # scan axis range scan_axis_range_um = 20.0 # unit: microns # galvo voltage at neutral #galvo_neutral_volt = 0 # unit: volts galvo_neutral_volt = -.150 scan_axis_step_um = 0.4 # unit: um # timepoints timepoints = 400 # timepoint interval (s) timing_interval = 0 # setup file name save_directory = Path('D:/20211204') save_name = 'fla-suc40' # automatically transfer files to NAS at end of dataset transfer_files = False # display data display_flag = False #------------------------------------------------------------------------------------------------------------------------------------ #----------------------------------------------End setup of scan parameters---------------------------------------------------------- #------------------------------------------------------------------------------------------------------------------------------------ with Bridge() as bridge: core = bridge.get_core() # give camera time to change modes if necessary core.set_config('Camera-Setup', 'ScanMode3') core.wait_for_config('Camera-Setup', 'ScanMode3') # set camera to internal trigger core.set_config('Camera-TriggerSource', 'INTERNAL') core.wait_for_config('Camera-TriggerSource', 'INTERNAL') # set camera to internal trigger # give camera time to change modes if necessary core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER KIND[0]', 'EXPOSURE') core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER KIND[1]', 'EXPOSURE') core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER KIND[2]', 'EXPOSURE') core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER POLARITY[0]', 'POSITIVE') core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER POLARITY[1]', 'POSITIVE') core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER POLARITY[2]', 'POSITIVE') # set exposure time core.set_exposure(exposure_ms) # determine image size core.snap_image() y_pixels = core.get_image_height() x_pixels = core.get_image_width() # turn all lasers on core.set_config('Laser', 'Off') core.wait_for_config('Laser', 'Off') # set all laser to external triggering core.set_config('Modulation-405', 'External-Digital') core.wait_for_config('Modulation-405', 'External-Digital') core.set_config('Modulation-488', 'External-Digital') core.wait_for_config('Modulation-488', 'External-Digital') core.set_config('Modulation-561', 'External-Digital') core.wait_for_config('Modulation-561', 'External-Digital') core.set_config('Modulation-637', 'External-Digital') core.wait_for_config('Modulation-637', 'External-Digital') core.set_config('Modulation-730', 'External-Digital') core.wait_for_config('Modulation-730', 'External-Digital') # turn all lasers on core.set_config('Laser', 'AllOn') core.wait_for_config('Laser', 'AllOn') core.set_property('Coherent-Scientific Remote', 'Laser 405-100C - PowerSetpoint (%)', channel_powers[0]) core.set_property('Coherent-Scientific Remote', 'Laser 488-150C - PowerSetpoint (%)', channel_powers[1]) core.set_property('Coherent-Scientific Remote', 'Laser OBIS LS 561-150 - PowerSetpoint (%)', channel_powers[2]) core.set_property('Coherent-Scientific Remote', 'Laser 637-140C - PowerSetpoint (%)', channel_powers[3]) core.set_property('Coherent-Scientific Remote', 'Laser 730-30C - PowerSetpoint (%)', channel_powers[4]) # camera pixel size pixel_size_um = .115 # unit: um # galvo scan setup scan_axis_calibration = 0.043 # unit: V / um min_volt = -(scan_axis_range_um * scan_axis_calibration / 2.) + galvo_neutral_volt # unit: volts scan_axis_step_volts = scan_axis_step_um * scan_axis_calibration # unit: V scan_axis_range_volts = scan_axis_range_um * scan_axis_calibration # unit: V scan_steps = np.rint(scan_axis_range_volts / scan_axis_step_volts).astype( np.int16) # galvo steps # handle case where no scan steps if scan_steps == 0: scan_steps = 1 # output experiment info print( "Scan axis range: %.1f um = %0.3fV, Scan axis step: %.1f nm = %0.3fV , Number of galvo positions: %d" % (scan_axis_range_um, scan_axis_range_volts, scan_axis_step_um * 1000, scan_axis_step_volts, scan_steps)) print('Galvo neutral (Volt): ' + str(galvo_neutral_volt) + ', Min voltage (volt): ' + str(min_volt)) print('Time points: ' + str(timepoints)) # create events to execute scan events = [] # Changes to event structure motivated by Henry's notes that pycromanager struggles to read "non-standard" axes. # https://github.com/micro-manager/pycro-manager/issues/220 for t in range(timepoints): for x in range(scan_steps): ch_idx = 0 for c in range(len(do_ind)): if channel_states[c]: if timing_interval == 0: evt = {'axes': {'t': t, 'z': x, 'c': ch_idx}} else: evt = { 'axes': { 't': t, 'z': x, 'c': ch_idx }, 'min_start_time': t * timing_interval } ch_idx = ch_idx + 1 events.append(evt) print("Generated %d events" % len(events)) # setup DAQ nvoltage_steps = scan_steps # 2 time steps per frame, except for first frame plus one final frame to reset voltage #samples_per_ch = (nvoltage_steps * 2 - 1) + 1 samples_per_ch = (nvoltage_steps * 2 * n_active_channels - 1) + 1 DAQ_sample_rate_Hz = 10000 #retriggerable = True num_DI_channels = 8 # Generate values for DO dataDO = np.zeros((samples_per_ch, num_DI_channels), dtype=np.uint8) for ii, ind in enumerate(active_channel_indices): dataDO[2 * ii::2 * n_active_channels, ind] = 1 dataDO[-1, :] = 0 # generate voltage steps max_volt = min_volt + scan_axis_range_volts # 2 voltage_values = np.linspace(min_volt, max_volt, nvoltage_steps) # Generate values for AO waveform = np.zeros(samples_per_ch) # one less voltage value for first frame waveform[0:2 * n_active_channels - 1] = voltage_values[0] if len(voltage_values) > 1: # (2 * # active channels) voltage values for all other frames waveform[2 * n_active_channels - 1:-1] = np.kron( voltage_values[1:], np.ones(2 * n_active_channels)) # set back to initial value at end waveform[-1] = voltage_values[0] #def read_di_hook(event): try: # ----- DIGITAL input ------- taskDI = daq.Task() taskDI.CreateDIChan("/Dev1/PFI0", "", daq.DAQmx_Val_ChanForAllLines) ## Configure change detectin timing (from wave generator) taskDI.CfgInputBuffer( 0) # must be enforced for change-detection timing, i.e no buffer taskDI.CfgChangeDetectionTiming("/Dev1/PFI0", "/Dev1/PFI0", daq.DAQmx_Val_ContSamps, 0) ## Set where the starting trigger taskDI.CfgDigEdgeStartTrig("/Dev1/PFI0", daq.DAQmx_Val_Rising) ## Export DI signal to unused PFI pins, for clock and start taskDI.ExportSignal(daq.DAQmx_Val_ChangeDetectionEvent, "/Dev1/PFI2") taskDI.ExportSignal(daq.DAQmx_Val_StartTrigger, "/Dev1/PFI1") # ----- DIGITAL output ------ taskDO = daq.Task() # TO DO: Write each laser line separately! taskDO.CreateDOChan("/Dev1/port0/line0:7", "", daq.DAQmx_Val_ChanForAllLines) ## Configure timing (from DI task) taskDO.CfgSampClkTiming("/Dev1/PFI2", DAQ_sample_rate_Hz, daq.DAQmx_Val_Rising, daq.DAQmx_Val_ContSamps, samples_per_ch) ## Write the output waveform samples_per_ch_ct_digital = ct.c_int32() taskDO.WriteDigitalLines(samples_per_ch, False, 10.0, daq.DAQmx_Val_GroupByChannel, dataDO, ct.byref(samples_per_ch_ct_digital), None) # ------- ANALOG output ----------- # first, set the galvo to the initial point if it is not already taskAO_first = daq.Task() taskAO_first.CreateAOVoltageChan("/Dev1/ao0", "", -6.0, 6.0, daq.DAQmx_Val_Volts, None) taskAO_first.WriteAnalogScalarF64(True, -1, waveform[0], None) taskAO_first.StopTask() taskAO_first.ClearTask() # now set up the task to ramp the galvo taskAO = daq.Task() taskAO.CreateAOVoltageChan("/Dev1/ao0", "", -6.0, 6.0, daq.DAQmx_Val_Volts, None) ## Configure timing (from DI task) taskAO.CfgSampClkTiming("/Dev1/PFI2", DAQ_sample_rate_Hz, daq.DAQmx_Val_Rising, daq.DAQmx_Val_ContSamps, samples_per_ch) ## Write the output waveform samples_per_ch_ct = ct.c_int32() taskAO.WriteAnalogF64(samples_per_ch, False, 10.0, daq.DAQmx_Val_GroupByScanNumber, waveform, ct.byref(samples_per_ch_ct), None) ## ------ Start both tasks ---------- taskAO.StartTask() taskDO.StartTask() taskDI.StartTask() except daq.DAQError as err: print("DAQmx Error %s" % err) # run acquisition with Acquisition(directory=save_directory, name=save_name, show_display=display_flag, max_multi_res_index=0, saving_queue_size=5000) as acq: acq.acquire(events) acq = None # stop DAQ try: ## Stop and clear both tasks taskDI.StopTask() taskDO.StopTask() taskAO.StopTask() taskDI.ClearTask() taskAO.ClearTask() taskDO.ClearTask() except daq.DAQError as err: print("DAQmx Error %s" % err) # save galvo scan parameters scan_param_data = [{ 'root_name': str(save_name), 'scan_type': 'galvo', 'theta': 30.0, 'exposure_ms': exposure_ms, 'scan_step': scan_axis_step_um * 1000., 'pixel_size': pixel_size_um * 1000., 'galvo_scan_range_um': scan_axis_range_um, 'galvo_volts_per_um': scan_axis_calibration, 'num_t': int(timepoints), 'num_y': 1, # might need to change this eventually 'num_z': 1, # might need to change this eventually 'num_ch': int(n_active_channels), 'scan_axis_positions': int(scan_steps), 'y_pixels': y_pixels, 'x_pixels': x_pixels, '405_active': channel_states[0], '488_active': channel_states[1], '561_active': channel_states[2], '635_active': channel_states[3], '730_active': channel_states[4] }] data_io.write_metadata(scan_param_data[0], save_directory / 'scan_metadata.csv') with Bridge() as bridge: core = bridge.get_core() # turn all lasers off core.set_config('Laser', 'Off') core.wait_for_config('Laser', 'Off') # set all lasers back to software control core.set_config('Modulation-405', 'CW (constant power)') core.wait_for_config('Modulation-405', 'CW (constant power)') core.set_config('Modulation-488', 'CW (constant power)') core.wait_for_config('Modulation-488', 'CW (constant power)') core.set_config('Modulation-561', 'CW (constant power)') core.wait_for_config('Modulation-561', 'CW (constant power)') core.set_config('Modulation-637', 'CW (constant power)') core.wait_for_config('Modulation-637', 'CW (constant power)') core.set_config('Modulation-730', 'CW (constant power)') core.wait_for_config('Modulation-730', 'CW (constant power)') # set all laser to zero power channel_powers = [0, 0, 0, 0, 0] core.set_property('Coherent-Scientific Remote', 'Laser 405-100C - PowerSetpoint (%)', channel_powers[0]) core.set_property('Coherent-Scientific Remote', 'Laser 488-150C - PowerSetpoint (%)', channel_powers[1]) core.set_property('Coherent-Scientific Remote', 'Laser OBIS LS 561-150 - PowerSetpoint (%)', channel_powers[2]) core.set_property('Coherent-Scientific Remote', 'Laser 637-140C - PowerSetpoint (%)', channel_powers[3]) core.set_property('Coherent-Scientific Remote', 'Laser 730-30C - PowerSetpoint (%)', channel_powers[4]) # put the galvo back to neutral # first, set the galvo to the initial point if it is not already taskAO_last = daq.Task() taskAO_last.CreateAOVoltageChan("/Dev1/ao0", "", -6.0, 6.0, daq.DAQmx_Val_Volts, None) taskAO_last.WriteAnalogScalarF64(True, -1, galvo_neutral_volt, None) taskAO_last.StopTask() taskAO_last.ClearTask() if transfer_files: # make parent directory on NAS and start reconstruction script on the server # make home directory on NAS save_directory_path = Path(save_directory) remote_directory = Path('y:/') / Path(save_directory_path.parts[1]) cmd = 'mkdir ' + str(remote_directory) status_mkdir = subprocess.run(cmd, shell=True) # copy full experiment metadata to NAS src = Path(save_directory) / Path('scan_metadata.csv') dst = Path(remote_directory) / Path('scan_metadata.csv') Thread(target=shutil.copy, args=[str(src), str(dst)]).start() # copy data to NAS save_directory_path = Path(save_directory) remote_directory = Path('y:/') / Path(save_directory_path.parts[1]) src = Path(save_directory) / Path(save_name + '_1') dst = Path(remote_directory) / Path(save_name + '_1') Thread(target=shutil.copytree, args=[str(src), str(dst)]).start()
from pycromanager import Acquisition, multi_d_acquisition_events, Bridge, start_headless mm_app_path = '/Applications/Micro-Manager-2.0.0-gamma1' # mm_app_path = 'C:/Program Files/Micro-Manager-2.0gamma' config_file = mm_app_path + "/MMConfig_demo.cfg" #Optional: specify your own version of java to run with java_loc = "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java" # java_loc = None start_headless(mm_app_path, config_file, java_loc=java_loc) b = Bridge() b.get_core().snap_image() print(b.get_core().get_image()) save_dir = "/Users/henrypinkard/tmp" # save_dir = "C:/Users/Henry Pinkard/Desktop/datadump" with Acquisition(directory=save_dir, name="tcz_acq", debug=True) as acq: # Generate the events for a single z-stack events = multi_d_acquisition_events( num_time_points=5, time_interval_s=0, channel_group="Channel", channels=["DAPI", "FITC"], z_start=0, z_end=6, z_step=0.4, order="tcz", )
def main(): bridge = Bridge() core = bridge.get_core() # FOV parameters ROI = [1024, 0, 256, 1024] #unit: pixels # camera exposure exposure_ms = 5 #unit: ms # set to high-res camera core.set_config('Camera', 'HighRes') # crop FOV core.set_roi(*ROI) # set exposure core.set_exposure(exposure_ms) # setup file name save_directory = Path('C:/data/test/') save_name = 'test_stages' # get handle to xy and z stages xy_stage = core.get_xy_stage_device() z_stage = core.get_focus_device() # move the stages to verify core can talk to them # positions chosen at random core.set_xy_position(100., 100.) core.wait_for_device(xy_stage) core.set_position(50.) core.wait_for_device(z_stage) # create events to hold all of the scan axis images during constant speed stage scan channel_configs = ['DAPI', 'FITC', 'Rhodamine', 'Cy5'] events = [] for y in range(2): for z in range(2): for c in range(len(channel_configs)): for x in range(2): evt = { 'axes': { 'x': x, 'y': y, 'z': z }, 'x': 100, 'y': y * 1000, 'z': z * 100, 'channel': { 'group': 'Channel', 'config': channel_configs[c] } } events.append(evt) # run acquisition # TO DO: properly handle an error here if camera driver fails to return expected number of images. with Acquisition(directory=save_directory, name=save_name, post_hardware_hook_fn=setup_scan_fn, post_camera_hook_fn=hook_fn, show_display=False, max_multi_res_index=0, debug=False) as acq: acq.acquire(events) acq.acquire(None) acq.await_completion()
layer_names = ['GFP', 'RFP'] # initialize global variables # flag to break while loops acq_running = False # empty queue for image data and z positions img_queue = queue.Queue() # xyz data stack data = np.random.rand(z_range[2], clip[0], clip[1]) * clim[1] # if z-stage is controlled through micromanager: # need bridge to move stage at beginning of stack # USE WITH CAUTION: only tested with micromanager demo config if not (simulate) and not (z_stack_external): from pycromanager import Bridge bridge = Bridge() #get object representing micro-manager core core = bridge.get_core() print(core) core.set_position(z_range[0]) ######################################################################### # function to write data into queue # ######################################################################### def place_data(image): """ fnc to place image data into the queue. Keeps track of z-position in stacks and of active color channels. Inputs: np.array image: image data Global variables: image_queue to write image and z position z_range to keep track of z position
def main(): #------------------------------------------------------------------------------------------------------------------------------------ #----------------------------------------------Begin setup of scan parameters-------------------------------------------------------- #------------------------------------------------------------------------------------------------------------------------------------ # set up lasers channel_labels = ["405", "488", "561", "635", "730"] channel_states = [False, False, True, False, False] # true -> active, false -> inactive channel_powers = [50, 10, 90, 100, 95] # (0 -> 100%) do_ind = [0, 1, 2, 3, 4] # digital output line corresponding to each channel # parse which channels are active active_channel_indices = [ ind for ind, st in zip(do_ind, channel_states) if st ] n_active_channels = len(active_channel_indices) print("%d active channels: " % n_active_channels, end="") for ind in active_channel_indices: print("%s " % channel_labels[ind], end="") print("") # exposure time exposure_ms = 50.0 # excess scan positions excess_scan_positions = 10 # galvo voltage at neutral galvo_neutral_volt = -0.15 # unit: volts # scan axis limits. Use stage positions reported by MM scan_axis_start_um = 8680. #unit: um scan_axis_end_um = 8800. #unit: um # tile axis limits. Use stage positions reported by MM tile_axis_start_um = -3841.28 #unit: um tile_axis_end_um = -3841.28 #unit: um # height axis limits. Use stage positions reported by MM height_axis_start_um = 13128.63 #unit: um height_axis_end_um = 13128.63 #unit: um # number of timepoints to execute # TO DO: add in control for rate of experiment timepoints = 1 # FOV parameters # ONLY MODIFY IF NECESSARY # ROI = [0, 1152, 2304, 512] #unit: pixels # setup file name save_directory = Path('D:/20210831') save_name = 'stage_scan' #------------------------------------------------------------------------------------------------------------------------------------ #----------------------------------------------End setup of scan parameters---------------------------------------------------------- #------------------------------------------------------------------------------------------------------------------------------------ # connect to Micromanager instance bridge = Bridge() core = bridge.get_core() # turn off lasers core.set_config('Laser', 'Off') core.wait_for_config('Laser', 'Off') # set camera to fast readout mode core.set_config('Camera-Setup', 'ScanMode3') core.wait_for_config('Camera-Setup', 'ScanMode3') # set camera to START mode upon input trigger core.set_config('Camera-TriggerType', 'START') core.wait_for_config('Camera-TriggerType', 'START') # set camera to positive input trigger core.set_config('Camera-TriggerPolarity', 'POSITIVE') core.wait_for_config('Camera-TriggerPolarity', 'POSITIVE') # set camera to internal control core.set_config('Camera-TriggerSource', 'INTERNAL') core.wait_for_config('Camera-TriggerSource', 'INTERNAL') # set camera to output positive triggers on all lines for exposure core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER KIND[0]', 'EXPOSURE') core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER KIND[1]', 'EXPOSURE') core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER KIND[2]', 'EXPOSURE') core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER POLARITY[0]', 'POSITIVE') core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER POLARITY[1]', 'POSITIVE') core.set_property('OrcaFusionBT', 'OUTPUT TRIGGER POLARITY[2]', 'POSITIVE') # change core timeout for long stage moves core.set_property('Core', 'TimeoutMs', 100000) time.sleep(1) # set exposure core.set_exposure(exposure_ms) # determine image size core.snap_image() y_pixels = core.get_image_height() x_pixels = core.get_image_width() # grab exposure true_exposure = core.get_exposure() # get actual framerate from micromanager properties actual_readout_ms = true_exposure + float( core.get_property('OrcaFusionBT', 'ReadoutTime')) #unit: ms # camera pixel size pixel_size_um = .115 # unit: um # scan axis setup scan_axis_step_um = 0.4 # unit: um scan_axis_step_mm = scan_axis_step_um / 1000. #unit: mm scan_axis_start_mm = scan_axis_start_um / 1000. #unit: mm scan_axis_end_mm = scan_axis_end_um / 1000. #unit: mm scan_axis_range_um = np.abs(scan_axis_end_um - scan_axis_start_um) # unit: um scan_axis_range_mm = scan_axis_range_um / 1000 #unit: mm actual_exposure_s = actual_readout_ms / 1000. #unit: s scan_axis_speed = np.round(scan_axis_step_mm / actual_exposure_s, 4) #unit: mm/s scan_axis_positions = np.rint(scan_axis_range_mm / scan_axis_step_mm).astype( int) #unit: number of positions # tile axis setup tile_axis_overlap = 0.2 #unit: percentage tile_axis_range_um = np.abs(tile_axis_end_um - tile_axis_start_um) #unit: um tile_axis_range_mm = tile_axis_range_um / 1000 #unit: mm tile_axis_ROI = x_pixels * pixel_size_um #unit: um tile_axis_step_um = np.round((tile_axis_ROI) * (1 - tile_axis_overlap), 2) #unit: um tile_axis_step_mm = tile_axis_step_um / 1000 #unit: mm tile_axis_positions = np.rint( tile_axis_range_mm / tile_axis_step_mm).astype(int) + 1 #unit: number of positions # if tile_axis_positions rounded to zero, make sure we acquire at least one position if tile_axis_positions == 0: tile_axis_positions = 1 # height axis setup height_axis_overlap = 0.2 #unit: percentage height_axis_range_um = np.abs(height_axis_end_um - height_axis_start_um) #unit: um height_axis_range_mm = height_axis_range_um / 1000 #unit: mm height_axis_ROI = y_pixels * pixel_size_um * np.sin( 30. * np.pi / 180.) #unit: um height_axis_step_um = np.round( (height_axis_ROI) * (1 - height_axis_overlap), 2) #unit: um height_axis_step_mm = height_axis_step_um / 1000 #unit: mm height_axis_positions = np.rint( height_axis_range_mm / height_axis_step_mm).astype(int) + 1 #unit: number of positions # if height_axis_positions rounded to zero, make sure we acquire at least one position if height_axis_positions == 0: height_axis_positions = 1 # get handle to xy and z stages xy_stage = core.get_xy_stage_device() z_stage = core.get_focus_device() # galvo voltage at neutral galvo_neutral_volt = -.15 # unit: volts # set the galvo to the neutral position if it is not already try: taskAO_first = daq.Task() taskAO_first.CreateAOVoltageChan("/Dev1/ao0", "", -4.0, 4.0, daq.DAQmx_Val_Volts, None) taskAO_first.WriteAnalogScalarF64(True, -1, galvo_neutral_volt, None) taskAO_first.StopTask() taskAO_first.ClearTask() except: print("DAQmx Error %s" % err) # Setup Tiger controller to pass signal when the scan stage cross the start position to the PLC plcName = 'PLogic:E:36' propPosition = 'PointerPosition' propCellConfig = 'EditCellConfig' #addrOutputBNC3 = 35 # BNC3 on the PLC front panel addrOutputBNC1 = 33 # BNC1 on the PLC front panel addrStageSync = 46 # TTL5 on Tiger backplane = stage sync signal # connect stage sync signal to BNC output core.set_property(plcName, propPosition, addrOutputBNC1) core.set_property(plcName, propCellConfig, addrStageSync) # turn on 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No') # set tile axis speed for all moves command = 'SPEED Y=.1' core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # set scan axis speed for large move to initial position command = 'SPEED X=.1' core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # turn off 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes') # move scan scan stage to initial position core.set_xy_position(scan_axis_start_um, tile_axis_start_um) core.wait_for_device(xy_stage) core.set_position(height_axis_start_um) core.wait_for_device(z_stage) # turn on 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No') # set scan axis speed to correct speed for continuous stage scan # expects mm/s command = 'SPEED X=' + str(scan_axis_speed) core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # set scan axis to true 1D scan with no backlash command = '1SCAN X? Y=0 Z=9 F=0' core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # set range and return speed (5% of max) for scan axis # expects mm command = '1SCANR X=' + str(scan_axis_start_mm) + ' Y=' + str( scan_axis_end_mm) + ' R=10' core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # turn off 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes') # set all laser to external triggering core.set_config('Modulation-405', 'External-Digital') core.wait_for_config('Modulation-405', 'External-Digital') core.set_config('Modulation-488', 'External-Digital') core.wait_for_config('Modulation-488', 'External-Digital') core.set_config('Modulation-561', 'External-Digital') core.wait_for_config('Modulation-561', 'External-Digital') core.set_config('Modulation-637', 'External-Digital') core.wait_for_config('Modulation-637', 'External-Digital') core.set_config('Modulation-730', 'External-Digital') core.wait_for_config('Modulation-730', 'External-Digital') # turn all lasers on core.set_config('Laser', 'AllOn') core.wait_for_config('Laser', 'AllOn') # set lasers to user defined power core.set_property('Coherent-Scientific Remote', 'Laser 405-100C - PowerSetpoint (%)', channel_powers[0]) core.set_property('Coherent-Scientific Remote', 'Laser 488-150C - PowerSetpoint (%)', channel_powers[1]) core.set_property('Coherent-Scientific Remote', 'Laser OBIS LS 561-150 - PowerSetpoint (%)', channel_powers[2]) core.set_property('Coherent-Scientific Remote', 'Laser 637-140C - PowerSetpoint (%)', channel_powers[3]) core.set_property('Coherent-Scientific Remote', 'Laser 730-30C - PowerSetpoint (%)', channel_powers[4]) # setup DAQ samples_per_ch = 2 DAQ_sample_rate_Hz = 10000 num_DI_channels = 8 # set the galvo to neutral taskAO_last = daq.Task() taskAO_last.CreateAOVoltageChan("/Dev1/ao0", "", -4.0, 4.0, daq.DAQmx_Val_Volts, None) taskAO_last.WriteAnalogScalarF64(True, -1, galvo_neutral_volt, None) taskAO_last.StopTask() taskAO_last.ClearTask() # output experiment info print('Number of X positions: ' + str(scan_axis_positions)) print('Number of Y tiles: ' + str(tile_axis_positions)) print('Number of Z slabs: ' + str(height_axis_positions)) print('Number of channels: ' + str(n_active_channels)) # flags for metadata and processing setup_processing = True setup_metadata = True # create events to execute scan events = [] for x in range(scan_axis_positions + excess_scan_positions): evt = {'axes': {'z': x}} events.append(evt) for t_idx in range(timepoints): for y_idx in range(tile_axis_positions): # calculate tile axis position tile_position_um = tile_axis_start_um + (tile_axis_step_um * y_idx) # move XY stage to new tile axis position core.set_xy_position(scan_axis_start_um, tile_position_um) core.wait_for_device(xy_stage) for z_idx in range(height_axis_positions): # calculate height axis position height_position_um = height_axis_start_um + ( height_axis_step_um * z_idx) # move Z stage to new height axis position core.set_position(height_position_um) core.wait_for_device(z_stage) for ch_idx in active_channel_indices: # create DAQ pattern for laser strobing controlled via rolling shutter dataDO = np.zeros((samples_per_ch, num_DI_channels), dtype=np.uint8) dataDO[0, ch_idx] = 1 dataDO[1, ch_idx] = 0 #print(dataDO) # update save_name with current tile information save_name_tyzc = save_name + '_t' + str(t_idx).zfill( 4) + '_y' + str(y_idx).zfill(4) + '_z' + str( z_idx).zfill(4) + '_ch' + str(ch_idx).zfill(4) # turn on 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No') # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # turn off 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes') # save actual stage positions xy_pos = core.get_xy_stage_position() stage_x = xy_pos.x stage_y = xy_pos.y stage_z = core.get_position() current_stage_data = [{ 'stage_x': stage_x, 'stage_y': stage_y, 'stage_z': stage_z }] df_current_stage = pd.DataFrame(current_stage_data) # setup DAQ for laser strobing try: # ----- DIGITAL input ------- taskDI = daq.Task() taskDI.CreateDIChan("/Dev1/PFI0", "", daq.DAQmx_Val_ChanForAllLines) ## Configure change detection timing (from wave generator) taskDI.CfgInputBuffer( 0 ) # must be enforced for change-detection timing, i.e no buffer taskDI.CfgChangeDetectionTiming( "/Dev1/PFI0", "/Dev1/PFI0", daq.DAQmx_Val_ContSamps, 0) ## Set where the starting trigger taskDI.CfgDigEdgeStartTrig("/Dev1/PFI0", daq.DAQmx_Val_Rising) ## Export DI signal to unused PFI pins, for clock and start taskDI.ExportSignal(daq.DAQmx_Val_ChangeDetectionEvent, "/Dev1/PFI2") taskDI.ExportSignal(daq.DAQmx_Val_StartTrigger, "/Dev1/PFI1") # ----- DIGITAL output ------ taskDO = daq.Task() taskDO.CreateDOChan("/Dev1/port0/line0:7", "", daq.DAQmx_Val_ChanForAllLines) ## Configure timing (from DI task) taskDO.CfgSampClkTiming("/Dev1/PFI2", DAQ_sample_rate_Hz, daq.DAQmx_Val_Rising, daq.DAQmx_Val_ContSamps, samples_per_ch) ## Write the output waveform samples_per_ch_ct_digital = ct.c_int32() taskDO.WriteDigitalLines( samples_per_ch, False, 10.0, daq.DAQmx_Val_GroupByChannel, dataDO, ct.byref(samples_per_ch_ct_digital), None) ## ------ Start digital input and output tasks ---------- taskDO.StartTask() taskDI.StartTask() except daq.DAQError as err: print("DAQmx Error %s" % err) # set camera to external control # DCAM sets the camera back to INTERNAL mode after each acquisition core.set_config('Camera-TriggerSource', 'EXTERNAL') core.wait_for_config('Camera-TriggerSource', 'EXTERNAL') # verify that camera actually switched back to external trigger mode trigger_state = core.get_property('OrcaFusionBT', 'TRIGGER SOURCE') # if not in external control, keep trying until camera changes settings while not (trigger_state == 'EXTERNAL'): time.sleep(2.0) core.set_config('Camera-TriggerSource', 'EXTERNAL') core.wait_for_config('Camera-TriggerSource', 'EXTERNAL') trigger_state = core.get_property( 'OrcaFusionBT', 'TRIGGER SOURCE') print('T: ' + str(t_idx) + ' Y: ' + str(y_idx) + ' Z: ' + str(z_idx) + ' C: ' + str(ch_idx)) # run acquisition for this tyzc combination with Acquisition(directory=save_directory, name=save_name_tyzc, post_camera_hook_fn=camera_hook_fn, show_display=False, max_multi_res_index=0, saving_queue_size=5000) as acq: acq.acquire(events) # clean up acquisition so that AcqEngJ releases directory. # NOTE: This currently does not work. acq = None acq_deleted = False while not (acq_deleted): try: del acq except: time.sleep(0.1) acq_deleted = False else: gc.collect() acq_deleted = True # stop DAQ and make sure it is at zero try: ## Stop and clear both tasks taskDI.StopTask() taskDO.StopTask() taskDI.ClearTask() taskDO.ClearTask() except daq.DAQError as err: print("DAQmx Error %s" % err) # save experimental info after first tile. # we do it this way so that Pycromanager can manage the directories. if (setup_metadata): # save stage scan parameters scan_param_data = [{ 'root_name': str(save_name), 'scan_type': str('stage'), 'theta': float(30.0), 'scan_step': float(scan_axis_step_um * 1000.), 'pixel_size': float(pixel_size_um * 1000.), 'num_t': int(timepoints), 'num_y': int(tile_axis_positions), 'num_z': int(height_axis_positions), 'num_ch': int(n_active_channels), 'scan_axis_positions': int(scan_axis_positions), 'excess_scan_positions': int(excess_scan_positions), 'y_pixels': int(y_pixels), 'x_pixels': int(x_pixels), '405_active': bool(channel_states[0]), '488_active': bool(channel_states[1]), '561_active': bool(channel_states[2]), '635_active': bool(channel_states[3]), '730_active': bool(channel_states[4]) }] # df_stage_scan_params = pd.DataFrame(scan_param_data) # save_name_stage_params = save_directory / 'scan_metadata.csv' # df_stage_scan_params.to_csv(save_name_stage_params) data_io.write_metadata( scan_param_data[0], save_directory / Path('scan_metadata.csv')) setup_metadata = False # save stage scan positions after each tile save_name_stage_positions = Path('t' + str(t_idx).zfill(4) + '_y' + str(y_idx).zfill(4) + '_z' + str(z_idx).zfill(4) + '_ch' + str(ch_idx).zfill(4) + '_stage_positions.csv') save_name_stage_positions = save_directory / save_name_stage_positions # todo: use data_io instead df_current_stage.to_csv(save_name_stage_positions) # turn on 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No') # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # turn off 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes') ''' # if first tile, make parent directory on NAS and start reconstruction script on the server if setup_processing: # make home directory on NAS save_directory_path = Path(save_directory) remote_directory = Path('y:/') / Path(save_directory_path.parts[1]) cmd='mkdir ' + str(remote_directory) status_mkdir = subprocess.run(cmd, shell=True) # copy full experiment metadata to NAS src= Path(save_directory) / Path('scan_metadata.csv') dst= Path(remote_directory) / Path('scan_metadata.csv') Thread(target=shutil.copy, args=[str(src), str(dst)]).start() setup_processing=False # copy current tyzc metadata to NAS save_directory_path = Path(save_directory) remote_directory = Path('y:/') / Path(save_directory_path.parts[1]) src= Path(save_directory) / Path(save_name_stage_positions.parts[2]) dst= Path(remote_directory) / Path(save_name_stage_positions.parts[2]) Thread(target=shutil.copy, args=[str(src), str(dst)]).start() # copy current tyzc data to NAS save_directory_path = Path(save_directory) remote_directory = Path('y:/') / Path(save_directory_path.parts[1]) src= Path(save_directory) / Path(save_name_tyzc+ '_1') dst= Path(remote_directory) / Path(save_name_tyzc+ '_1') Thread(target=shutil.copytree, args=[str(src), str(dst)]).start() ''' # set lasers to zero power channel_powers = [0., 0., 0., 0., 0.] core.set_property('Coherent-Scientific Remote', 'Laser 405-100C - PowerSetpoint (%)', channel_powers[0]) core.set_property('Coherent-Scientific Remote', 'Laser 488-150C - PowerSetpoint (%)', channel_powers[1]) core.set_property('Coherent-Scientific Remote', 'Laser OBIS LS 561-150 - PowerSetpoint (%)', channel_powers[2]) core.set_property('Coherent-Scientific Remote', 'Laser 637-140C - PowerSetpoint (%)', channel_powers[3]) core.set_property('Coherent-Scientific Remote', 'Laser 730-30C - PowerSetpoint (%)', channel_powers[4]) # turn all lasers off core.set_config('Laser', 'Off') core.wait_for_config('Laser', 'Off') # set all lasers back to software control core.set_config('Modulation-405', 'CW (constant power)') core.wait_for_config('Modulation-405', 'CW (constant power)') core.set_config('Modulation-488', 'CW (constant power)') core.wait_for_config('Modulation-488', 'CW (constant power)') core.set_config('Modulation-561', 'CW (constant power)') core.wait_for_config('Modulation-561', 'CW (constant power)') core.set_config('Modulation-637', 'CW (constant power)') core.wait_for_config('Modulation-637', 'CW (constant power)') core.set_config('Modulation-730', 'CW (constant power)') core.wait_for_config('Modulation-730', 'CW (constant power)') # set camera to internal control core.set_config('Camera-TriggerSource', 'INTERNAL') core.wait_for_config('Camera-TriggerSource', 'INTERNAL') bridge.close()
def __init__(self, app, args=None, parent=None, spatial_subsampling=4, time_subsampling=1): """ Intrinsic Imaging GUI """ self.app = app super(MainWindow, self).__init__(i=1, title='intrinsic imaging') # some initialisation self.running, self.stim, self.STIM = False, None, None self.datafolder, self.img, self.vasculature_img = '', None, None self.t0, self.period = 0, 1 ### trying the camera try: # we initialize the camera self.bridge = Bridge() self.core = self.bridge.get_core() self.exposure = self.core.get_exposure() self.demo = False auto_shutter = self.core.get_property('Core', 'AutoShutter') self.core.set_property('Core', 'AutoShutter', 0) except BaseException as be: print(be) print('') print(' /!\ Problem with the Camera /!\ ') print(' --> no camera found ') print('') self.exposure = -1 # flag for no camera self.demo = True ######################## ##### building GUI ##### ######################## self.minView = False self.showwindow() # layout (from NewWindow class) self.init_basic_widget_grid(wdgt_length=3, Ncol_wdgt=20, Nrow_wdgt=20) # -- A plot area (ViewBox + axes) for displaying the image --- self.view = self.graphics_layout.addViewBox(lockAspect=True, invertY=True) self.view.setMenuEnabled(False) self.view.setAspectLocked() self.pimg = pg.ImageItem() # --- setting subject information --- self.add_widget(QtWidgets.QLabel('subjects file:')) self.subjectFileBox = QtWidgets.QComboBox(self) self.subjectFileBox.addItems([ f for f in os.listdir(subjects_path)[::-1] if f.endswith('.json') ]) self.subjectFileBox.activated.connect(self.get_subject_list) self.add_widget(self.subjectFileBox) self.add_widget(QtWidgets.QLabel('subject:')) self.subjectBox = QtWidgets.QComboBox(self) self.get_subject_list() self.add_widget(self.subjectBox) self.add_widget(QtWidgets.QLabel(20 * ' - ')) self.vascButton = QtWidgets.QPushButton( " - = save Vasculature Picture = - ", self) self.vascButton.clicked.connect(self.take_vasculature_picture) self.add_widget(self.vascButton) self.add_widget(QtWidgets.QLabel(20 * ' - ')) # --- data acquisition properties --- self.add_widget(QtWidgets.QLabel('data folder:'), spec='small-left') self.folderB = QtWidgets.QComboBox(self) self.folderB.addItems(FOLDERS.keys()) self.add_widget(self.folderB, spec='large-right') self.add_widget(QtWidgets.QLabel(' - protocol:'), spec='small-left') self.protocolBox = QtWidgets.QComboBox(self) self.protocolBox.addItems(['ALL', 'up', 'down', 'left', 'right']) self.add_widget(self.protocolBox, spec='large-right') self.add_widget( QtWidgets.QLabel(' - exposure: %.0f ms (from Micro-Manager)' % self.exposure)) self.add_widget(QtWidgets.QLabel(' - Nrepeat :'), spec='large-left') self.repeatBox = QtWidgets.QLineEdit() self.repeatBox.setText('10') self.add_widget(self.repeatBox, spec='small-right') self.add_widget(QtWidgets.QLabel(' - stim. period (s):'), spec='large-left') self.periodBox = QtWidgets.QLineEdit() self.periodBox.setText('10') self.add_widget(self.periodBox, spec='small-right') self.add_widget(QtWidgets.QLabel(' - bar size (degree):'), spec='large-left') self.barBox = QtWidgets.QLineEdit() self.barBox.setText('6') self.add_widget(self.barBox, spec='small-right') self.add_widget(QtWidgets.QLabel(' - spatial sub-sampling (px):'), spec='large-left') self.spatialBox = QtWidgets.QLineEdit() self.spatialBox.setText(str(spatial_subsampling)) self.add_widget(self.spatialBox, spec='small-right') self.add_widget(QtWidgets.QLabel(' - acq. freq. (Hz):'), spec='large-left') self.freqBox = QtWidgets.QLineEdit() self.freqBox.setText('10') self.add_widget(self.freqBox, spec='small-right') # self.add_widget(QtWidgets.QLabel(' - flick. freq. (Hz) /!\ > acq:'), # spec='large-left') # self.flickBox = QtWidgets.QLineEdit() # self.flickBox.setText('10') # self.add_widget(self.flickBox, spec='small-right') self.demoBox = QtWidgets.QCheckBox("demo mode") self.demoBox.setStyleSheet("color: gray;") self.add_widget(self.demoBox, spec='large-left') self.demoBox.setChecked(self.demo) self.camBox = QtWidgets.QCheckBox("cam.") self.camBox.setStyleSheet("color: gray;") self.add_widget(self.camBox, spec='small-right') self.camBox.setChecked(True) # --- launching acquisition --- self.liveButton = QtWidgets.QPushButton("-- live view -- ", self) self.liveButton.clicked.connect(self.live_view) self.add_widget(self.liveButton) # --- launching acquisition --- self.acqButton = QtWidgets.QPushButton("-- RUN PROTOCOL -- ", self) self.acqButton.clicked.connect(self.launch_protocol) self.add_widget(self.acqButton, spec='large-left') self.stopButton = QtWidgets.QPushButton(" STOP ", self) self.stopButton.clicked.connect(self.stop_protocol) self.add_widget(self.stopButton, spec='small-right') # --- launching analysis --- self.add_widget(QtWidgets.QLabel(20 * ' - ')) self.analysisButton = QtWidgets.QPushButton(" - = Analysis GUI = - ", self) self.analysisButton.clicked.connect(self.open_analysis) self.add_widget(self.analysisButton, spec='large-left') self.pimg.setImage(0 * self.get_frame()) self.view.addItem(self.pimg) self.view.autoRange(padding=0.001) self.analysisWindow = None
class MainWindow(NewWindow): def __init__(self, app, args=None, parent=None, spatial_subsampling=4, time_subsampling=1): """ Intrinsic Imaging GUI """ self.app = app super(MainWindow, self).__init__(i=1, title='intrinsic imaging') # some initialisation self.running, self.stim, self.STIM = False, None, None self.datafolder, self.img, self.vasculature_img = '', None, None self.t0, self.period = 0, 1 ### trying the camera try: # we initialize the camera self.bridge = Bridge() self.core = self.bridge.get_core() self.exposure = self.core.get_exposure() self.demo = False auto_shutter = self.core.get_property('Core', 'AutoShutter') self.core.set_property('Core', 'AutoShutter', 0) except BaseException as be: print(be) print('') print(' /!\ Problem with the Camera /!\ ') print(' --> no camera found ') print('') self.exposure = -1 # flag for no camera self.demo = True ######################## ##### building GUI ##### ######################## self.minView = False self.showwindow() # layout (from NewWindow class) self.init_basic_widget_grid(wdgt_length=3, Ncol_wdgt=20, Nrow_wdgt=20) # -- A plot area (ViewBox + axes) for displaying the image --- self.view = self.graphics_layout.addViewBox(lockAspect=True, invertY=True) self.view.setMenuEnabled(False) self.view.setAspectLocked() self.pimg = pg.ImageItem() # --- setting subject information --- self.add_widget(QtWidgets.QLabel('subjects file:')) self.subjectFileBox = QtWidgets.QComboBox(self) self.subjectFileBox.addItems([ f for f in os.listdir(subjects_path)[::-1] if f.endswith('.json') ]) self.subjectFileBox.activated.connect(self.get_subject_list) self.add_widget(self.subjectFileBox) self.add_widget(QtWidgets.QLabel('subject:')) self.subjectBox = QtWidgets.QComboBox(self) self.get_subject_list() self.add_widget(self.subjectBox) self.add_widget(QtWidgets.QLabel(20 * ' - ')) self.vascButton = QtWidgets.QPushButton( " - = save Vasculature Picture = - ", self) self.vascButton.clicked.connect(self.take_vasculature_picture) self.add_widget(self.vascButton) self.add_widget(QtWidgets.QLabel(20 * ' - ')) # --- data acquisition properties --- self.add_widget(QtWidgets.QLabel('data folder:'), spec='small-left') self.folderB = QtWidgets.QComboBox(self) self.folderB.addItems(FOLDERS.keys()) self.add_widget(self.folderB, spec='large-right') self.add_widget(QtWidgets.QLabel(' - protocol:'), spec='small-left') self.protocolBox = QtWidgets.QComboBox(self) self.protocolBox.addItems(['ALL', 'up', 'down', 'left', 'right']) self.add_widget(self.protocolBox, spec='large-right') self.add_widget( QtWidgets.QLabel(' - exposure: %.0f ms (from Micro-Manager)' % self.exposure)) self.add_widget(QtWidgets.QLabel(' - Nrepeat :'), spec='large-left') self.repeatBox = QtWidgets.QLineEdit() self.repeatBox.setText('10') self.add_widget(self.repeatBox, spec='small-right') self.add_widget(QtWidgets.QLabel(' - stim. period (s):'), spec='large-left') self.periodBox = QtWidgets.QLineEdit() self.periodBox.setText('10') self.add_widget(self.periodBox, spec='small-right') self.add_widget(QtWidgets.QLabel(' - bar size (degree):'), spec='large-left') self.barBox = QtWidgets.QLineEdit() self.barBox.setText('6') self.add_widget(self.barBox, spec='small-right') self.add_widget(QtWidgets.QLabel(' - spatial sub-sampling (px):'), spec='large-left') self.spatialBox = QtWidgets.QLineEdit() self.spatialBox.setText(str(spatial_subsampling)) self.add_widget(self.spatialBox, spec='small-right') self.add_widget(QtWidgets.QLabel(' - acq. freq. (Hz):'), spec='large-left') self.freqBox = QtWidgets.QLineEdit() self.freqBox.setText('10') self.add_widget(self.freqBox, spec='small-right') # self.add_widget(QtWidgets.QLabel(' - flick. freq. (Hz) /!\ > acq:'), # spec='large-left') # self.flickBox = QtWidgets.QLineEdit() # self.flickBox.setText('10') # self.add_widget(self.flickBox, spec='small-right') self.demoBox = QtWidgets.QCheckBox("demo mode") self.demoBox.setStyleSheet("color: gray;") self.add_widget(self.demoBox, spec='large-left') self.demoBox.setChecked(self.demo) self.camBox = QtWidgets.QCheckBox("cam.") self.camBox.setStyleSheet("color: gray;") self.add_widget(self.camBox, spec='small-right') self.camBox.setChecked(True) # --- launching acquisition --- self.liveButton = QtWidgets.QPushButton("-- live view -- ", self) self.liveButton.clicked.connect(self.live_view) self.add_widget(self.liveButton) # --- launching acquisition --- self.acqButton = QtWidgets.QPushButton("-- RUN PROTOCOL -- ", self) self.acqButton.clicked.connect(self.launch_protocol) self.add_widget(self.acqButton, spec='large-left') self.stopButton = QtWidgets.QPushButton(" STOP ", self) self.stopButton.clicked.connect(self.stop_protocol) self.add_widget(self.stopButton, spec='small-right') # --- launching analysis --- self.add_widget(QtWidgets.QLabel(20 * ' - ')) self.analysisButton = QtWidgets.QPushButton(" - = Analysis GUI = - ", self) self.analysisButton.clicked.connect(self.open_analysis) self.add_widget(self.analysisButton, spec='large-left') self.pimg.setImage(0 * self.get_frame()) self.view.addItem(self.pimg) self.view.autoRange(padding=0.001) self.analysisWindow = None def take_vasculature_picture(self): filename = generate_filename_path(FOLDERS[self.folderB.currentText()], filename='vasculature-%s' % self.subjectBox.currentText(), extension='.tif') # save HQ image as tiff img = self.get_frame(force_HQ=True) np.save(filename.replace('.tif', '.npy'), img) img = np.array(255 * (img - img.min()) / (img.max() - img.min()), dtype=np.uint8) im = PIL.Image.fromarray(img) im.save(filename) print('vasculature image, saved as:') print(filename) # then keep a version to store with imaging: self.vasculature_img = self.get_frame() self.pimg.setImage(img) # show on displayn def open_analysis(self): self.analysisWindow = runAnalysis(self.app, parent=self) def get_subject_list(self): with open( os.path.join(subjects_path, self.subjectFileBox.currentText())) as f: self.subjects = json.load(f) self.subjectBox.clear() self.subjectBox.addItems(self.subjects.keys()) def init_visual_stim(self, demo=True): with open( os.path.join( pathlib.Path(__file__).resolve().parents[1], 'intrinsic', 'vis_stim', 'up.json'), 'r') as fp: protocol = json.load(fp) if self.demoBox.isChecked(): protocol['demo'] = True self.stim = visual_stim.build_stim(protocol) self.parent = dummy_parent() def get_patterns(self, protocol, angle, size, Npatch=30): patterns = [] if protocol in ['left', 'right']: z = np.linspace(-self.stim.screen['resolution'][1], self.stim.screen['resolution'][1], Npatch) for i in np.arange(len(z) - 1)[(1 if self.flip else 0)::2]: patterns.append( visual.Rect(win=self.stim.win, size=(self.stim.angle_to_pix(size), z[1] - z[0]), pos=(self.stim.angle_to_pix(angle), z[i]), units='pix', fillColor=1)) if protocol in ['up', 'down']: x = np.linspace(-self.stim.screen['resolution'][0], self.stim.screen['resolution'][0], Npatch) for i in np.arange(len(x) - 1)[(1 if self.flip else 0)::2]: patterns.append( visual.Rect(win=self.stim.win, size=(x[1] - x[0], self.stim.angle_to_pix(size)), pos=(x[i], self.stim.angle_to_pix(angle)), units='pix', fillColor=1)) return patterns def run(self): self.flip = False self.stim = visual_stim( { "Screen": "Dell-2020", "presentation-prestim-screen": -1, "presentation-poststim-screen": -1 }, demo=self.demoBox.isChecked()) self.Nrepeat = int(self.repeatBox.text()) # self.period = float(self.periodBox.text()) # degree / second self.bar_size = float(self.barBox.text()) # degree / second # self.dt_save, self.dt = 1./float(self.freqBox.text()), 1./float(self.flickBox.text()) self.dt_save, self.dt = 1. / float(self.freqBox.text()), 1. / float( self.freqBox.text()) xmin, xmax = 1.15 * np.min(self.stim.x), 1.15 * np.max(self.stim.x) zmin, zmax = 1.3 * np.min(self.stim.z), 1.3 * np.max(self.stim.z) self.angle_start, self.angle_max, self.protocol, self.label = 0, 0, '', '' self.Npoints = int(self.period / self.dt_save) if self.protocolBox.currentText() == 'ALL': self.STIM = { 'angle_start': [zmin, xmax, zmax, xmin], 'angle_stop': [zmax, xmin, zmin, xmax], 'label': ['up', 'left', 'down', 'right'], 'xmin': xmin, 'xmax': xmax, 'zmin': zmin, 'zmax': zmax } self.label = 'up' # starting point else: self.STIM = { 'label': [self.protocolBox.currentText()], 'xmin': xmin, 'xmax': xmax, 'zmin': zmin, 'zmax': zmax } if self.protocolBox.currentText() == 'up': self.STIM['angle_start'] = [zmin] self.STIM['angle_stop'] = [zmax] if self.protocolBox.currentText() == 'down': self.STIM['angle_start'] = [zmax] self.STIM['angle_stop'] = [zmin] if self.protocolBox.currentText() == 'left': self.STIM['angle_start'] = [xmax] self.STIM['angle_stop'] = [xmin] if self.protocolBox.currentText() == 'right': self.STIM['angle_start'] = [xmin] self.STIM['angle_stop'] = [xmax] self.label = self.protocolBox.currentText() for il, label in enumerate(self.STIM['label']): self.STIM[label + '-times'] = np.arange( self.Npoints * self.Nrepeat) * self.dt_save self.STIM[label + '-angle'] = np.concatenate([ np.linspace(self.STIM['angle_start'][il], self.STIM['angle_stop'][il], self.Npoints) for n in range(self.Nrepeat) ]) # initialize one episode: self.iEp, self.iTime, self.t0_episode = 0, 0, time.time() self.img, self.nSave = self.new_img(), 0 self.save_metadata() print('acquisition running [...]') self.update_dt() # while loop def new_img(self): return np.zeros(self.imgsize, dtype=np.float64) def save_img(self): if self.nSave > 0: self.img /= self.nSave if True: # live display self.pimg.setImage(self.img) # NEED TO STORE DATA HERE self.FRAMES.append(self.img) # re-init time step of acquisition self.img, self.nSave = self.new_img(), 0 def update_dt(self): self.tSave = time.time() while (time.time() - self.tSave) <= self.dt_save: self.t = time.time() # show image patterns = self.get_patterns( self.STIM['label'][self.iEp % len(self.STIM['label'])], self.STIM[self.STIM['label'][self.iEp % len(self.STIM['label'])] + '-angle'][self.iTime], self.bar_size) for pattern in patterns: pattern.draw() try: self.stim.win.flip() except BaseException: pass if self.camBox.isChecked(): # # fetch image self.img += self.get_frame() self.nSave += 1.0 # time.sleep(max([self.dt-(time.time()-self.t), 0])) # self.flip = (False if self.flip else True) # flip the flag self.flip = (False if self.flip else True) # flip the flag if self.camBox.isChecked(): self.save_img() # re-init image here self.iTime += 1 # checking if not episode over if not (self.iTime < len(self.STIM[self.STIM['label'][ self.iEp % len(self.STIM['label'])] + '-angle'])): if self.camBox.isChecked(): self.write_data() # writing data when over self.t0_episode, self.img, self.nSave = time.time(), self.new_img( ), 0 self.FRAMES = [] # re init data self.iTime = 0 self.iEp += 1 # continuing ? if self.running: QtCore.QTimer.singleShot(1, self.update_dt) def write_data(self): filename = '%s-%i.nwb' % (self.STIM['label'][self.iEp % len( self.STIM['label'])], int(self.iEp / len(self.STIM['label'])) + 1) nwbfile = pynwb.NWBFile( 'Intrinsic Imaging data following bar stimulation', 'intrinsic', datetime.datetime.utcnow(), file_create_date=datetime.datetime.utcnow()) # Create our time series angles = pynwb.TimeSeries( name='angle_timeseries', data=self.STIM[self.STIM['label'][self.iEp % len(self.STIM['label'])] + '-angle'], unit='Rd', timestamps=self.STIM[self.STIM['label'][self.iEp % len(self.STIM['label'])] + '-times']) nwbfile.add_acquisition(angles) images = pynwb.image.ImageSeries( name='image_timeseries', data=np.array(self.FRAMES, dtype=np.float64), unit='a.u.', timestamps=self.STIM[self.STIM['label'][self.iEp % len(self.STIM['label'])] + '-times']) nwbfile.add_acquisition(images) # Write the data to file io = pynwb.NWBHDF5IO(os.path.join(self.datafolder, filename), 'w') print('writing:', filename) io.write(nwbfile) io.close() print(filename, ' saved !') def save_metadata(self): filename = generate_filename_path(FOLDERS[self.folderB.currentText()], filename='metadata', extension='.npy') metadata = { 'subject': str(self.subjectBox.currentText()), 'exposure': self.exposure, 'bar-size': float(self.barBox.text()), 'acq-freq': float(self.freqBox.text()), 'period': float(self.periodBox.text()), 'Nrepeat': int(self.repeatBox.text()), 'imgsize': self.imgsize, 'STIM': self.STIM } np.save(filename, metadata) if self.vasculature_img is not None: np.save(filename.replace('metadata', 'vasculature'), self.vasculature_img) self.datafolder = os.path.dirname(filename) def launch_protocol(self): if not self.running: self.running = True # initialization of data self.FRAMES = [] self.img = self.get_frame() self.imgsize = self.img.shape self.pimg.setImage(self.img) self.view.autoRange(padding=0.001) self.run() else: print( ' /!\ --> pb in launching acquisition (either already running or missing camera)' ) def live_view(self): self.running, self.t0 = True, time.time() self.update_Image() def stop_protocol(self): if self.running: self.running = False if self.stim is not None: self.stim.close() else: print('acquisition not launched') def get_frame(self, force_HQ=False): if self.exposure > 0: self.core.snap_image() tagged_image = self.core.get_tagged_image() #pixels by default come out as a 1D array. We can reshape them into an image img = np.reshape(tagged_image.pix, newshape=[ tagged_image.tags['Height'], tagged_image.tags['Width'] ]) elif (self.stim is not None) and (self.STIM is not None): it = int((time.time() - self.t0_episode) / self.dt_save) % int( self.period / self.dt_save) protocol = self.STIM['label'][self.iEp % len(self.STIM['label'])] if protocol == 'left': img = np.random.randn(*self.stim.x.shape)+\ np.exp(-(self.stim.x-(40*it/self.Npoints-20))**2/2./10**2)*\ np.exp(-self.stim.z**2/2./15**2) elif protocol == 'right': img = np.random.randn(*self.stim.x.shape)+\ np.exp(-(self.stim.x+(40*it/self.Npoints-20))**2/2./10**2)*\ np.exp(-self.stim.z**2/2./15**2) elif protocol == 'up': img = np.random.randn(*self.stim.x.shape)+\ np.exp(-(self.stim.z-(40*it/self.Npoints-20))**2/2./10**2)*\ np.exp(-self.stim.x**2/2./15**2) else: # down img = np.random.randn(*self.stim.x.shape)+\ np.exp(-(self.stim.z+(40*it/self.Npoints-20))**2/2./10**2)*\ np.exp(-self.stim.x**2/2./15**2) else: img = np.random.randn(720, 1280) if (int(self.spatialBox.text()) > 1) and not force_HQ: return 1.0 * analysis.resample_img(img, int( self.spatialBox.text())) else: return 1.0 * img def update_Image(self): # plot it self.pimg.setImage(self.get_frame()) new_t0 = time.time() print('dt=%.1f ms' % (1e3 * (new_t0 - self.t0))) self.t0 = new_t0 if self.running: QtCore.QTimer.singleShot(1, self.update_Image) def hitting_space(self): if not self.running: self.launch_protocol() else: self.stop_protocol() def process(self): self.launch_analysis() def quit(self): if self.exposure > 0: self.bridge.close() sys.exit()
def __init__(self, stageDevice): bridge = Bridge() self.mmc = bridge.get_core() self.mmc.set_xy_stage_device(stageDevice)
from pycromanager import Acquisition, multi_d_acquisition_events, Bridge, Dataset from matplotlib import pyplot as plt import numpy as np import cv2 import time, math import os, sys, re from PIL import Image from math import sqrt from pathlib import Path bridge = Bridge() core = bridge.get_core() mm = bridge.get_studio() pm = mm.positions() mmc = mm.core() pos_list = pm.get_position_list() #------------------------------------------- directoryPATH = 'E:\KENZA Folder\CapstoneTests' nameofSAVEDFILE = 'saving_name' #-------------------------------------------- def merge_imagesVertical(file1, file2): """Merge two images into one vertical image :return: the merged Image object """ image1 = file1 image2 = file2 vis = np.concatenate((image1, image2), axis=0)
def main(): #------------------------------------------------------------------------------------------------------------------------------------ #----------------------------------------------Begin setup of scan parameters-------------------------------------------------------- #------------------------------------------------------------------------------------------------------------------------------------ # lasers to use # 0 -> inactive # 1 -> active state_405 = 0 state_488 = 0 state_561 = 0 state_635 = 1 state_730 = 0 # laser powers (0 -> 100%) power_405 = 2 power_488 = 2 power_561 = 2 power_635 = 50 power_730 = 0 # exposure time exposure_ms = 5. # scan axis limits. Use stage positions reported by MM scan_axis_start_um = 1614. #unit: um scan_axis_end_um = 1625. #unit: um tile_axis_start_um = -265. height_axis_start_um = 9500. # FOV parameters # ONLY MODIFY IF NECESSARY ROI = [1024, 0, 256, 2048] #unit: pixels # setup file name save_directory = Path('E:/20201023/') save_name = 'scan_test' #------------------------------------------------------------------------------------------------------------------------------------ #----------------------------------------------End setup of scan parameters---------------------------------------------------------- #------------------------------------------------------------------------------------------------------------------------------------ bridge = Bridge() core = bridge.get_core() # set camera into 16bit readout mode # give camera time to change modes if necessary core.set_property('Camera', 'ReadoutRate', '100MHz 16bit') time.sleep(5) # set camera into low noise readout mode # give camera time to change modes if necessary core.set_property('Camera', 'Gain', '2-CMS') time.sleep(5) # set camera to trigger first mode # give camera time to change modes if necessary core.set_property('Camera', 'Trigger Timeout (secs)', 60) time.sleep(5) # set camera to internal trigger # give camera time to change modes if necessary core.set_property('Camera', 'TriggerMode', 'Internal Trigger') time.sleep(5) # set exposure core.set_exposure(exposure_ms) # get actual framerate, accounting for readout time actual_readout_ms = float(core.get_property( 'Camera', 'ActualInterval-ms')) #unit: ms # camera pixel size pixel_size_um = .115 # unit: um # scan axis setup scan_axis_step_um = 0.2 # unit: um scan_axis_step_mm = scan_axis_step_um / 1000. #unit: mm scan_axis_start_mm = scan_axis_start_um / 1000. #unit: mm scan_axis_end_mm = scan_axis_end_um / 1000. #unit: mm scan_axis_range_um = np.abs(scan_axis_end_um - scan_axis_start_um) # unit: um scan_axis_range_mm = scan_axis_range_um / 1000 #unit: mm actual_exposure_s = actual_readout_ms / 1000. #unit: s scan_axis_speed = np.round(scan_axis_step_mm / actual_exposure_s, 2) #unit: mm/s scan_axis_positions = np.rint(scan_axis_range_mm / scan_axis_step_mm).astype(int) # get handle to xy and z stages xy_stage = core.get_xy_stage_device() z_stage = core.get_focus_device() # Setup PLC card to give start trigger plcName = 'PLogic:E:36' propPosition = 'PointerPosition' propCellConfig = 'EditCellConfig' addrOutputBNC3 = 35 addrStageSync = 46 # TTL5 on Tiger backplane = stage sync signal # connect stage sync signal to BNC output core.set_property(plcName, propPosition, addrOutputBNC3) core.set_property(plcName, propCellConfig, addrStageSync) # turn on 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No') # set tile axis speed for all moves command = 'SPEED Y=.5' core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # set scan axis speed for large move to initial position command = 'SPEED X=.5' core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # turn off 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes') # move scan scan stage to initial position core.set_xy_position(scan_axis_start_um, tile_axis_start_um) core.wait_for_device(xy_stage) core.set_position(height_axis_start_um) core.wait_for_device(z_stage) # turn on 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'No') # set scan axis speed to correct speed for continuous stage scan # expects mm/s command = 'SPEED X=' + str(scan_axis_speed) core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # set scan axis to true 1D scan with no backlash command = '1SCAN X? Y=0 Z=9 F=0' core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # set range for scan axis # expects mm command = '1SCANR X=' + str(scan_axis_start_mm) + ' Y=' + str( scan_axis_end_mm) + ' R=50' core.set_property('TigerCommHub', 'SerialCommand', command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) #command = '1SCANV X=0 Y=0 Z=2' #core.set_property('TigerCommHub','SerialCommand',command) # check to make sure Tiger is not busy ready = 'B' while (ready != 'N'): command = 'STATUS' core.set_property('TigerCommHub', 'SerialCommand', command) ready = core.get_property('TigerCommHub', 'SerialResponse') time.sleep(.500) # turn off 'transmit repeated commands' for Tiger core.set_property('TigerCommHub', 'OnlySendSerialCommandOnChange', 'Yes') # construct boolean array for lasers to use channel_states = [state_405, state_488, state_561, state_635, state_730] channel_powers = [power_405, power_488, power_561, power_635, power_730] # set all lasers to off and user defined power core.set_property('Coherent-Scientific Remote', 'Laser 405-100C - PowerSetpoint (%)', channel_powers[0]) core.set_property('Coherent-Scientific Remote', 'Laser 488-150C - PowerSetpoint (%)', channel_powers[1]) core.set_property('Coherent-Scientific Remote', 'Laser OBIS LS 561-150 - PowerSetpoint (%)', channel_powers[2]) core.set_property('Coherent-Scientific Remote', 'Laser 637-140C - PowerSetpoint (%)', channel_powers[3]) core.set_property('Coherent-Scientific Remote', 'Laser 730-30C - PowerSetpoint (%)', channel_powers[4]) print(scan_axis_positions) # create events to execute scan events = [] #for t in range(2): for x in range(scan_axis_positions): evt = {'axes': {'x': x}} events.append(evt) # set camera to internal trigger # give camera time to change modes if necessary core.set_property('Camera', 'TriggerMode', 'Trigger first') time.sleep(1) # run acquisition with Acquisition(directory=save_directory, name=save_name, post_hardware_hook_fn=post_hook_fn, post_camera_hook_fn=camera_hook_fn, show_display=True, max_multi_res_index=0) as acq: acq.acquire(events) # set camera to internal trigger # give camera time to change modes if necessary core.set_property('Camera', 'TriggerMode', 'Internal Trigger') time.sleep(1)