def on_acquisition(self, evt): """ Start the acquisition (really) Similar to win.acquisition.on_acquire() """ # Time-resolved data cannot be saved in .ome.tiff format for now # OME-TIFF wants to save each time data on a separate "page", which causes too many pages. has_temporal = False for s in self._tab_data_model.streams.value: if (isinstance(s, ScannedTemporalSettingsStream) or isinstance(s, ScannedTCSettingsStream) or isinstance(s, TemporalSpectrumSettingsStream)): has_temporal = True if (self.conf.last_format == 'TIFF' or self.conf.last_format == 'Serialized TIFF') and has_temporal: raise NotImplementedError("Cannot save temporal data in %s format, data format must be HDF5." \ % self.conf.last_format) self._pause_streams() self.btn_acquire.Disable() self.btn_cancel.Enable() self._main_data_model.is_acquiring.value = True self.gauge_acq.Show() self.btn_cancel.Show() self._show_status_icons(None) self._tab_panel.Layout() # to put the gauge at the right place # start acquisition + connect events to callback self.acq_future = acq.acquire(self._tab_data_model.acquisitionStreams) self._acq_future_connector = ProgressiveFutureConnector( self.acq_future, self.gauge_acq, self.lbl_acqestimate) self.acq_future.add_done_callback(self.on_acquisition_done)
def showProgress(self, future): """ Shows a progress bar, based on the status of the progressive future given. As long as the future is not finished, the buttons are disabled. future (None or Future): The progressive future to show the progress with the progress bar. If future is None, it will hide the progress bar. If future is cancellable, show a cancel button next to the progress bar. """ if future is not None and not future.cancelled(): self.current_future = future self.enable_buttons(False) self.Layout() self.Update() if self.current_future is None: self._acq_future_connector = None return else: if hasattr(self.current_future, "add_update_callback"): self._acq_future_connector = ProgressiveFutureConnector( self.current_future, self.gauge_progress, self.lbl_gauge) else: # TODO: just pulse the gauge at a "good" frequency (need to use a timer) self.gauge_progress.Pulse() if hasattr(self.current_future, 'task_canceller'): self.btn_cancel.Enable() else: self.btn_cancel.Disable() future.add_done_callback(self._on_future_done)
def _on_fine_align(self, event): """ Called when the "Fine alignment" button is clicked """ self._pause() main_data = self._main_data_model main_data.is_acquiring.value = True logging.debug("Starting overlay procedure") f = align.FindOverlay(self.OVRL_REPETITION, main_data.fineAlignDwellTime.value, self.OVRL_MAX_DIFF, main_data.ebeam, main_data.ccd, main_data.sed, skew=True) logging.debug("Overlay procedure is running...") self._acq_future = f # Transform Fine alignment button into cancel self._tab_panel.btn_fine_align.Bind(wx.EVT_BUTTON, self._on_cancel) self._tab_panel.btn_fine_align.Label = "Cancel" # Set up progress bar self._tab_panel.lbl_fine_align.Hide() self._tab_panel.gauge_fine_align.Show() self._sizer.Layout() self._faf_connector = ProgressiveFutureConnector( f, self._tab_panel.gauge_fine_align) f.add_done_callback(self._on_fa_done)
def on_calibrate(self, evt): """ Start or cancel the calibrations for all set regions of calibrations (ROC) when the calibration button is triggered. A progressive future for all rocs is created. :param evt: (GenButtonEvent) Button triggered. """ # check if cancelled if self._tab_data.is_calibrating.value: logging.debug("Calibration was cancelled.") align_fastem._executor.cancel() # all the rest will be handled by on_alignment_done() # FIXME cancelling does not yet display the correct label in the gui return # calibrate self._tab_data.is_calibrating.unsubscribe(self._on_is_acquiring) # Briefly unsubscribe as don't need to know about this event (is_acquiring = True): # It would disable the calibration button, but want to be able to still cancel calibration. self._tab_data.is_calibrating.value = True # make sure the acquire/tab buttons are disabled self._tab_data.is_calibrating.subscribe(self._on_is_acquiring) self._on_calibration_state() # update the controls in the panel futures = {} try: for roc_num in sorted(self.calibration_regions.value.keys()): # check if calibration region (ROC) on scintillator is set (undefined = not set) roc = self.calibration_regions.value[roc_num] if roc.coordinates.value != stream.UNDEFINED_ROI: # calculate the center position of the ROC (half field right/bottom # compared to top/left corner in view) xmin, ymin, _, _ = roc.coordinates.value field_size = (self._tab_data.main.multibeam.resolution.value[0] * self._tab_data.main.multibeam.pixelSize.value[0], self._tab_data.main.multibeam.resolution.value[1] * self._tab_data.main.multibeam.pixelSize.value[1]) roc_center = (xmin + field_size[0] / 2, ymin + field_size[1] / 2) # start calibration f = align.fastem.align(self._main_data_model.ebeam, self._main_data_model.multibeam, self._main_data_model.descanner, self._main_data_model.mppc, self._main_data_model.stage, self._main_data_model.ccd, self._main_data_model.beamshift, self._main_data_model.det_rotator, calibrations=self.calibrations, stage_pos=roc_center) t = align.fastem.estimate_calibration_time(self.calibrations) # also handles cancelling and exceptions f.add_done_callback(partial(self._on_calibration_done, roc_num=roc_num)) futures[f] = t calib_future = model.ProgressiveBatchFuture(futures) # also handles cancelling and exceptions calib_future.add_done_callback(self._on_batch_calibrations_done) # connect the future to the progress bar and its label self._future_connector = ProgressiveFutureConnector(calib_future, self.gauge, self.label, full=False) except Exception as ex: # In case all calibrations failed to start logging.warning("Calibration failed with %s", ex) for f in futures.keys(): f.cancel() # cancel all sub-futures self._main_data_model.is_acquiring.value = False self._update_calibration_controls("Calibrations failed.")
def _on_auto_center(self, event): """ Called when the "Auto centering" button is clicked """ # Force spot mode: not needed by the code, but makes sense for the user self._tab_data_model.tool.value = guimod.TOOL_SPOT self._pause() main_data = self._main_data_model main_data.is_acquiring.value = True logging.debug("Starting auto centering procedure") f = align.AlignSpot(main_data.ccd, self._aligner_xy, main_data.ebeam, main_data.focus, type=OBJECTIVE_MOVE) logging.debug("Auto centering is running...") self._acq_future = f # Transform auto centering button into cancel self._tab_panel.btn_auto_center.Bind(wx.EVT_BUTTON, self._on_cancel) self._tab_panel.btn_auto_center.Label = "Cancel" # Set up progress bar self._tab_panel.lbl_auto_center.Hide() self._tab_panel.gauge_auto_center.Show() self._sizer.Layout() self._acf_connector = ProgressiveFutureConnector( f, self._tab_panel.gauge_auto_center) f.add_done_callback(self._on_ac_done)
def on_calibrate(self, evt): """ Start or cancel the calibration when the button is triggered. :param evt: (GenButtonEvent) Button triggered. """ # check if cancelled if self._tab_data.is_calibrating.value: logging.debug("Calibration was cancelled.") align_fastem._executor.cancel() # all the rest will be handled by on_alignment_done() return # calibrate self._tab_data.is_calibrating.unsubscribe(self._on_is_acquiring) # Don't catch this event (is_calibrating = True) - this would disable the button, # but it should be still enabled in order to be able to cancel the calibration self._tab_data.is_calibrating.value = True # make sure the acquire/tab buttons are disabled self._tab_data.is_calibrating.subscribe(self._on_is_acquiring) self._on_calibration_state() # update the controls in the panel # Start alignment f = align.fastem.align(self._main_data_model.ebeam, self._main_data_model.multibeam, self._main_data_model.descanner, self._main_data_model.mppc, self._main_data_model.stage, self._main_data_model.ccd, self._main_data_model.beamshift, self._main_data_model.det_rotator, calibrations=self.calibrations) f.add_done_callback(self._on_calibration_done) # also handles cancelling and exceptions # connect the future to the progress bar and its label self._future_connector = ProgressiveFutureConnector(f, self.gauge, self.label, full=False)
def on_acquisition(self, evt): """ Start the acquisition (really) """ self._main_data_model.is_acquiring.value = True self.btn_acquire.Enable(False) self.btn_cancel.Enable(True) self.btn_cancel.Show() self.gauge_acq.Show() self._show_status_icons(None) self.gauge_acq.Range = self.roa_count self.gauge_acq.Value = 0 # Acquire ROAs for all projects fs = {} for p in self._tab_data_model.projects.value: ppath = os.path.join(self.path, p.name.value) # <acquisition date>/<project name> for roa in p.roas.value: f = fastem.acquire(roa, ppath, self._main_data_model.ebeam, self._main_data_model.multibeam, self._main_data_model.descanner, self._main_data_model.mppc, self._main_data_model.stage, self._main_data_model.ccd, self._main_data_model.beamshift, self._main_data_model.lens) t = roa.estimate_acquisition_time() fs[f] = t self.acq_future = model.ProgressiveBatchFuture(fs) self._fs_connector = ProgressiveFutureConnector(self.acq_future, self.gauge_acq, self.lbl_acqestimate) self.acq_future.add_done_callback(self.on_acquisition_done)
def on_acquire(self, evt): """ Start the actual acquisition """ logging.info("Acquire button clicked, starting acquisition") acq_streams = self.get_acq_streams() if not acq_streams: logging.info("No stream to acquire, ending immediately") self.on_close( evt) # Nothing to do, so it's the same as closing the window self.acquiring = True # Adjust view FoV to the whole area, so that it's possible to follow the acquisition self._fit_view_to_area() self.btn_secom_acquire.Disable() # Freeze all the settings so that it's not possible to change anything self._pause_settings() self.gauge_acq.Show() self.Layout() # to put the gauge at the right place # For now, always indicate the best quality if self._main_data_model.opm: self._main_data_model.opm.setAcqQuality(path.ACQ_QUALITY_BEST) zlevels = self._get_zstack_levels() focus_mtd = FocusingMethod.MAX_INTENSITY_PROJECTION if zlevels else FocusingMethod.NONE if self.filename_tiles: logging.info("Acquisition tiles logged at %s", self.filename_tiles) os.makedirs(os.path.dirname(self.filename_tiles)) self.acq_future = stitching.acquireTiledArea( acq_streams, self._main_data_model.stage, area=self.area, overlap=self.overlap, settings_obs=self._main_data_model.settings_obs, log_path=self.filename_tiles, weaver=WEAVER_COLLAGE_REVERSE, zlevels=zlevels, focusing_method=focus_mtd) self._acq_future_connector = ProgressiveFutureConnector( self.acq_future, self.gauge_acq, self.lbl_acqestimate) # TODO: Build-up the complete image during the acquisition, so that the # progress can be followed live. self.acq_future.add_done_callback(self.on_acquisition_done) self.btn_cancel.SetLabel("Cancel") self.btn_cancel.Bind(wx.EVT_BUTTON, self.on_cancel)
def on_acquisition(self, evt): """ Start the acquisition (really) """ self.update_acquisition_time( ) # make sure we show the right label if the previous acquisition failed self._main_data_model.is_acquiring.value = True self.btn_acquire.Enable(False) self.btn_cancel.Enable(True) self.btn_cancel.Show() self.gauge_acq.Show() self.gauge_acq.Range = len( self._tab_data_model.selected_scintillators.value) self.gauge_acq.Value = 0 # Acquire ROAs for all projects acq_futures = {} for num in self._tab_data_model.selected_scintillators.value: center = self._tab_data_model.main.scintillator_positions[num] sz = self._tab_data_model.main.scintillator_size coords = (center[0] - sz[0] / 2, center[1] - sz[1] / 2, center[0] + sz[0] / 2, center[1] + sz[1] / 2) try: f = fastem.acquireTiledArea( self._tab_data_model.streams.value[0], self._main_data_model.stage, coords) t = fastem.estimateTiledAcquisitionTime( self._tab_data_model.streams.value[0], self._main_data_model.stage, coords) except Exception: logging.exception("Failed to start overview acquisition") # Try acquiring the other continue f.add_done_callback(partial(self.on_acquisition_done, num=num)) acq_futures[f] = t if acq_futures: self.acq_future = model.ProgressiveBatchFuture(acq_futures) self.acq_future.add_done_callback(self.full_acquisition_done) self._fs_connector = ProgressiveFutureConnector( self.acq_future, self.gauge_acq, self.lbl_acqestimate) else: # In case all acquisitions failed to start self._main_data_model.is_acquiring.value = False self._reset_acquisition_gui("Acquisition failed (see log panel).", level=logging.WARNING)
def on_acquire(self, evt): """ Start the actual acquisition """ if self.last_saved_file: # This means the button is actually "View" self._view_file() return logging.info("Acquire button clicked, starting acquisition") self.acquiring = True self.btn_secom_acquire.Disable() # disable estimation time updates during acquisition self._view.lastUpdate.unsubscribe(self.on_streams_changed) # Freeze all the settings so that it's not possible to change anything self._pause_settings() self.gauge_acq.Show() self.Layout() # to put the gauge at the right place # For now, always indicate the best quality (even if the preset is set # to "live") if self._main_data_model.opm: self._main_data_model.opm.setAcqQuality(path.ACQ_QUALITY_BEST) # Note: It should never be possible to reach here with no streams streams = self.get_acq_streams() v_streams = self._view.getStreams() # visible streams for s in streams: # Add extra viewable streams to view. However, do not add incompatible streams. if s not in v_streams and not isinstance(s, NON_SPATIAL_STREAMS): self._view.addStream(s) # Update the filename in the streams if hasattr(s, "filename"): pathname, base = os.path.split(self.filename.value) s.filename.value = base self.acq_future = acqmng.acquire(streams, self._main_data_model.settings_obs) self._acq_future_connector = ProgressiveFutureConnector(self.acq_future, self.gauge_acq, self.lbl_acqestimate) self.acq_future.add_done_callback(self.on_acquisition_done) self.btn_cancel.SetLabel("Cancel") self.btn_cancel.Bind(wx.EVT_BUTTON, self.on_cancel)
def __init__(self, parent, main_data, shid): xrcprogress_dialog.__init__(self, parent) # ProgressiveFuture for the ongoing calibration self._main_data = main_data self._shid = shid self.calib_future = None self._calib_future_connector = None self._started = False self.cancel_btn.Bind(wx.EVT_BUTTON, self.on_cancel) self.Bind(wx.EVT_CLOSE, self.on_close) self.info_txt.SetLabel("Calibration of the sample holder in progress") self.calib_future = DelphiCalibration(main_data) self._calib_future_connector = ProgressiveFutureConnector( self.calib_future, self.gauge, self.time_txt) self.calib_future.add_done_callback(self.on_calib_done) self.Fit()
def on_acquisition(self, evt): """ Start the acquisition (really) Similar to win.acquisition.on_acquire() """ # Time-resolved data cannot be saved in .ome.tiff format for now # OME-TIFF wants to save each time data on a separate "page", which causes too many pages. has_temporal = False for s in self._tab_data_model.streams.value: if (isinstance(s, ScannedTemporalSettingsStream) or isinstance(s, ScannedTCSettingsStream) or isinstance(s, TemporalSpectrumSettingsStream)): has_temporal = True # ADD the the overlay (live_update) in the SEM window which displays the SEM measurements of the current # acquisition if a stream is added and acquisition is started. for v in self._tab_data_model.visible_views.value: if hasattr(v, "stream_classes") and isinstance(self._tab_data_model.semStream, v.stream_classes): v.addStream(self._tab_data_model.semStream) if (self.conf.last_format == 'TIFF' or self.conf.last_format == 'Serialized TIFF') and has_temporal: raise NotImplementedError("Cannot save temporal data in %s format, data format must be HDF5." \ % self.conf.last_format) self._pause_streams() self.btn_acquire.Disable() self.btn_cancel.Enable() self._main_data_model.is_acquiring.value = True self.gauge_acq.Show() self.btn_cancel.Show() self._show_status_icons(None) self._tab_panel.Layout() # to put the gauge at the right place # start acquisition + connect events to callback self.acq_future = acqmng.acquire(self._tab_data_model.acquisitionStreams, self._main_data_model.settings_obs) self._acq_future_connector = ProgressiveFutureConnector(self.acq_future, self.gauge_acq, self.lbl_acqestimate) self.acq_future.add_done_callback(self.on_acquisition_done)
def on_acquisition(self, evt): """ Start the acquisition (really) Similar to win.acquisition.on_acquire() """ self._pause_streams() self.btn_acquire.Disable() self.btn_cancel.Enable() self._main_data_model.is_acquiring.value = True self.gauge_acq.Show() self.btn_cancel.Show() self._show_status_icons(None) self._tab_panel.Layout() # to put the gauge at the right place # start acquisition + connect events to callback streams = self._tab_data_model.acquisitionView.getStreams() self.acq_future = acq.acquire(streams) self._acq_future_connector = ProgressiveFutureConnector( self.acq_future, self.gauge_acq, self.lbl_acqestimate) self.acq_future.add_done_callback(self.on_acquisition_done)
def on_acquire(self, evt): """ Start the actual acquisition """ if self.last_saved_file: # This means the button is actually "View" self._view_file() return logging.info("Acquire button clicked, starting acquisition") self.btn_secom_acquire.Disable() # disable estimation time updates during acquisition self._view.lastUpdate.unsubscribe(self.on_streams_changed) # TODO: freeze all the settings so that it's not possible to change anything self._pause_settings() self.gauge_acq.Show() self.Layout() # to put the gauge at the right place # start acquisition + connect events to callback streams = self._view.getStreams() # Add the overlay stream if the fine alignment check box is checked if self.chkbox_fine_align.Value: streams.append(self._ovrl_stream) # Turn off the fan to avoid vibrations (in all acquisitions) self._set_fan(False) # It should never be possible to reach here with no streams self.acq_future = acq.acquire(streams) self._acq_future_connector = ProgressiveFutureConnector( self.acq_future, self.gauge_acq, self.lbl_acqestimate) self.acq_future.add_done_callback(self.on_acquisition_done) self.btn_cancel.SetLabel("Cancel") self.btn_cancel.Bind(wx.EVT_BUTTON, self.on_cancel)