def __get_initial_profiles( self) -> typing.List[scan_base.ScanFrameParameters]: profiles = list() # profiles.append(scan_base.ScanFrameParameters({"size": (512, 512), "pixel_time_us": 0.2})) # profiles.append(scan_base.ScanFrameParameters({"size": (1024, 1024), "pixel_time_us": 0.2})) # profiles.append(scan_base.ScanFrameParameters({"size": (2048, 2048), "pixel_time_us": 2.5})) profiles.append( scan_base.ScanFrameParameters({ "size": (256, 256), "pixel_time_us": 1, "fov_nm": self.__instrument.stage_size_nm * 0.1 })) profiles.append( scan_base.ScanFrameParameters({ "size": (512, 512), "pixel_time_us": 1, "fov_nm": self.__instrument.stage_size_nm * 0.4 })) profiles.append( scan_base.ScanFrameParameters({ "size": (1024, 1024), "pixel_time_us": 1, "fov_nm": self.__instrument.stage_size_nm * 1.0 })) return profiles
def __init__(self): # these are required to register the device self.scan_device_id = "orsay_scan_device" self.scan_device_name = _("Orsay Scan") self.stem_controller_id = AUTOSTEM_CONTROLLER_ID self.__is_scanning = False self.on_device_state_changed = None self.flyback_pixels = 0 self.__frame_number = 0 self.__scan_size = [512, 512] self.__sizez = 2 self.orsayscan = orsayScan(1) self.spimscan = orsayScan(2, self.orsayscan.orsayscan) #list all inputs totalinputs = self.orsayscan.getInputsCount() self.dinputs = dict() for index in range(totalinputs): prop = self.orsayscan.getInputProperties(index) self.dinputs[index] = [prop, False] self.usedinputs = [[0, False, self.dinputs[0][0]], [1, False, self.dinputs[1][0]], [6, False, self.dinputs[6][0]], [7, False, self.dinputs[7][0]]] self.orsayscan.SetInputs([1, 0]) __inputs = self.orsayscan.GetInputs() for inp in __inputs[1]: for k in self.usedinputs: if k[0] == inp: k[1] = True # # Add eels camera if there # self.__eelscamera = HardwareSource.HardwareSourceManager().get_hardware_source_for_hardware_source_id("orsay_camera_kuro") self.usedinputs.append([100, False, [0, 0, "eels", 100]]) channels = list(self.usedinputs[ch][1] for ch in range(len(self.usedinputs))) self.__cameras_parsed = False self.__profiles = list() self.__profiles.append(scan_base.ScanFrameParameters({"size": (512, 512), "pixel_time_us": 0.2, "channels":channels})) self.__profiles.append(scan_base.ScanFrameParameters({"size": (1024, 1024), "pixel_time_us": 0.2, "channels":channels})) self.__profiles.append(scan_base.ScanFrameParameters({"size": (64, 64), "pixel_time_us": 1000, "channels":channels})) self.__profiles.append(scan_base.ScanFrameParameters({"size": (2048, 2048), "pixel_time_us": 2.5, "channels":channels})) self.__frame_parameters = copy.deepcopy(self.__profiles[0]) self.imagedata = numpy.empty((self.__sizez * self.__scan_size[1], self.__scan_size[0]), dtype = numpy.int16) self.imagedata_ptr = self.imagedata.ctypes.data_as(ctypes.c_void_p) self.has_data_event = threading.Event() self.fnlock = LOCKERFUNC(self.__data_locker) self.orsayscan.registerLocker(self.fnlock) self.fnunlock = UNLOCKERFUNCA(self.__data_unlockerA) self.orsayscan.registerUnlockerA(self.fnunlock) self.orsayscan.pixelTime = 0.000002 # set the scan scale to 5v to match SuperScan, which output bank, then one for each direction self.orsayscan.setScanScale(0, 5.0, 5.0) #for channel_index in range(self.channel_count): # self.set_channel_enabled(channel_index, channels_enabled[channel_index]) print(f"OrsayScan Version: {self.orsayscan._major}") self.__angle = 0
def test_eels_data_is_consistent_when_energy_offset_changes(self): instrument = InstrumentDevice.Instrument("usim_stem_controller") instrument.get_scan_data( scan_base.ScanFrameParameters({ "size": (256, 256), "pixel_time_us": 1, "fov_nm": 10 }), 0) instrument.validate_probe_position() camera = instrument._get_camera_simulator("eels") camera_size = camera._camera_shape camera.noise.enabled = False readout_area = Geometry.IntRect(origin=Geometry.IntPoint(), size=camera_size) binning_shape = Geometry.IntSize(1, 1) # get the value at 200eV and ZLP offset of 0 instrument.ZLPoffset = 0 d = xd.sum(instrument.get_camera_data("eels", readout_area, binning_shape, 0.01), axis=0) index200_0 = int( d.dimensional_calibrations[-1].convert_from_calibrated_value(200)) value200_0 = d.data[index200_0] # get the value at 200eV and ZLP offset of 100 instrument.ZLPoffset = 100 d = xd.sum(instrument.get_camera_data("eels", readout_area, binning_shape, 0.01), axis=0) index200_100 = int( d.dimensional_calibrations[-1].convert_from_calibrated_value(200)) value200_100 = d.data[index200_100] self.assertEqual(int(value200_0 / 100), int(value200_100 / 100))
def test_eels_data_camera_current_is_consistent(self): instrument = InstrumentDevice.Instrument("usim_stem_controller") # set up the scan context; these are here temporarily until the scan context architecture is fully implemented instrument._update_scan_context(Geometry.IntSize(256, 256), Geometry.FloatPoint(), 10, 0.0) instrument._set_scan_context_probe_position( instrument.scan_context, Geometry.FloatPoint(0.5, 0.5)) # grab scan data instrument.get_scan_data( scan_base.ScanFrameParameters({ "size": (256, 256), "pixel_time_us": 1, "fov_nm": 10 }), 0) instrument.validate_probe_position() camera = instrument._get_camera_simulator("eels") camera_size = camera._camera_shape camera.noise.enabled = False readout_area = Geometry.IntRect(origin=Geometry.IntPoint(), size=camera_size) binning_shape = Geometry.IntSize(1, 1) # get the value at 200eV and ZLP offset of 0 instrument.ZLPoffset = -20 exposure_s = 0.01 d = xd.sum(instrument.get_camera_data("eels", readout_area, binning_shape, exposure_s), axis=0).data # confirm it is a reasonable value camera_current_pA = numpy.sum( d) / exposure_s / instrument.counts_per_electron / 6.242e18 * 1e12 # print(f"current {camera_current_pA :#.2f}pA") self.assertTrue(190 < camera_current_pA < 210)
def test_eels_data_thickness_is_consistent(self): instrument = InstrumentDevice.Instrument("usim_stem_controller") # use the flake sample instrument.sample_index = 0 # set up the scan context; these are here temporarily until the scan context architecture is fully implemented instrument._update_scan_context(Geometry.IntSize(256, 256), Geometry.FloatPoint(), 10, 0.0) instrument._set_scan_context_probe_position( instrument.scan_context, Geometry.FloatPoint(0.5, 0.5)) # grab scan data instrument.get_scan_data( scan_base.ScanFrameParameters({ "size": (256, 256), "pixel_time_us": 1, "fov_nm": 10 }), 0) instrument.validate_probe_position() camera = instrument._get_camera_simulator("eels") camera_size = camera._camera_shape camera.noise.enabled = False readout_area = Geometry.IntRect(origin=Geometry.IntPoint(), size=camera_size) binning_shape = Geometry.IntSize(1, 1) # get the value at 200eV and ZLP offset of 0 instrument.ZLPoffset = -20 d = xd.sum(instrument.get_camera_data("eels", readout_area, binning_shape, 0.01), axis=0).data # confirm it is a reasonable value # print(measure_thickness(d)) self.assertTrue(0.40 < measure_thickness(d) < 1.00)
def test_eels_data_is_consistent_when_energy_offset_changes_with_negative_zlp_offset( self): instrument = InstrumentDevice.Instrument("usim_stem_controller") instrument.get_scan_data( scan_base.ScanFrameParameters({ "size": (256, 256), "pixel_time_us": 1, "fov_nm": 10 }), 0) instrument.validate_probe_position() camera = instrument._get_camera_simulator("eels") camera_size = camera._camera_shape camera.noise.enabled = False readout_area = Geometry.IntRect(origin=Geometry.IntPoint(), size=camera_size) binning_shape = Geometry.IntSize(1, 1) # get the value at 200eV and ZLP offset of 0 instrument.ZLPoffset = -20 instrument.get_camera_data("eels", readout_area, binning_shape, 0.01)