def open(self) -> None: """Doc.""" try: self.open_instrument() except IOError as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self)
def _fit_and_get_param_dict(fit_func, x, y, p0, **kwargs) -> FitParams: """Doc.""" try: popt, pcov = opt.curve_fit(fit_func, x, y, p0=p0, **kwargs) except (RuntimeWarning, RuntimeError, opt.OptimizeWarning) as exc: raise FitError(err_hndlr(exc, sys._getframe(), None, lvl="debug")) func_name = fit_func.__name__ beta = popt try: beta_error = np.sqrt(np.diag(pcov)) except Exception as exc: raise FitError(err_hndlr(exc, sys._getframe(), None, lvl="debug")) sigma = kwargs.get("sigma", 1) chi_sq_arr = np.square((fit_func(x, *beta) - y) / sigma) try: chi_sq_norm = chi_sq_arr.sum() / x.size except AttributeError: # x is a tuple (2D Gaussian) chi_sq_norm = chi_sq_arr.sum() / x[0].size return FitParams( func_name, beta, beta_error, x, y, sigma, kwargs.get("x_limits", Limits()), kwargs.get("y_limits", Limits()), chi_sq_norm, )
def __init__(self, param_dict, scanners_ai_tasks): super().__init__( param_dict, task_types=("ci", ), ) try: cont_ai_task = [ task for task in scanners_ai_tasks if (task.name == "Continuous AI") ][0] self.ai_cont_rate = cont_ai_task.timing.samp_clk_rate self.ai_cont_src = cont_ai_task.timing.samp_clk_term except IndexError: exc = DeviceError( f"{self.log_ref} can't be synced because scanners failed to Initialize" ) err_hndlr(exc, sys._getframe(), locals(), dvc=self) else: self.cont_read_buffer = np.zeros(shape=(self.CONT_READ_BFFR_SZ, ), dtype=np.uint32) self.last_avg_time = time.perf_counter() self.num_reads_since_avg = 0 self.ci_chan_specs = { "name_to_assign_to_channel": "photon counter", "counter": self.address, "edge": ni_consts.Edge.RISING, "initial_count": 0, "count_direction": ni_consts.CountDirection.COUNT_UP, } with suppress(DeviceError): self.start_continuous_read_task() self.toggle_led_and_switch(True)
def get_status(self): """Doc.""" try: return self.get_queue_status() except Exception as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self)
def __init__(self, param_dict): [setattr(self, key, val) for key, val in param_dict.items()] self.log_ref = param_dict["log_ref"] self._inst = None if not list_instruments(module="cameras"): exc = IOError("No UC480 cameras detected.") err_hndlr(exc, sys._getframe(), locals(), dvc=self)
def __init__(self, param_dict): super().__init__(param_dict=param_dict, ) try: self.open_instrument() except IOError as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self) else: self.init_data() self.purge()
def __init__(self, param_dict, task_types, **kwargs): [setattr(self, key, val) for key, val in param_dict.items()] self.task_types = task_types self.tasks = SimpleNamespace(**{type: [] for type in task_types}) try: len(ni.system.system.System().devices) except FileNotFoundError as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self)
def toggle(self, is_being_switched_on): """Doc.""" try: self.open_instrument( ) if is_being_switched_on else self.close_instrument() except IOError as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self) else: self.toggle_led_and_switch(is_being_switched_on) self.state = is_being_switched_on
def set_auto_exposure(self, should_turn_on: bool) -> None: """Doc.""" try: self._inst.set_auto_exposure(should_turn_on) except uc480.UC480Error: exc = IOError( f"{self.log_ref} was not properly closed.\nRestart to fix.") err_hndlr(exc, sys._getframe(), locals(), dvc=self) else: self.is_auto_exposure_on = should_turn_on
def laser_toggle(self, is_being_switched_on): """Doc.""" cmnd = f"setLDenable {int(is_being_switched_on)}" try: self.write(cmnd) except Exception as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self) else: self.emission_state = is_being_switched_on self.change_icons("on" if is_being_switched_on else "off")
async def timeout(self) -> None: """awaits all individual async loops, each with its own repeat time.""" try: await asyncio.gather( self._read_ci_and_ai(), self._update_dep(), self._update_main_gui(), self._update_video(), ) except Exception as exc: err_hndlr(exc, sys._getframe(), locals()) logging.debug("timeout function exited")
def toggle(self, is_being_switched_on): """Doc.""" try: self.digital_write(self.address, is_being_switched_on) except DaqError: exc = IOError( f"NI device address ({self.address}) is wrong, or data acquisition board is unplugged" ) err_hndlr(exc, sys._getframe(), locals(), dvc=self) else: self.toggle_led_and_switch(is_being_switched_on) self.state = is_being_switched_on
def get_image(self, should_display=True) -> np.ndarray: """Doc.""" try: if self.is_in_video_mode: self.latest_image = np.flipud((self.get_latest_frame())) else: self.latest_image = np.flipud((self.grab_image())) except IOError as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self) else: if should_display: self.display.obj.display_image(self.latest_image, cursor=True) return self.latest_image
async def move(self, dir, steps): """Doc.""" cmd_dict = { "UP": f"my {-steps}", "DOWN": f"my {steps}", "LEFT": f"mx {steps}", "RIGHT": f"mx {-steps}", } try: self.write(cmd_dict[dir]) await asyncio.sleep(500 * 1e-3) self.write("ryx ") # release except Exception as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self)
def start_scan_read_task(self, samp_clk_cnfg, timing_params) -> None: """Doc.""" try: self.close_tasks("ai") self.create_ai_task( name="Continuous AI", address=self.ai_x_addr, chan_specs=self.ai_chan_specs + self.ao_int_chan_specs, samp_clk_cnfg=samp_clk_cnfg, timing_params=timing_params, ) self.start_tasks("ai") except DaqError as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self)
def toggle(self, is_being_switched_on, **kwargs): """Doc.""" try: if is_being_switched_on: self.open_instrument(model=self.model_query) self.laser_toggle(False) else: if self.state is True: self.laser_toggle(False) self.close_instrument() except IOError as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self) else: self.toggle_led_and_switch(is_being_switched_on, **kwargs) self.state = is_being_switched_on
def toggle(self, is_being_switched_on): """Doc.""" try: if is_being_switched_on: self._start_co_clock_sync() else: self.close_all_tasks() except DaqError: exc = IOError( f"NI device address ({self.address}) is wrong, or data acquisition board is unplugged" ) err_hndlr(exc, sys._getframe(), locals(), dvc=self) else: self.toggle_led_and_switch(is_being_switched_on) self.state = is_being_switched_on
def set_power(self, value_mW): """Doc.""" # check that value is within range if value_mW in self.power_limits_mW: try: # change the mode to power cmnd = "powerenable 1" self.write(cmnd) # then set the power cmnd = f"setpower 0 {value_mW}" self.write(cmnd) except Exception as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self) else: Error(custom_txt=f"Power out of range {self.power_limits_mW}" ).display()
def get_prop(self, prop): """Doc.""" prop_cmnd_dict = { "temp": "SHGtemp", "curr": "LDcurrent 1", "pow": "power 0", } cmnd = prop_cmnd_dict[prop] try: self.flush() # get fresh response response = self.query(cmnd) except IOError as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self) else: return response
def toggle_video(self, should_turn_on: bool, keep_off=False, **kwargs) -> bool: """Doc.""" if keep_off: should_turn_on = False try: self.toggle_video_mode(should_turn_on, **kwargs) self.toggle_led_and_switch(should_turn_on) self.is_in_video_mode = should_turn_on return should_turn_on except IOError as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self) return not should_turn_on
def set_current(self, value_mA): """Doc.""" # check that value is within range if value_mA in self.current_limits_mA: try: # change the mode to power cmnd = "powerenable 0" self.write(cmnd) # then set the power cmnd = f"setLDcur 1 {value_mA}" self.write(cmnd) except Exception as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self) else: Error(custom_txt=f"Current out of range {self.current_limits_mA}" ).display()
def smooth_start(axis: str, ao_chan_specs: list, final_pos: float, step_sz: float = 0.25) -> None: """Doc.""" # NOTE: Ask Oleg why we used 40 steps in LabVIEW (this is why I use a step size of 10/40 V) try: init_pos = self.ai_buffer[-1][3:][self.AXIS_INDEX[axis]] except IndexError: init_pos = self.last_int_ao[self.AXIS_INDEX[axis]] total_dist = abs(final_pos - init_pos) n_steps = div_ceil(total_dist, step_sz) if n_steps < 2: # one small step needs no smoothing return else: ao_data = np.linspace(init_pos, final_pos, n_steps) # move task_name = "Smooth AO Z" try: self.close_tasks("ao") ao_task = self.create_ao_task( name=task_name, chan_specs=ao_chan_specs, samp_clk_cnfg={ "rate": self. MIN_OUTPUT_RATE_Hz, # WHY? see CreateAOTask.vi "samps_per_chan": n_steps, "sample_mode": ni_consts.AcquisitionType.FINITE, }, ) ao_data = self._limit_ao_data(ao_task, ao_data) self.analog_write(task_name, ao_data, auto_start=False) self.start_tasks("ao") self.wait_for_task("ao", task_name) self.close_tasks("ao") except Exception as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self)
def start_scan_read_task(self, samp_clk_cnfg, timing_params) -> None: """Doc.""" try: self.close_tasks("ci") self.create_ci_task( name="Scan CI", chan_specs=self.ci_chan_specs, chan_xtra_params={ "ci_count_edges_term": self.CI_cnt_edges_term, "ci_data_xfer_mech": ni_consts.DataTransferActiveTransferMode.DMA, }, samp_clk_cnfg=samp_clk_cnfg, timing_params=timing_params, ) self.start_tasks("ci") except DaqError as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self)
def start_continuous_read_task(self) -> None: """Doc.""" try: self.close_tasks("ai") self.create_ai_task( name="Continuous AI", address=self.ai_x_addr, chan_specs=self.ai_chan_specs + self.ao_int_chan_specs, samp_clk_cnfg={ "rate": self.MIN_OUTPUT_RATE_Hz, "sample_mode": ni_consts.AcquisitionType.CONTINUOUS, "samps_per_chan": self.CONT_READ_BFFR_SZ, }, ) self.init_ai_buffer() self.start_tasks("ai") except IOError as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self) else: self.toggle_led_and_switch(False)
def set_parameter(self, name, value) -> None: """Doc.""" if name not in {"pixel_clock", "framerate", "exposure"}: raise ValueError(f"Unknown parameter '{name}'.") valid_value = Limits(getattr(self, f"{name}_range")).clamp(value) try: if name == "pixel_clock": self._inst._dev.PixelClock(uc480.lib.PIXELCLOCK_CMD_SET, int(valid_value)) self.update_parameter_ranges() elif name == "framerate": self._inst._dev.SetFrameRate(valid_value) self.update_parameter_ranges() elif name == "exposure": self._inst._set_exposure(f"{valid_value}ms") except uc480.UC480Error: exc = IOError( f"{self.log_ref} was not properly closed.\nRestart to fix.") err_hndlr(exc, sys._getframe(), locals(), dvc=self)
def start_continuous_read_task(self) -> None: """Doc.""" try: self.close_tasks("ci") self.create_ci_task( name="Continuous CI", chan_specs=self.ci_chan_specs, chan_xtra_params={ "ci_count_edges_term": self.CI_cnt_edges_term }, samp_clk_cnfg={ "rate": self.ai_cont_rate, "source": self.ai_cont_src, "sample_mode": ni_consts.AcquisitionType.CONTINUOUS, "samps_per_chan": self.CONT_READ_BFFR_SZ, }, ) self.init_ci_buffer() self.start_tasks("ci") except DaqError as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self)
def disp_ACF(self): """Doc.""" def compute_acf(data): """Doc.""" s = SolutionSFCSMeasurement() p = s.process_data_file(file_dict=self.prep_data_dict(), ignore_coarse_fine=True) s.data.append(p) s.correlate_and_average(cf_name=self.laser_mode) return s try: s = compute_acf(self.data_dvc.data) except RuntimeWarning as exc: # RuntimeWarning - some sort of zero-division in _calculate_weighted_avg # (due to invalid data during beam obstruction) errors.err_hndlr(exc, sys._getframe(), locals()) except Exception as exc: print("THIS SHOULD NOT HAPPEN, HANDLE THE EXCEPTION PROPERLY!") errors.err_hndlr(exc, sys._getframe(), locals()) else: cf = s.cf[self.laser_mode] try: cf.fit_correlation_function() except fit_tools.FitError as exc: # fit failed errors.err_hndlr(exc, sys._getframe(), locals(), lvl="debug") self.fit_led.set(self.icon_dict["led_red"]) g0, tau = cf.g0, 0.1 self.g0_wdgt.set(g0) self.tau_wdgt.set(0) self.plot_wdgt.obj.plot_acfs((cf.lag, "lag"), cf.avg_cf_cr, g0) else: # fit succeeded self.fit_led.set(self.icon_dict["led_off"]) fp = cf.fit_params["diffusion_3d_fit"] g0, tau, _ = fp.beta fit_func = getattr(fit_tools, fp.func_name) self.g0_wdgt.set(g0) self.tau_wdgt.set(tau * 1e3) self.plot_wdgt.obj.plot_acfs((fp.x, "lag"), fp.y, g0, should_autoscale=True) y_fit = fit_func(cf.lag, *fp.beta) self.plot_wdgt.obj.plot(cf.lag, y_fit, "-.r") logging.info( f"Aligning ({self.laser_mode}): g0: {g0/1e3:.1f}K, tau: {tau*1e3:.1f} us." )
async def run(self): """Doc.""" # initialize gui start/end times self.set_current_and_end_times() # turn on lasers try: await self.toggle_lasers() except (MeasurementError, errors.DeviceError) as exc: await self.stop() self.type = None errors.err_hndlr(exc, sys._getframe(), locals()) return try: if self.scanning: self.setup_scan() self._app.gui.main.impl.device_toggle("pixel_clock", leave_on=True) # make the circular ai buffer clip as long as the ao buffer self.scanners_dvc.init_ai_buffer(type="circular", size=self.ao_buffer.shape[1]) self.counter_dvc.init_ci_buffer() else: self.scanners_dvc.init_ai_buffer() except errors.DeviceError as exc: await self.stop() errors.err_hndlr(exc, sys._getframe(), locals()) return else: self.is_running = True self.start_time = time.perf_counter() self.time_passed_s = 0 file_num = 1 logging.info(f"Running {self.type} measurement") try: while self.is_running and self.time_passed_s < self.duration_s: # initialize data buffer self.data_dvc.init_data() self.data_dvc.purge_buffers() if self.scanning: self.counter_dvc.init_ci_buffer() # re-start scan for each file self.scanners_dvc.init_ai_buffer( type="circular", size=self.ao_buffer.shape[1]) self.init_scan_tasks("CONTINUOUS") self.scanners_dvc.start_tasks("ao") else: self.scanners_dvc.init_ai_buffer() self.file_num_wdgt.set(file_num) logging.debug("FPGA reading starts.") # reading if self.repeat: await self.record_data(self.start_time, timed=True) else: await self.record_data(self.start_time, timed=True, size_limited=True) logging.debug("FPGA reading finished.") # collect final ai/CI self.counter_dvc.fill_ci_buffer() self.scanners_dvc.fill_ai_buffer() # case aligning and not manually stopped if self.repeat and self.is_running: self.disp_ACF() # reset measurement self.set_current_and_end_times() self.start_time = time.perf_counter() self.time_passed_s = 0 # case final alignment and not manually stopped elif self.final and self.is_running: self.disp_ACF() self.save_data(self.prep_data_dict(), self.build_filename(0)) # case regular measurement and finished file or measurement elif not self.repeat: self.save_data(self.prep_data_dict(), self.build_filename(file_num)) if self.scanning: self.scanners_dvc.init_ai_buffer( type="circular", size=self.ao_buffer.shape[1]) file_num += 1 except Exception as exc: # TESTESTEST print("THIS SHOULD NOT HAPPEN!") errors.err_hndlr(exc, sys._getframe(), locals()) if self.is_running: # if not manually stopped await self.stop() self.type = None
async def run(self): """Doc.""" self.setup_scan() try: await self.toggle_lasers() self.data_dvc.init_data() self.data_dvc.purge_buffers() self._app.gui.main.impl.device_toggle("pixel_clock", leave_on=True) self.scanners_dvc.init_ai_buffer(type="inf") self.counter_dvc.init_ci_buffer(type="inf") except (MeasurementError, errors.DeviceError) as exc: await self.stop() self.type = None errors.err_hndlr(exc, sys._getframe(), locals()) return else: n_planes = self.scan_params.n_planes self.plane_data = [] self.start_time = time.perf_counter() self.time_passed_s = 0 self.is_running = True logging.info(f"Running {self.type} measurement") # start all tasks (AO, AI, CI) self.init_scan_tasks("FINITE") self.scanners_dvc.start_tasks("ao") try: for plane_idx in range(n_planes): if self.is_running: self.change_plane(plane_idx) self.curr_plane_wdgt.set(plane_idx) self.curr_plane = plane_idx # Re-start only AO self.init_scan_tasks("FINITE", ao_only=True) self.scanners_dvc.start_tasks("ao") # recording await self.record_data(self.start_time, timed=False) # collect final ai/CI self.counter_dvc.fill_ci_buffer() self.scanners_dvc.fill_ai_buffer() else: break except MeasurementError as exc: await self.stop() errors.err_hndlr(exc, sys._getframe(), locals()) return except Exception as exc: # TESTESTEST print("THIS SHOULD NOT HAPPEN!") errors.err_hndlr(exc, sys._getframe(), locals()) # finished measurement if self.is_running: # if not manually stopped # prepare data data_dict = self.prep_data_dict() if self.always_save: # save data self.save_data(data_dict, self.build_filename()) self.keep_last_meas(data_dict) # show middle plane mid_plane = int(len(self.scan_params.set_pnts_planes) / 2) self.plane_shown.set(mid_plane) self.plane_choice.set(mid_plane) should_display_autocross = self.scan_params.auto_cross and ( self.laser_mode == "exc") self._app.gui.main.impl.disp_plane_img( auto_cross=should_display_autocross) if self.is_running: # if not manually before completion await self.stop() self.type = None
def start_write_task( self, ao_data: np.ndarray, type: str, samp_clk_cnfg_xy: dict = {}, samp_clk_cnfg_z: dict = {}, start=True, ) -> None: """Doc.""" def smooth_start(axis: str, ao_chan_specs: list, final_pos: float, step_sz: float = 0.25) -> None: """Doc.""" # NOTE: Ask Oleg why we used 40 steps in LabVIEW (this is why I use a step size of 10/40 V) try: init_pos = self.ai_buffer[-1][3:][self.AXIS_INDEX[axis]] except IndexError: init_pos = self.last_int_ao[self.AXIS_INDEX[axis]] total_dist = abs(final_pos - init_pos) n_steps = div_ceil(total_dist, step_sz) if n_steps < 2: # one small step needs no smoothing return else: ao_data = np.linspace(init_pos, final_pos, n_steps) # move task_name = "Smooth AO Z" try: self.close_tasks("ao") ao_task = self.create_ao_task( name=task_name, chan_specs=ao_chan_specs, samp_clk_cnfg={ "rate": self. MIN_OUTPUT_RATE_Hz, # WHY? see CreateAOTask.vi "samps_per_chan": n_steps, "sample_mode": ni_consts.AcquisitionType.FINITE, }, ) ao_data = self._limit_ao_data(ao_task, ao_data) self.analog_write(task_name, ao_data, auto_start=False) self.start_tasks("ao") self.wait_for_task("ao", task_name) self.close_tasks("ao") except Exception as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self) axes_to_use = self.AXES_TO_BOOL_TUPLE_DICT[type] xy_chan_spcs = [] z_chan_spcs = [] ao_data_xy = np.empty(shape=(0, )) ao_data_row_idx = 0 for ax, is_ax_used, ax_chn_spcs in zip("XYZ", axes_to_use, self.ao_chan_specs): if is_ax_used: if ax in "XY": xy_chan_spcs.append(ax_chn_spcs) if ao_data_xy.size == 0: # first concatenate the X/Y data to empty array to have 1D array ao_data_xy = np.concatenate( (ao_data_xy, ao_data[ao_data_row_idx])) else: # then, if XY scan, stack the Y data below the X data to have 2D array ao_data_xy = np.vstack( (ao_data_xy, ao_data[ao_data_row_idx])) ao_data_row_idx += 1 else: # "Z" z_chan_spcs.append(ax_chn_spcs) ao_data_z = ao_data[ao_data_row_idx] # start smooth if z_chan_spcs: smooth_start(axis="z", ao_chan_specs=z_chan_spcs, final_pos=ao_data_z[0]) try: self.close_tasks("ao") if xy_chan_spcs: xy_task_name = "AO XY" ao_task = self.create_ao_task( name=xy_task_name, chan_specs=xy_chan_spcs, samp_clk_cnfg=samp_clk_cnfg_xy, ) ao_data_xy = self._limit_ao_data(ao_task, ao_data_xy) ao_data_xy = self._diff_vltg_data(ao_data_xy) self.analog_write(xy_task_name, ao_data_xy) if z_chan_spcs: z_task_name = "AO Z" ao_task = self.create_ao_task( name=z_task_name, chan_specs=z_chan_spcs, samp_clk_cnfg=samp_clk_cnfg_z, ) ao_data_z = self._limit_ao_data(ao_task, ao_data_z) self.analog_write(z_task_name, ao_data_z) if start is True: self.start_tasks("ao") except DaqError as exc: err_hndlr(exc, sys._getframe(), locals(), dvc=self) else: self.toggle_led_and_switch(True)