def clear_scan_context_fields() -> None:
     self.__roi_description.text = _("Scan context not active")
     self.__scan_label_widget.text = None
     self.__scan_specifier.scan_context = stem_controller.ScanContext()
     self.__scan_specifier.scan_count = 1
     self.__scan_specifier.size = None
     self.__scan_specifier.drift_interval_lines = 0
     self.__scan_specifier.drift_interval_scans = 0
     self.__acquire_button._widget.enabled = self.__acquisition_state == SequenceState.scanning  # focus will be on the SI data, so enable if scanning
     self.__scan_pixels = 0
    def _get_stem_controller_and_camera(self,
                                        initialize: bool = True,
                                        is_eels: bool = False):
        # this is simulator specific. replace this code but be sure to set up self.exposure and blanked and positioned
        # initial settings.
        self.exposure = 0.04

        instrument = InstrumentDevice.Instrument("usim_stem_controller")
        Registry.register_component(instrument, {"stem_controller"})

        camera_id = "usim_ronchigram_camera" if not is_eels else "usim_eels_camera"
        camera_type = "ronchigram" if not is_eels else "eels"
        camera_name = "uSim Camera"
        camera_settings = CameraDevice.CameraSettings(camera_id)
        camera_device = CameraDevice.Camera(camera_id, camera_type,
                                            camera_name, instrument)
        camera_hardware_source = camera_base.CameraHardwareSource(
            "usim_stem_controller", camera_device, camera_settings, None, None)
        if is_eels:
            camera_hardware_source.features["is_eels_camera"] = True
            camera_hardware_source.add_channel_processor(
                0, HardwareSource.SumProcessor(((0.25, 0.0), (0.5, 1.0))))
            # EELS camera only produces data if a valid scan context is presend in intrument controller, so set one up here
            scan_context = stem_controller.ScanContext()
            scan_context.update(Geometry.IntSize(128, 128),
                                Geometry.FloatPoint(), 10.0, 0.0)
            # This is the only method that allows access to the scan context
            instrument._set_scan_context_probe_position(
                scan_context, Geometry.FloatPoint(0.5, 0.5))
        camera_hardware_source.set_frame_parameters(
            0,
            camera_base.CameraFrameParameters({
                "exposure_ms": self.exposure * 1000,
                "binning": 2
            }))
        camera_hardware_source.set_frame_parameters(
            1,
            camera_base.CameraFrameParameters({
                "exposure_ms": self.exposure * 1000,
                "binning": 2
            }))
        camera_hardware_source.set_frame_parameters(
            2,
            camera_base.CameraFrameParameters({
                "exposure_ms":
                self.exposure * 1000 * 2,
                "binning":
                1
            }))
        camera_hardware_source.set_selected_profile_index(0)

        HardwareSource.HardwareSourceManager().register_hardware_source(
            camera_hardware_source)

        return instrument, camera_hardware_source
Exemple #3
0
    def __init__(self, instrument_id: str):
        super().__init__()
        self.priority = 20
        self.instrument_id = instrument_id
        self.property_changed_event = Event.Event()
        self.__camera_frame_event = threading.Event()
        self.__camera_frame_event_ack = threading.Event()

        # define the STEM geometry limits
        self.stage_size_nm = 1000
        self.max_defocus = 5000 / 1E9

        # define the samples
        self.__samples = [
            SampleSimulator.RectangleFlakeSample(self.stage_size_nm),
            SampleSimulator.AmorphousSample()
        ]
        self.__sample_index = 0

        self.__stage_position_m = Geometry.FloatPoint()
        self.__drift_controller = DriftController()
        self.__slit_in = False
        self.__energy_per_channel_eV = 0.5
        self.__beam_current = 200E-12  # 200 pA
        self.__blanked = False
        self.__ronchigram_shape = Geometry.IntSize(2048, 2048)
        self.__eels_shape = Geometry.IntSize(256, 1024)
        self.__scan_context = stem_controller.ScanContext()
        self.__probe_position = None
        self.__live_probe_position = None
        self.__sequence_progress = 0
        self._is_synchronized = False
        self.__lock = threading.Lock()
        self.__controls = dict()

        built_in_controls = self.__create_built_in_controls()
        for control in built_in_controls:
            self.add_control(control)
        # We need to set the expressions after adding the controls to InstrumentDevice
        self.__set_expressions()

        self.__cameras = {
            "ronchigram":
            RonchigramCameraSimulator.RonchigramCameraSimulator(
                self, self.__ronchigram_shape, self.counts_per_electron,
                self.stage_size_nm),
            "eels":
            EELSCameraSimulator.EELSCameraSimulator(self, self.__eels_shape,
                                                    self.counts_per_electron)
        }
Exemple #4
0
        def update_context() -> None:
            scan_hardware_source = typing.cast(scan_base.ScanHardwareSource, self.__scan_hardware_source_choice.hardware_source)
            scan_context = scan_hardware_source.scan_context

            if scan_context.is_valid and scan_hardware_source.line_scan_enabled and scan_hardware_source.line_scan_vector:
                calibration = scan_context.calibration
                start = Geometry.FloatPoint.make(scan_hardware_source.line_scan_vector[0])
                end = Geometry.FloatPoint.make(scan_hardware_source.line_scan_vector[1])
                length = int(Geometry.distance(start, end) * scan_context.size.height)
                max_dim = max(scan_context.size.width, scan_context.size.height)
                length_str = calibration.convert_to_calibrated_size_str(length, value_range=(0, max_dim), samples=max_dim)
                line_str = _("Line Scan")
                self.__roi_description.text = f"{line_str} {length_str} ({length} px)"
                scan_str = _("Scan (1D)")
                scan_length = max(self.__scan_width, 1)
                self.__scan_label_widget.text = f"{scan_str} {scan_length} px"
                self.__scan_pixels = scan_length
                self.__scan_specifier.scan_context = copy.deepcopy(scan_context)
                self.__scan_specifier.size = 1, scan_length
                self.__scan_specifier.drift_interval_lines = 0
                self.__acquire_button._widget.enabled = True
            elif scan_context.is_valid and scan_hardware_source.subscan_enabled and scan_hardware_source.subscan_region:
                calibration = scan_context.calibration
                width = scan_hardware_source.subscan_region.width * scan_context.size.width
                height = scan_hardware_source.subscan_region.height * scan_context.size.height
                width_str = calibration.convert_to_calibrated_size_str(width, value_range=(0, scan_context.size.width), samples=scan_context.size.width)
                height_str = calibration.convert_to_calibrated_size_str(height, value_range=(0, scan_context.size.height), samples=scan_context.size.height)
                rect_str = _("Subscan")
                self.__roi_description.text = f"{rect_str} {width_str} x {height_str} ({int(width)} px x {int(height)} px)"
                scan_str = _("Scan (2D)")
                scan_width = self.__scan_width
                scan_height = int(self.__scan_width * height / width)
                drift_lines = scan_hardware_source.calculate_drift_lines(scan_width, self.__exposure_time_ms_value_model.value / 1000) if scan_hardware_source else 0
                drift_str = f" / Drift {drift_lines} lines" if drift_lines > 0 else str()
                self.__scan_label_widget.text = f"{scan_str} {scan_width} x {scan_height} px" + drift_str
                self.__scan_pixels = scan_width * scan_height
                self.__scan_specifier.scan_context = copy.deepcopy(scan_context)
                self.__scan_specifier.size = scan_height, scan_width
                self.__scan_specifier.drift_interval_lines = drift_lines
                self.__acquire_button._widget.enabled = True
            elif scan_context.is_valid:
                calibration = scan_context.calibration
                width = scan_context.size.width
                height = scan_context.size.height
                width_str = calibration.convert_to_calibrated_size_str(width, value_range=(0, scan_context.size.width), samples=scan_context.size.width)
                height_str = calibration.convert_to_calibrated_size_str(height, value_range=(0, scan_context.size.height), samples=scan_context.size.height)
                data_str = _("Context Scan")
                self.__roi_description.text = f"{data_str} {width_str} x {height_str} ({int(width)} x {int(height)})"
                scan_str = _("Scan (2D)")
                scan_width = self.__scan_width
                scan_height = int(self.__scan_width * height / width)
                drift_lines = scan_hardware_source.calculate_drift_lines(scan_width, self.__exposure_time_ms_value_model.value / 1000) if scan_hardware_source else 0
                drift_str = f" / Drift {drift_lines} lines" if drift_lines > 0 else str()
                self.__scan_label_widget.text = f"{scan_str} {scan_width} x {scan_height} px" + drift_str
                self.__scan_pixels = scan_width * scan_height
                self.__scan_specifier.scan_context = copy.deepcopy(scan_context)
                self.__scan_specifier.size = scan_height, scan_width
                self.__scan_specifier.drift_interval_lines = drift_lines
                self.__acquire_button._widget.enabled = True
            else:
                self.__roi_description.text = _("Scan context not active")
                self.__scan_label_widget.text = None
                self.__scan_specifier.scan_context = stem_controller.ScanContext()
                self.__scan_specifier.size = None
                self.__scan_specifier.drift_interval_lines = 0
                self.__acquire_button._widget.enabled = self.__acquisition_state == SequenceState.scanning  # focus will be on the SI data, so enable if scanning
                self.__scan_pixels = 0

            self.__scan_width_widget.text = Converter.IntegerToStringConverter().convert(self.__scan_width)

            self.__update_estimate()