def initialize_camera(self): """ Initialization function; starts communication with the sensor, pulling information such as capabilities, which are useful for further acquisition settings """ rich_print('Connecting to camera...', color='yellow') Initialize() self.serial_number = GetCameraSerialNumber() # Pull model and other capabilities struct self.check_capabilities() # Pull hardware attributes self.head_name = GetHeadModel() self.x_size, self.y_size = GetDetector() self.x_pixel_size, self.y_pixel_size = GetPixelSize() self.hardware_version = GetHardwareVersion() # Pull software attributes self.software_version = GetSoftwareVersion() if self.chatty: rich_print("Software version: ", self.software_version, color='cornflowerblue') # Pull important capability ranges self.temperature_range = GetTemperatureRange() self.emccd_gain_range = GetEMGainRange() self.number_of_preamp_gains = GetNumberPreAmpGains() self.preamp_gain_range = ( GetPreAmpGain(0), GetPreAmpGain(self.number_of_preamp_gains - 1), )
def grab_multiple(self, n_images, images, waitForNextBuffer=True): """Grab n_images into images array during buffered acquistion.""" # TODO: Catch timeout errors, check if abort, else keep trying. print(f"Camera configured in {self.camera.acquisition_mode} mode.") print(f"Actual readout time is {self.camera.readout_time} s.") print(f"Keep clean cycle time is {self.camera.keepClean_time} s.") if 'kinetic_series' in self.camera.acquisition_mode: print( f"Kinetics number is {self.camera.default_acquisition_attrs['number_kinetics']}." ) print( f"Actual kinetics period is {self.camera.kinetics_timing} s.") print(f"Actual exposure time is {self.camera.exposure_time} s.") print( f"Actual digitization speed (HSpeed) is {self.camera.horizontal_shift_speed} MHz." ) print(f"Actual vertical shift speed is {self.camera.vs_speed} us.") rich_print(f" ---> EMCCD Gain value is {self.camera.emccd_gain}.", color='magenta') if 'fast_kinetics' in self.camera.acquisition_mode: print( f"FK mode Kinetics Number is {self.camera.number_fast_kinetics}." ) print(f" ---> Attempting to grab {n_images} acquisition(s).") if 'single' in self.camera.acquisition_mode: for image_number in range(n_images): self.camera.acquire() print(f" {image_number}: Acquire complete") downloaded = self.camera.download_acquisition() print(f" {image_number}: Download complete") images.append(downloaded) self.camera.armed = True self.camera.armed = False print(f"Got {len(images)} of {n_images} acquisition(s).") elif 'fast_kinetics' in self.camera.acquisition_mode: nacquisitions = n_images // self.camera.number_fast_kinetics for image_number in range(nacquisitions): self.camera.acquire() print(f" {image_number}: Acquire complete") downloaded = self.camera.download_acquisition() print(f" {image_number}: Download complete") images.extend(list(downloaded)) self.camera.armed = True self.camera.armed = False # This last disarming may be redundant print( f"Got {len(images)} images in {nacquisitions} FK series acquisition(s)." ) else: self.camera.acquire() print(f" Acquire complete") downloaded = self.camera.download_acquisition() print( f" images {len(images)}-{len(images) + len(downloaded)}: Download complete" ) images.extend(list(downloaded)) self.camera.armed = False print(f"Got {len(images)} of {n_images} acquisition(s).")
def acquire(self): """ Carries down the acquisition, if the camera is armed and waits for an acquisition event for acquisition timeout (has to be in milliseconds), default to 5 seconds """ acquisition_timeout = self.acquisition_attributes[ 'acquisition_timeout'] def homemade_wait_for_acquisition(): self.acquisition_status = '' start_wait = time.time() while self.acquisition_status != 'DRV_IDLE': self.acquisition_status = GetStatus() # TODO: Also count the number of acquired (buffered) images and # stop when it matches the expected number of frames. t0 = time.time() - start_wait if t0 > acquisition_timeout * ms: rich_print( "homemade_wait_for_acquisition: timeout occured", color='firebrick', ) break time.sleep(0.05) if self.chatty: rich_print( f"Leaving homemade_wait with status {self.acquisition_status} ", color='goldenrod', ) rich_print( f"homemade_wait_for_acquisition: elapsed time {t0/ms} ms, out of max {acquisition_timeout} ms", color='goldenrod', ) if not self.armed: raise Exception("Cannot start acquisition until armed") else: self.acquisition_status = GetStatus() if 'DRV_IDLE' in self.acquisition_status: StartAcquisition() if self.chatty: rich_print( f"Waiting for {acquisition_timeout} ms for timeout ...", color='yellow', ) homemade_wait_for_acquisition() # Last chance, check if the acquisition is finished, update # acquisition status otherwise, abort and raise an error self.acquisition_status = GetStatus() self.armed = False if self.acquisition_status != 'DRV_IDLE': AbortAcquisition() raise AndorException('Acquisition aborted due to timeout')
def run(self): item = self.from_parent.get() x, y = item sys.stdout.write(repr(x)) sys.stderr.write(y) self.to_parent.put(item) os.system('echo hello from echo') # Wait some time here to reduce the chance of output arriving out of order, # which would break the tests even though we don't actually guarantee that the # order will come out right. time.sleep(0.2) # And now test logging: import logging logger = logging.Logger('test') logger.setLevel(logging.DEBUG) logger.addHandler(RichStreamHandler()) logger.info('this is a log message') # And now test rich printing rich_print('some test text', color='#123456', bold=True, italic=False)
def transition_to_manual(self): if self.function_table is None: return True elif not self.function_table: rich_print("no stop functions", color=GREY) return True rich_print("[running stop functions]", color=PURPLE) while self.function_table: t, name, function, args, kwargs = self.function_table.pop(0) assert t == 'stop' rich_print(f" t={t}: {name}()",color=BLUE) function(self.shot_context, t, *args, **kwargs) rich_print("[finished stop functions]", color=PURPLE) return True
def homemade_wait_for_acquisition(): self.acquisition_status = '' start_wait = time.time() while self.acquisition_status != 'DRV_IDLE': self.acquisition_status = GetStatus() # TODO: Also count the number of acquired (buffered) images and # stop when it matches the expected number of frames. t0 = time.time() - start_wait if t0 > acquisition_timeout * ms: rich_print( "homemade_wait_for_acquisition: timeout occured", color='firebrick', ) break time.sleep(0.05) if self.chatty: rich_print( f"Leaving homemade_wait with status {self.acquisition_status} ", color='goldenrod', ) rich_print( f"homemade_wait_for_acquisition: elapsed time {t0/ms} ms, out of max {acquisition_timeout} ms", color='goldenrod', )
def abort_acquisition(self): """Abort""" if self.chatty: rich_print("Debug: Abort Called", color='yellow') AbortAcquisition()
def setup_acquisition(self, added_attributes=None): """ Main acquisition configuration method. Available acquisition modes are below. The relevant methods are called with the corresponding acquisition attributes dictionary, then the camera is armed and ready """ if added_attributes is None: added_attributes = {} # Override default acquisition attrs with added ones self.acquisition_attributes = self.default_acquisition_attrs.copy() self.acquisition_attributes.update(added_attributes) self.acquisition_mode = self.acquisition_attributes['acquisition'] if self.acquisition_attributes['preamp']: self.enable_preamp(self.acquisition_attributes['preamp_gain']) if self.acquisition_attributes['emccd']: self.enable_emccd(self.acquisition_attributes['emccd_gain']) if self.acquisition_attributes['cooldown']: self.enable_cooldown( self.acquisition_attributes['temperature'], self.acquisition_attributes['water_cooling'], wait_until_stable=True, ) # Get current temperature and temperature status self.temperature, self.temperature_status = GetTemperatureF() if self.chatty: rich_print( f"""At setup_acquisition the temperature is: {self.temperature}; with status {self.temperature_status}""", color='magenta', ) # Available modes modes = { 'single': 1, 'accumulate': 2, 'kinetic_series': 3, 'fast_kinetics': 4, 'run_till_abort': 5, } self.setup_trigger(**self.acquisition_attributes) # Configure horizontal shifting (serial register clocks) self.setup_horizontal_shift() # Configure vertical shifting (image and storage area clocks) self.setup_vertical_shift() SetAcquisitionMode(modes[self.acquisition_mode]) # Configure added acquisition specific parameters if 'accumulate' in self.acquisition_mode: self.configure_accumulate(**self.acquisition_attributes) elif 'kinetic_series' in self.acquisition_mode: self.configure_kinetic_series(**self.acquisition_attributes) elif 'fast_kinetics' in self.acquisition_mode: self.configure_fast_kinetics(**self.acquisition_attributes) elif 'run_till_abort' in self.acquisition_mode: self.configure_run_till_abort(**self.acquisition_attributes) # Set exposure time, note that this may be overriden # by the readout, trigger or shutter timings thereafter SetExposureTime(self.acquisition_attributes['exposure_time']) self.setup_shutter(**self.acquisition_attributes) self.setup_readout(**self.acquisition_attributes) # Get actual timings self.exposure_time, self.accum_timing, self.kinetics_timing = GetAcquisitionTimings( ) if 'fast_kinetics' in self.acquisition_mode: self.exposure_time = GetFKExposureTime() # Arm sensor self.armed = True self.keepClean_time = GetKeepCleanTime() # Note: The GetReadOutTime call breaks in FK mode for unknown reasons if 'fast_kinetics' not in self.acquisition_mode: self.readout_time = GetReadOutTime() else: # Made up number, somehow FK doesn't work with GetReadOutTime() self.readout_time = 1000.0
def check_capabilities(self): """ Do checks based on the _AC dict """ # Pull the hardware noted capabilities self.andor_capabilities = GetCapabilities() self.model = camera_type.get_type(self.andor_capabilities.ulCameraType) self.acq_caps = acq_mode.check(self.andor_capabilities.ulAcqModes) self.read_caps = read_mode.check(self.andor_capabilities.ulReadModes) self.trig_caps = trigger_mode.check( self.andor_capabilities.ulTriggerModes) self.pixmode = pixel_mode.check(self.andor_capabilities.ulPixelMode) self.setfuncs = set_functions.check( self.andor_capabilities.ulSetFunctions) self.getfuncs = get_functions.check( self.andor_capabilities.ulGetFunctions) self.features = features.check(self.andor_capabilities.ulFeatures) self.emgain_caps = em_gain.check( self.andor_capabilities.ulEMGainCapability) if self.chatty: rich_print(f"Camera Capabilities", color='cornflowerblue') rich_print(f" acq_caps: {self.acq_caps}", color='lightsteelblue') rich_print(f" read_caps: {self.read_caps}", color='lightsteelblue') rich_print(f" trig_caps: {self.trig_caps}", color='lightsteelblue') rich_print(f" pixmode: {self.pixmode}", color='lightsteelblue') rich_print(f" model: {self.model}", color='goldenrod') rich_print(f" set funcs: {self.setfuncs}", color='firebrick') rich_print(f" get funcs: {self.getfuncs}", color='firebrick') rich_print(f" features: {self.features}", color='lightsteelblue') rich_print(f" emgain_caps: {self.emgain_caps}", color='lightsteelblue')
def transition_to_buffered(self, device_name, h5_file, initial_values, fresh): rich_print(f"====== new shot: {os.path.basename(h5_file)} ======", color=GREEN) with h5py.File(h5_file, 'r') as f: group = f[f'devices/{self.device_name}'] if 'FUNCTION_TABLE' not in group: self.function_table = None rich_print("[no functions]", color=GREY) return {} function_table = group['FUNCTION_TABLE'][:] self.function_table = deserialise_function_table( function_table, self.device_name ) self.shot_context = ShotContext(h5_file, self.device_name) if self.function_table[0][0] != 'start': rich_print("no start functions", color=GREY) return {} rich_print("[running start functions]", color=PURPLE) while self.function_table: t, name, function, args, kwargs = self.function_table[0] if t != 'start': break del self.function_table[0] rich_print(f" t={t}: {name}()", color=BLUE) function(self.shot_context, t, *args, **kwargs) rich_print("[finished start functions]", color=PURPLE) return {}