def __init__( self, num_measurements=15, ): # Grab control of hardware self.analog_out = ni.Analog_Out( num_channels=len(n2c.keys()), num_digital_lines=0, rate=5e5, daq_type='6733', board_name='Dev1') self.idp = image_data_pipeline.Image_Data_Pipeline( num_buffers=1, buffer_shape=(num_measurements, 1944, 2592), camera_child_process=DMK_camera_child_process) self.idp.apply_camera_settings(trigger='external_trigger') self.idp.display.withdraw() # To prevent focus-theft self.mirror_voltage_shape = None self.measurement_start_pixel = None self.measurement_pixels = None self.illumination = None self._calibrate_laser() return None
def __init__( self, zaber_stage_port_name, # For example, 'COM3' exposure_time_seconds=0.2, bin_size=None, ): # Image data pipeline, to get frames off the camera, display # them on-screen, and possibly save them to disk: self.idp = image_data_pipeline.Image_Data_Pipeline( num_buffers=1, buffer_shape=(1, 1944, 2592), camera_child_process=DMK_camera_child_process) self.idp.display.withdraw() # To prevent focus-theft self.idp.apply_camera_settings( exposure_time_microseconds=exposure_time_seconds * 1e6, trigger='external_trigger') self.idp.display.withdraw() # To prevent focus-theft self.idp.file_saving.commands.send(('set_bin_size', { 'bin_size': bin_size })) # Analog-out card, to trigger the camera and the illumination: self.analog_out = ni.Analog_Out(num_channels='all', rate=1e5, daq_type='9263', board_name='cDAQ1Mod1') self.set_exposure_and_dose(dose_duration_488_seconds=5, dose_duration_405_seconds=5, snap_voltage_488=4, snap_voltage_405=4, dose_voltage_488=4, dose_voltage_405=4) # XY stage, to scan multiple fields of view self.stage = zaber.Stage(port_name=zaber_stage_port_name, timeout=7) self.stage.min_x, self.stage.min_y = 0, 0 self.stage.max_x, self.stage.max_y = 303118, 303118 self.last_snap_x, self.last_snap_y = -1, -1 return None
def main(): # This incantation is forced on us so the IDP won't print everything twice: import logging import multiprocessing as mp logger = mp.log_to_stderr() logger.setLevel(logging.INFO) # Set parameters for IDP (Image Data Pipeline) set_num_buffers = 8 image_height_pixels = 128 image_width_pixels = 380 # Set parameters for DAQ (analog out card) num_daq_channels = 3 daq_rate = 8e5 ############################################################## # Set exposure parameters for camera and laser illumination: # ############################################################## green_AOM_mV = [ 0, 69, 92, 114, 151, 212, 300, ] #calibrated green_powers = [ '0mW', '4mW', '13mW', '26mW', '53mW', '96mW', '130mW', ] red_AOM_mV = [ 269, ] #calibrated red_powers = [, '0mW', ] angle_string = '' # Set laser pulse duration VERY SHORT green_pulse_duration_pixels = 1 red_pulse_duration_pixels = 1 # Set green pulse train repetition time short enough to # thermally stabilize the sample green_rep_time_us = 600 green_rep_time_pixels = int(np.ceil( green_rep_time_us * 1e-6 * daq_rate)) # how many red laser shots in an exposure? pulses_per_exposure = 8 # you don't want red light leaking into next exposure so set this to # 1 if you're imaging 720 nm. # set to zero if you're looking for depletion, because you need # every green pulse matched with a red for that measurement less_red_pulses = 0 desired_effective_exposure_time_pixels = (green_rep_time_pixels * pulses_per_exposure) assert desired_effective_exposure_time_pixels > 0 #define red/green pulse delays red_start_pixel_array = np.array([-2, 0, 2]) num_delays = red_start_pixel_array.shape[0] print('Red/green delay (us) =', red_start_pixel_array / daq_rate * 1e6) # number of exposures should be the first dimension of the idp buffer num_delay_scan_repetitions = 1 num_exposures = num_delays * num_delay_scan_repetitions # actual roll time is 640 us, which should be a multiple of # green_rep_time_us, but may not always be # this only works for the current field of view height 128 pixels # 10 us per line, rolling is symmetrical around middle of chip rolling_time_us = 640 #experimentally determined for this field of view rolling_time_pixels = int(np.ceil( rolling_time_us * 1e-6 * daq_rate)) extra_time_after_roll_pixels = (green_rep_time_pixels - rolling_time_pixels % green_rep_time_pixels) effective_exposure_time_pixels = (extra_time_after_roll_pixels + desired_effective_exposure_time_pixels) # reminder: negative delay values (red before green) are only valid if the # camera roll finishes before the red pulse gets there assert extra_time_after_roll_pixels > -min(red_start_pixel_array) set_exposure_time_pixels = (rolling_time_pixels + effective_exposure_time_pixels) # set exposure time must be an integer multiple of green rep time assert (set_exposure_time_pixels % green_rep_time_pixels) == 0 set_exposure_time_us = int(np.ceil( set_exposure_time_pixels / daq_rate * 1e6)) # Initialize the IDP: idp = image_data_pipeline.Image_Data_Pipeline( num_buffers=set_num_buffers, buffer_shape=(num_exposures, image_height_pixels, image_width_pixels), camera_child_process=pco_edge_camera_child_process) assert idp.buffer_shape[0] == num_exposures # Initialize the DAQ: daq = ni.PCI_6733( num_channels=num_daq_channels, rate=daq_rate, verbose=True) assert daq.rate == daq_rate try: # Apply camera settings: idp.display.set_intensity_scaling('median_filter_autoscale') idp.apply_camera_settings( trigger='external_trigger', exposure_time_microseconds = set_exposure_time_us, region_of_interest ={'bottom': 1088, 'top': 961, 'left': 841, 'right': 1220}, preframes=0) # UNCOMMON COMMAND: the daq voltage string can get very long, so # Andy wrote a new part of pco.py that adjusts the set timeout # for waiting for the FIRST camera trigger (Oct 4, 2016) idp.camera.commands.send(('set_first_trigger_timeout_seconds', {'first_trigger_timeout_seconds': 3})) assert idp.camera.commands.recv() == 3 # clear command queue # Figure out some basic timing information: This is what the # camera thinks it's doing. Is it what we want it to do? exposure_time_us = idp.camera.get_setting('exposure_time_microseconds') print('I want exposure time to be (us)',set_exposure_time_us) print('Exposure time actually is (us)',exposure_time_us) assert exposure_time_us == set_exposure_time_us rolling_time_us = idp.camera.get_setting('rolling_time_microseconds') rolling_time_jitter_us = 15 #experimentally measured and also in spec rolling_time_us += rolling_time_jitter_us pulse_tail_us = 25 #experimentally measured response of buffer amp and AOM print("\nCamera exposure time:", exposure_time_us, "(us)\n") print("\nCamera rolling time:", rolling_time_us, "(us)\n") effective_exposure_us = exposure_time_us - rolling_time_us print("\nCamera effective exposure:", effective_exposure_us, "(us)\n") for [red_voltage_num, my_red_voltage_mV] in enumerate(red_AOM_mV): for [green_voltage_num, my_green_voltage_mV] in enumerate(green_AOM_mV): # Calculate DAQ voltages # Set voltages to play on analog out card green_voltage = my_green_voltage_mV/1000 red_voltage = my_red_voltage_mV/1000 trig_voltage = 3 # time between exposures must be greater than camera trigger # jitter and a multiple of the green rep time # trigger jitter is about 10 us time_between_exposures_pixels = 2 * green_rep_time_pixels camera_rep_time_pixels = (set_exposure_time_pixels + time_between_exposures_pixels) camera_rep_time_us = camera_rep_time_pixels / daq_rate * 1e6 voltages = np.zeros((camera_rep_time_pixels * num_exposures, num_daq_channels)) # camera trigger duration should be 3us or greater trigger_duration_us = 3 trigger_duration_pixels = int(np.ceil( trigger_duration_us / 1e6 * daq_rate)) # loop used to define camera trigger and red laser pulse # voltages for which_exposure in range(num_exposures): cursor = which_exposure * camera_rep_time_pixels # Camera triggers: voltages[cursor:cursor + trigger_duration_pixels, 0] = ( trig_voltage) # Red laser pulses red_start_pixel = ( red_start_pixel_array[which_exposure % num_delays]) red_series_start = (cursor + rolling_time_pixels + extra_time_after_roll_pixels + red_start_pixel) red_chunk = np.zeros(green_rep_time_pixels) red_chunk[0:red_pulse_duration_pixels] = red_voltage red_exposure_array = np.tile(red_chunk, ( pulses_per_exposure - less_red_pulses)) voltages[red_series_start:(red_series_start + red_exposure_array.shape[0]), 2] = red_exposure_array # Green laser pulses green_start_pixel = 0 green_series_start = (cursor + rolling_time_pixels + extra_time_after_roll_pixels + green_start_pixel) green_chunk = np.zeros(green_rep_time_pixels) green_chunk[0:green_pulse_duration_pixels] = green_voltage green_exposure_array = np.tile(green_chunk, ( pulses_per_exposure - less_red_pulses)) voltages[green_series_start:(green_series_start + green_exposure_array.shape[0]), 1] = green_exposure_array # save voltages that will be sent to daq with open('voltages_green_' + green_powers[green_voltage_num] + '_red_' + red_powers[red_voltage_num] + '_fluorescence.pickle', 'wb') as f: pickle.dump(voltages, f) # Put it all together idp.load_permission_slips( num_slips=1, file_saving_info=[ {'filename': ( 'fluorescence' + '_green_' + green_powers[green_voltage_num] + '_red_' + red_powers[red_voltage_num] + '_up.tif'), 'channels': num_delays, 'slices': num_delay_scan_repetitions, }]) daq.play_voltages(voltages, block=True) finally: # Shut everything down. This can be important! daq.close() idp.close()
objective = 'oil' # Choose 'air' or 'oil' # 'air':0.98 for best correction collar setting of 0.19 for Argolight # 'oil':1.45 z_ratio = {'air': 0.98, 'oil': 1.45}[objective] # Z step size half amplitude focus = 0 z_step = 10 # microns, relative to current set point dmi8_z_step = -z_step # insert can only move away so match polarity here insert_piezo_z_step = z_step rr_piezo_z_step = -z_step * z_ratio # microns, scaled piezo step size # Initialize hardware idp = image_data_pipeline.Image_Data_Pipeline( num_buffers=1, buffer_shape=(num_frames, roi['bottom'] - roi['top'] + 1, roi['right'] - roi['left'] + 1), camera_child_process=pco_edge_camera_child_process) idp.apply_camera_settings(exposure_time_microseconds=exposure_ms * 1000, trigger='external_trigger', preframes=0, region_of_interest=roi) ao = ni.Analog_Out( num_channels='all', rate=1e5, # Voltages per second daq_type='6733', board_name='Dev1') dmi8 = leica_scope.DMI_8_Microscope(dmi8_com_port) # insert_piezo will be controlled via analog and should be # setup manually using manufacturer software rr_piezo = physik_instrumente.E753_Z_Piezo(which_port=rr_piezo_com_port,