def __init__(self, fn, number): self.number = number # get the components self.light = model.getComponent(role="light") self.ccd = model.getComponent(role="ccd") # TODO: only support TIFF # prepare the data export self.exporter = dataio.find_fittest_converter(fn) # Make the name "fn" -> "~/Pictures/fn-XXXXXX.ext" path, base = os.path.split(fn) bn, ext = os.path.splitext(base) tmpl = os.path.join(path, bn + "-%06d" + ext) if path.startswith("/"): # if fn starts with / => don't add ~/Pictures self.fntmpl = tmpl else: self.fntmpl = os.path.join(get_picture_folder(), tmpl) self._acq_done = threading.Event() self._n = 0 self._startt = 0 # starting time of acquisition self._q = Queue.Queue() # queue of tuples (str, DataArray) for saving data # TODO: find the right number of threads, based on CPU numbers (but with # python threading that might be a bit overkill) for i in range(4): t = threading.Thread(target=self._saving_thread, args=(i,)) t.daemon = True t.start()
def __init__(self, microscope, main_app): super(MonoScanPlugin, self).__init__(microscope, main_app) # Can only be used on a Sparc with a monochromator if not microscope: return try: self.ebeam = model.getComponent(role="e-beam") self.mchr = model.getComponent(role="monochromator") self.sgrh = model.getComponent(role="spectrograph") except LookupError: logging.debug("No mochromator and spectrograph found, cannot use the plugin") return self.addMenu("Acquisition/Monochromator scan...", self.start) # the SEM survey stream (will be updated when showing the window) self._survey_s = None # Create a stream for monochromator scan self._mchr_s = MonochromatorScanStream("Spectrum", self.mchr, self.ebeam, self.sgrh) # The settings to be displayed in the dialog # Trick: we use the same VAs as the stream, so they are directly synchronised self.startWavelength = self._mchr_s.startWavelength self.endWavelength = self._mchr_s.endWavelength self.numberOfPixels = self._mchr_s.numberOfPixels self.dwellTime = self._mchr_s.dwellTime self.filename = model.StringVA("a.h5") self.expectedDuration = model.VigilantAttribute(1, unit="s", readonly=True) # Update the expected duration when values change self.dwellTime.subscribe(self._update_exp_dur) self.numberOfPixels.subscribe(self._update_exp_dur)
def setUpClass(cls): if driver.get_backend_status() == driver.BACKEND_RUNNING: logging.info("A running backend is already found, skipping tests") cls.backend_was_running = True return # run the backend as a daemon # we cannot run it normally as the child would also think he's in a unittest cmd = ODEMISD_CMD + ODEMISD_ARG + [SECOM_LENS_CONFIG] ret = subprocess.call(cmd) if ret != 0: logging.error("Failed starting backend with '%s'", cmd) time.sleep(1) # time to start # find components by their role cls.ebeam = model.getComponent(role="e-beam") cls.sed = model.getComponent(role="bs-detector") cls.ccd = model.getComponent(role="ccd") cls.sem_stage = model.getComponent(role="sem-stage") cls.opt_stage = model.getComponent(role="align") cls.ebeam_focus = model.getComponent(role="ebeam-focus") cls.focus = model.getComponent(role="focus") cls.light = model.getComponent(role="light") cls.light_filter = model.getComponent(role="filter") cls.combined_stage = model.getComponent(role="stage")
def setUpClass(cls): try: test.start_backend(SECOM_CONFIG) except LookupError: logging.info("A running backend is already found, skipping tests") cls.backend_was_running = True return except IOError as exp: logging.error(str(exp)) raise # create some streams connected to the backend cls.microscope = model.getMicroscope() cls.ccd = model.getComponent(role="ccd") cls.ebeam = model.getComponent(role="e-beam") cls.sed = model.getComponent(role="se-detector") cls.light = model.getComponent(role="light") cls.light_filter = model.getComponent(role="filter") s1 = stream.FluoStream("fluo1", cls.ccd, cls.ccd.data, cls.light, cls.light_filter) s1.excitation.value = sorted(s1.excitation.choices)[0] s2 = stream.FluoStream("fluo2", cls.ccd, cls.ccd.data, cls.light, cls.light_filter) s2.excitation.value = sorted(s2.excitation.choices)[-1] s3 = stream.BrightfieldStream("bf", cls.ccd, cls.ccd.data, cls.light) cls.streams = [s1, s2, s3]
def cryoTiltSample(rx, rz=0): """ Provide the ability to switch between imaging and tilted position, withing bumping into anything. Imaging position is considered when rx and rz are equal 0, otherwise it's considered tilting :param rx: (float) rotation movement in x axis :param rz: (float) rotation movement in z axis :return (CancellableFuture -> None): cancellable future of the move to observe the progress, and control raising the ValueError exception """ # Get the stage and align components from the backend components stage = model.getComponent(role='stage') align = model.getComponent(role='align') f = model.CancellableFuture() f.task_canceller = _cancelCryoMoveSample f._task_state = RUNNING f._task_lock = threading.Lock() f._running_subf = model.InstantaneousFuture() # Run in separate thread executeAsyncTask(f, _doCryoTiltSample, args=( f, stage, align, rx, rz, )) return f
def setUpClass(cls): test.start_backend(ENZEL_CONFIG) # find components by their role cls.stage = model.getComponent(role="stage") cls.aligner = model.getComponent(role="align") cls.stage_active = cls.stage.getMetadata()[model.MD_FAV_POS_ACTIVE] cls.stage_deactive = cls.stage.getMetadata()[model.MD_FAV_POS_DEACTIVE] cls.stage_coating = cls.stage.getMetadata()[model.MD_FAV_POS_COATING] cls.stage_alignment = cls.stage.getMetadata()[model.MD_FAV_POS_ALIGN] cls.stage_sem_imaging = cls.stage.getMetadata()[model.MD_FAV_POS_SEM_IMAGING] cls.stage_3beams = get3beamsSafePos(cls.stage.getMetadata()[model.MD_FAV_POS_ACTIVE], SAFETY_MARGIN_5DOF) cls.align_deactive = cls.aligner.getMetadata()[model.MD_FAV_POS_DEACTIVE] cls.align_alignment = cls.aligner.getMetadata()[model.MD_FAV_POS_ALIGN] cls.align_active = cls.aligner.getMetadata()[model.MD_FAV_POS_ACTIVE] cls.align_3beams = get3beamsSafePos(cls.aligner.getMetadata()[model.MD_FAV_POS_ACTIVE], SAFETY_MARGIN_3DOF) # Make sure the lens is referenced too (small move will only complete after the referencing) cls.aligner.moveRelSync({"x": 1e-6}) # The 5DoF stage is not referenced automatically, so let's do it now if not all(cls.stage.referenced.value.values()): stage_axes = set(cls.stage.axes.keys()) cls.stage.reference(stage_axes).result() # Set custom value that works well within the simulator range cls.rx_angle = 0.3 cls.rz_angle = 0.1
def test_properties_set(self): """Test creating component with specific properties""" filename = "example-secom.odm.yaml" cmdline = "--log-level=2 --log-target=testdaemon.log --daemonize %s" % filename ret = subprocess.call(ODEMISD_CMD + cmdline.split()) self.assertEqual(ret, 0, "trying to run '%s'" % cmdline) # eventually it should say it's running ret = self._wait_backend_starts(10) self.assertEqual(ret, 0, "backend status check returned %d" % (ret,)) # Check that the specific properties are set ccd = model.getComponent(role="ccd") self.assertEqual(ccd.exposureTime.value, 0.3) ebeam = model.getComponent(role="e-beam") self.assertEqual(ebeam.horizontalFoV.value, 1e-6) # stop the backend cmdline = "odemisd --log-level=2 --log-target=test.log --kill" ret = main.main(cmdline.split()) self.assertEqual(ret, 0, "trying to run '%s'" % cmdline) time.sleep(5) # give some time to stop ret = main.main(cmdline.split()) os.remove("test.log") os.remove("testdaemon.log")
def __init__(self, fn, number): self.number = number # get the components self.light = model.getComponent(role="light") self.ccd = model.getComponent(role="ccd") # TODO: only support TIFF # prepare the data export self.exporter = dataio.find_fittest_converter(fn) # Make the name "fn" -> "~/Pictures/fn-XXXXXX.ext" path, base = os.path.split(fn) bn, ext = os.path.splitext(base) tmpl = os.path.join(path, bn + "-%06d" + ext) if path.startswith("/"): # if fn starts with / => don't add ~/Pictures self.fntmpl = tmpl else: self.fntmpl = os.path.join(get_picture_folder(), tmpl) self._acq_done = threading.Event() self._n = 0 self._startt = 0 # starting time of acquisition self._q = queue.Queue() # queue of tuples (str, DataArray) for saving data # TODO: find the right number of threads, based on CPU numbers (but with # python threading that might be a bit overkill) for i in range(4): t = threading.Thread(target=self._saving_thread, args=(i,)) t.daemon = True t.start()
def acquire_zstack(num, interval, filename): """ Acquire a focus stack of num slices centered around current position, with given interval and save to file. """ logging.info("Preparing to acquire z-stack of %d images with interval " "%.3f µm giving total stack size of %.3f µm.", num, interval, num * interval) # find component by their role ccd = model.getComponent(role="ccd") focus = model.getComponent(role="focus") origpos = focus.position.value['z'] interval *= 1.0e-6 # convert to µm images = [] try: for i in range(num): islice = i - num // 2 # Make the stack centered around the origpos pos = origpos + islice * interval logging.info("Request move to target position %.8f", pos) focus.moveAbs({'z': pos}).result() logging.info("Acquiring image %d of %d", i + 1, num) images.append(ccd.data.get()) finally: # return to original position focus.moveAbs({'z': origpos}) # save the file exporter = dataio.find_fittest_converter(filename) exporter.export(filename, images)
def __init__(self, microscope, main_app): # Called when the plugin is loaed (ie, at GUI initialisation) super(Correlator2D, self).__init__(microscope, main_app) if not microscope or microscope.role not in ("sparc", "sparc2"): return try: self.ebeam = model.getComponent(role="e-beam") self.correlator = model.getComponent(role="time-correlator") self.sed = model.getComponent(role="se-detector") except LookupError: logging.debug("Hardware not found, cannot use the plugin") return # the SEM survey stream (will be updated when showing the window) self._survey_s = None # Create a stream for correlator spectral measurement self._correlator_s = CorrelatorScanStream("Correlator data", self.correlator, self.sed, self.ebeam, main_app.main_data.opm) # For reading the ROA and anchor ROI self._acqui_tab = main_app.main_data.getTabByName( "sparc_acqui").tab_data_model self.dwellTime = self._correlator_s.dwellTime self.pixelDuration = self._correlator_s.pixelDuration self.syncOffset = self._correlator_s.syncOffset self.syncDiv = self._correlator_s.syncDiv # The scanning positions are defined by ROI (as selected in the acquisition tab) + stepsize # Based on these values, the scanning resolution is computed self.roi = self._correlator_s.roi self.stepsize = self._correlator_s.stepsize self.cropvalue = self._correlator_s.cropvalue self.xres = model.IntVA(1, unit="px") self.yres = model.IntVA(1, unit="px") self.nDC = self._correlator_s.nDC self.filename = model.StringVA("a.h5") self.expectedDuration = model.VigilantAttribute(1, unit="s", readonly=True) # Update the expected duration when values change, depends both dwell time and # of pixels self.dwellTime.subscribe(self._update_exp_dur) self.stepsize.subscribe(self._update_exp_dur) self.nDC.subscribe(self._update_exp_dur) # subscribe to update X/Y res self.stepsize.subscribe(self._update_res) self.roi.subscribe(self._update_res) self.addMenu("Acquisition/CL time correlator scan...", self.start)
def main(args): """ Handles the command line arguments. Parameters ---------- args: The list of arguments passed. Returns ------- (int) value to return to the OS as program exit code. """ parser = argparse.ArgumentParser() parser.add_argument('--debug', action="store_true", default=False) parser.add_argument("--role", dest="role", default="diagnostic-ccd", metavar="<component>", help="Role of the camera to connect to via the Odemis " "back-end. Ex: 'ccd'.") parser.add_argument("--channel", dest="channel", default=1, metavar="<component>", help="Number of the AWG output channel.") parser.add_argument("--auto", dest="auto", default=True, metavar="<component>", help="If True automatically align the ebeam scan to" "multiprobe. To do this a server must be running " "on the microscope PC.") options = parser.parse_args(args[1:]) if options.debug: logging.getLogger().setLevel(logging.DEBUG) else: logging.getLogger().setLevel(logging.WARNING) if get_backend_status() != BACKEND_RUNNING: raise ValueError("Backend is not running.") ccd = model.getComponent(role=options.role) try: sem_rotation = get_sem_rotation(ccd, auto=options.auto, channel=options.channel) if options.auto: scanner = model.getComponent(role="ebeam-control") val = scanner.rotation.value scanner.rotation.value = val + sem_rotation print("Added {:.2f}° to the scan rotation using SEM PC." "Rotation is now set to: {:.2f}°".format( math.degrees(sem_rotation), math.degrees(scanner.rotation.value))) else: print("Add {:.2f}° to the scan rotation using SEM PC. If negative" "subtract this value from the scan rotation.".format( math.degrees(sem_rotation))) except Exception as exp: logging.error("%s", exp, exc_info=True) return 128 return 0
def main(args): """ Handles the command line arguments args is the list of arguments passed return (int): value to return to the OS as program exit code """ parser = argparse.ArgumentParser( description="Record a series of image brightness " "for different angles of a given polarizer.") parser.add_argument("--polarizer", "-p", dest="polarizer", required=True, choices=("linear", "qwp"), help="Actuator to use") parser.add_argument("--output", "-o", dest="filename", required=True, help="Output filename (in tab-separate values)") options = parser.parse_args(args[1:]) try: if "." not in options.filename[-5:]: raise ValueError("Output argument must contain extension, " "but got '%s'" % (options.filename, )) if options.polarizer == "linear": role = "lin-pol" else: # qwp # Search for qwp = 0 by optimizing RHC role = "quarter-wave-plate" logging.info("Moving the linear polarizer to positive diagonal") linpol = model.getComponent(role="lin-pol") linpol.moveAbsSync({"rz": math.radians(45)}) polarizer = model.getComponent(role=role) # 180° (every 2°) + 25% to check it's indeed repeating angles = numpy.arange(0, math.pi * 1.25, math.radians(2)) brightness = acquire_angles(polarizer, angles) logging.debug("Acquired brightness: %s", brightness) # Stores the file with open(options.filename, "w+") as f: for a, b in zip(angles, brightness): f.write("%f\t%f\n" % (a, b)) # Show on a graph plt.plot(angles, brightness) plt.show() except Exception: logging.exception("Unexpected error while performing action.") return 129 return 0
def setUpClass(cls): if TEST_NOHW: raise unittest.SkipTest('No HW present. Skipping tests.') test.start_backend(CLSPOTS_CONFIG) # find components by their role cls.diagnostic_cam = model.getComponent(role="diagnostic-ccd") cls.stage = model.getComponent(role="stage") cls._optimal_focus = 40e-6 # update with actual value
def setUpClass(cls): try: import fastem_calibrations except ImportError as err: raise unittest.SkipTest( f"Skipping the fastem tests, correct libraries " f"to perform the tests are not available.\n" f"Got the error: {err}") if TEST_NOHW: test.start_backend(FASTEM_CONFIG) elif driver.get_backend_status() != driver.BACKEND_RUNNING: raise IOError( "Backend controlling a real hardware should be started before running this test case" ) # get the hardware components cls.scanner = model.getComponent(role='e-beam') cls.asm = model.getComponent(role="asm") cls.mppc = model.getComponent(role="mppc") cls.multibeam = model.getComponent(role="multibeam") cls.descanner = model.getComponent(role="descanner") cls.stage = model.getComponent( role="stage" ) # TODO replace with stage-scan when ROA conversion method available cls.ccd = model.getComponent(role="diagnostic-ccd") cls.beamshift = model.getComponent(role="ebeam-shift") cls.det_rotator = model.getComponent(role="det-rotator")
def setUpClass(cls): if TEST_NOHW: test.start_backend(FASTEM_CONFIG) elif driver.get_backend_status() != driver.BACKEND_RUNNING: raise IOError("Backend controlling a real hardware should be started before running this test case") cls.ebeam = model.getComponent(role="e-beam") cls.efocuser = model.getComponent(role="ebeam-focus") cls.sed = model.getComponent(role="se-detector") cls.stage = model.getComponent(role="stage") cls.stage.reference({"x", "y"}).result()
def main(args): """ Handles the command line arguments args is the list of arguments passed return (int): value to return to the OS as program exit code """ parser = argparse.ArgumentParser(description="Measure the needed SEM calibration") parser.add_argument("--move", dest="move", action='store_true', help="First to move to the standard location for Delphi calibration on the sample") parser.add_argument("--autofocus", "-f", dest="focus", action='store_true', help="Auto focus the SEM image before calibrating") options = parser.parse_args(args[1:]) try: escan = model.getComponent(role="e-beam") bsd = model.getComponent(role="bs-detector") # This moves the SEM stage precisely on the hole, as the calibration does it if options.move: semstage = model.getComponent(role="sem-stage") semstage.moveAbs(delphi.SHIFT_DETECTION).result() if options.focus: efocus = model.getComponent(role="ebeam-focus") efocus.moveAbs({"z": delphi.SEM_KNOWN_FOCUS}).result() f = autofocus.AutoFocus(bsd, escan, efocus) focus, fm_level = f.result() print("SEM focused @ %g m" % (focus,)) logging.debug("Starting Phenom SEM calibration...") blank_md = dict.fromkeys(delphi.MD_CALIB_SEM, (0, 0)) escan.updateMetadata(blank_md) # Compute spot shift percentage f = delphi.ScaleShiftFactor(bsd, escan, logpath="./") spot_shift = f.result() print("Spot shift = %s" % (spot_shift,)) # Compute HFW-related values f = delphi.HFWShiftFactor(bsd, escan, logpath="./") hfw_shift = f.result() print("HFW shift = %s" % (hfw_shift,)) # Compute resolution-related values f = delphi.ResolutionShiftFactor(bsd, escan, logpath="./") res_sa, res_sb = f.result() print("res A = %s, res B = %s" % (res_sa, res_sb)) except Exception: logging.exception("Unexpected error while performing action.") return 127 return 0
def acquire_volts(volts, detector): """ vots (list of floats > 0): voltage in kV detector (str): role of the spectrometer to use returns (list of DataArray): all the spectra, in order """ ebeam = model.getComponent(role="e-beam") sed = model.getComponent(role="se-detector") spmt = model.getComponent(role=detector) hw_settings = save_hw_settings(ebeam) # Go to spot mode (ie, res = 1x1) if ebeam.resolution.value != (1, 1): ebeam.resolution.value = (1, 1) ebeam.translation.value = (0, 0) # at the center of the FoV else: logging.info("Leaving the e-beam in spot mode at %s", ebeam.translation.value) ebeam.dwellTime.value = 0.1 try: # Activate the e-beam sed.data.subscribe(discard_data) das = [] for vstr in volts: v = float(vstr) * 1000 ebeam.accelVoltage.value = v if not util.almost_equal(ebeam.accelVoltage.value, v): logging.warning( "Voltage requested at %g kV, but e-beam set at %g kV", v / 1000, ebeam.accelVoltage.value / 1000) else: logging.info("Acquiring at %g kV", v / 1000) # Acquire one spectrum spec = spmt.data.get() # Add dimensions to make it a spectrum (X, first dim -> C, 5th dim) spec.shape = (spec.shape[-1], 1, 1, 1, 1) # Add some useful metadata spec.metadata[model.MD_DESCRIPTION] = "Spectrum at %g kV" % (v / 1000) spec.metadata[model.MD_EBEAM_VOLTAGE] = v # TODO: store the spot position in MD_POS das.append(spec) finally: sed.data.unsubscribe(discard_data) # Just to be sure resume_hw_settings(ebeam, hw_settings) return das
def __init__(self, dt, roi, pxs, subpx=1, lpower=0.2): """ pxs (0<float): distance in m between center of each tile subpx (1<=int): number of sub-pixels """ if subpx < 1 or (math.sqrt(subpx) % 1) != 0: raise ValueError("subpx must be square of an integer") self.dt = dt self.roi = roi subpx_x = math.trunc(math.sqrt(subpx)) self.pxs = pxs self.subpxs = pxs / subpx_x logging.info("Sub-pixels will be spaced by %f nm", self.subpxs * 1e9) self.tile_shape = (subpx_x, subpx_x ) # for now always the same in x and y self.lpower = lpower # Get the components we need self.sed = model.getComponent(role="se-detector") self.ebeam = model.getComponent(role="e-beam") self.light = model.getComponent(role="light") self.ccd = model.getComponent(role="ccd") self.stage = model.getComponent(role="stage") # Find the index with maximum power to use to set lpower self.max_power_index = list(self.light.power.range[1]).index( max(self.light.power.range[1])) lprng = self.light.power.range if not (lprng[0][self.max_power_index] < lpower < lprng[1][self.max_power_index]): raise ValueError("starting light power value must be between %s" % (lprng, )) # counter-intuitively, to get the smaller pixel size, no sub-pixel # should be used. That's because when there is no sub-pixel we can use # spot mode, which allows to go at less than scale=1. # It could easily be fixed by allowsing scale down to 0.1 in the driver. if (self.ebeam.pixelSize.value[0] > 10 * pxs or self.ebeam.pixelSize.value[0] > self.subpxs): raise ValueError("Pixel size requested (%g nm/%g nm) is too small " "compared to recommended SEM pixel size (%g nm)" % (pxs * 1e9, self.subpxs * 1e9, self.ebeam.pixelSize.value[0] * 1e9)) elif self.ebeam.pixelSize.value[0] > pxs: logging.warning( "Pixel size requested (%g nm) is smaller than " "recommended SEM pixel size (%g nm) at the current " "mag.", pxs * 1e9, self.ebeam.pixelSize.value[0] * 1e9) self._hw_settings = () # will be used to save/resume SEM settings
def __init__(self, microscope, main_app): super(RGBCLIntensity, self).__init__(microscope, main_app) # Can only be used on a SPARC with a CL-intensity detector if not microscope: return try: self.ebeam = model.getComponent(role="e-beam") self.cldetector = model.getComponent(role="cl-detector") self.filterwheel = model.getComponent(role="cl-filter") self.sed = model.getComponent(role="se-detector") # We could also check the filter wheel has at least 3 filters, but # let's not be too picky, if the user has installed the plugin, he # probably wants to use it anyway. except LookupError: logging.info("Hardware not found, cannot use the RGB CL plugin") return # The SEM survey and CLi stream (will be updated when showing the window) self._survey_s = None self._cl_int_s = None self._acqui_tab = main_app.main_data.getTabByName( "sparc_acqui").tab_data_model # The settings to be displayed in the dialog # TODO: pick better default filters than first 3 filters # => based on the wavelengths fitting best RGB, or the names (eg, "Blue"), # and avoid "pass-through". fbchoices = self.filterwheel.axes["band"].choices if isinstance(fbchoices, dict): fbvalues = sorted(fbchoices.keys()) else: fbvalues = fbchoices # FloatEnumerated because filter positions can be in rad (ie, not int positions) self.filter1 = model.FloatEnumerated(fbvalues[0], choices=fbchoices) self.filter2 = model.FloatEnumerated(fbvalues[min( 1, len(fbvalues) - 1)], choices=fbchoices) self.filter3 = model.FloatEnumerated(fbvalues[min( 2, len(fbvalues) - 1)], choices=fbchoices) self._filters = [self.filter1, self.filter2, self.filter3] self._colours = [(0, 0, 255), (0, 255, 0), (255, 0, 0)] # B, G, R self.filename = model.StringVA("a.tiff") self.expectedDuration = model.VigilantAttribute(1, unit="s", readonly=True) self.addMenu("Acquisition/RGB CL intensity...", self.start)
def __init__(self, microscope, main_app): # Called when the plugin is loaed (ie, at GUI initialisation) super(Correlator2D, self).__init__(microscope, main_app) if not microscope or microscope.role not in ("sparc", "sparc2"): return try: self.ebeam = model.getComponent(role="e-beam") self.correlator = model.getComponent(role="time-correlator") self.sed = model.getComponent(role="se-detector") except LookupError: logging.debug("Hardware not found, cannot use the plugin") return # the SEM survey stream (will be updated when showing the window) self._survey_s = None # Create a stream for correlator spectral measurement self._correlator_s = CorrelatorScanStream("Correlator data", self.correlator, self.sed, self.ebeam, main_app.main_data.opm) # For reading the ROA and anchor ROI self._acqui_tab = main_app.main_data.getTabByName("sparc_acqui").tab_data_model self.dwellTime = self._correlator_s.dwellTime self.pixelDuration = self._correlator_s.pixelDuration self.syncOffset = self._correlator_s.syncOffset self.syncDiv = self._correlator_s.syncDiv # The scanning positions are defined by ROI (as selected in the acquisition tab) + stepsize # Based on these values, the scanning resolution is computed self.roi = self._correlator_s.roi self.stepsize = self._correlator_s.stepsize self.cropvalue = self._correlator_s.cropvalue self.xres = model.IntVA(1, unit="px") self.yres = model.IntVA(1, unit="px") self.nDC = self._correlator_s.nDC self.filename = model.StringVA("a.h5") self.expectedDuration = model.VigilantAttribute(1, unit="s", readonly=True) # Update the expected duration when values change, depends both dwell time and # of pixels self.dwellTime.subscribe(self._update_exp_dur) self.stepsize.subscribe(self._update_exp_dur) self.nDC.subscribe(self._update_exp_dur) # subscribe to update X/Y res self.stepsize.subscribe(self._update_res) self.roi.subscribe(self._update_res) self.addMenu("Acquisition/CL time correlator scan...", self.start)
def setUpClass(cls): if TEST_NOHW: test.start_backend(FASTEM_CONFIG_ASM) elif driver.get_backend_status() != driver.BACKEND_RUNNING: raise IOError("Backend controlling a real hardware should be started before running this test case") # get the hardware components cls.asm = model.getComponent(role="asm") cls.mppc = model.getComponent(role="mppc") cls.multibeam = model.getComponent(role="multibeam") cls.descanner = model.getComponent(role="descanner") cls.stage = model.getComponent( role="stage") # TODO replace with stage-scan when ROA conversion method available cls.stage.reference({"x", "y"}).result()
def setUpClass(cls): try: test.start_backend(SECOM_LENS_CONFIG) except LookupError: logging.info("A running backend is already found, skipping tests") cls.backend_was_running = True return except IOError as exp: logging.error(str(exp)) raise # find components by their role cls.ebeam = model.getComponent(role="e-beam") cls.sed = model.getComponent(role="se-detector") cls.ccd = model.getComponent(role="ccd") cls.focus = model.getComponent(role="focus") cls.align = model.getComponent(role="align") cls.light = model.getComponent(role="light") cls.light_filter = model.getComponent(role="filter") cls.stage = model.getComponent(role="stage") # Used for OBJECTIVE_MOVE type cls.aligner_xy = ConvertStage("converter-ab", "stage", children={"orig": cls.align}, axes=["b", "a"], rotation=math.radians(45))
def acquire_volts(volts, detector): """ vots (list of floats > 0): voltage in kV detector (str): role of the spectrometer to use returns (list of DataArray): all the spectra, in order """ ebeam = model.getComponent(role="e-beam") sed = model.getComponent(role="se-detector") spmt = model.getComponent(role=detector) hw_settings = save_hw_settings(ebeam) # Go to spot mode (ie, res = 1x1) if ebeam.resolution.value != (1, 1): ebeam.resolution.value = (1, 1) ebeam.translation.value = (0, 0) # at the center of the FoV else: logging.info("Leaving the e-beam in spot mode at %s", ebeam.translation.value) ebeam.dwellTime.value = 0.1 try: # Activate the e-beam sed.data.subscribe(discard_data) das = [] for vstr in volts: v = float(vstr) * 1000 ebeam.accelVoltage.value = v if not util.almost_equal(ebeam.accelVoltage.value, v): logging.warning("Voltage requested at %g kV, but e-beam set at %g kV", v / 1000, ebeam.accelVoltage.value / 1000) else: logging.info("Acquiring at %g kV", v / 1000) # Acquire one spectrum spec = spmt.data.get() # Add dimensions to make it a spectrum (X, first dim -> C, 5th dim) spec.shape = (spec.shape[-1], 1, 1, 1, 1) # Add some useful metadata spec.metadata[model.MD_DESCRIPTION] = "Spectrum at %g kV" % (v / 1000) spec.metadata[model.MD_EBEAM_VOLTAGE] = v # TODO: store the spot position in MD_POS das.append(spec) finally: sed.data.unsubscribe(discard_data) # Just to be sure resume_hw_settings(ebeam, hw_settings) return das
def setUpClass(cls): if TEST_NOHW is True: raise unittest.SkipTest( "No simulator running or HW present. Skip fastem ROA tests.") # get the hardware components cls.microscope = model.getMicroscope() cls.asm = model.getComponent(role="asm") cls.mppc = model.getComponent(role="mppc") cls.multibeam = model.getComponent(role="multibeam") cls.descanner = model.getComponent(role="descanner") cls.stage = model.getComponent( role="stage" ) # TODO replace with stage-scan when ROA conversion method available cls.stage.reference({"x", "y"}).result()
def __init__(self): # find components by their role # the ebeam scanner self.escan = model.getComponent(role="e-beam") # the secondary electron detector self.sed = model.getComponent(role="se-detector") # the spectrometer self.spect = model.getComponent(role="spectrometer") # For acquisition self.spec_data = None self.acq_done = threading.Event() # For drift correction self.drift = (0, 0)
def setUpClass(cls): try: test.start_backend(CLSPOTS_SIM_CONFIG) except LookupError: logging.debug("A running backend is already found, skipping tests") cls.backend_was_running = True return except IOError as exp: logging.error(str(exp)) raise # find components by their role cls.diagnostic_cam = model.getComponent(role="diagnostic-ccd") cls.stage = model.getComponent(role="stage") cls.ofocus = model.getComponent(role="diagnostic-cam-focus")
def main(args): """ Handles the command line arguments args is the list of arguments passed return (int): value to return to the OS as program exit code """ parser = argparse.ArgumentParser(description="Record a series of image brightness " "for different angles of a given polarizer.") parser.add_argument("--polarizer", "-p", dest="polarizer", required=True, choices=("linear", "qwp"), help="Actuator to use") parser.add_argument("--output", "-o", dest="filename", required=True, help="Output filename (in tab-separate values)") options = parser.parse_args(args[1:]) try: if "." not in options.filename[-5:]: raise ValueError("Output argument must contain extension, " "but got '%s'" % (options.filename,)) if options.polarizer == "linear": role = "lin-pol" else: # qwp # Search for qwp = 0 by optimizing RHC role = "quarter-wave-plate" logging.info("Moving the linear polarizer to positive diagonal") linpol = model.getComponent(role="lin-pol") linpol.moveAbsSync({"rz": math.radians(45)}) polarizer = model.getComponent(role=role) # 180° (every 2°) + 25% to check it's indeed repeating angles = numpy.arange(0, math.pi * 1.25, math.radians(2)) brightness = acquire_angles(polarizer, angles) logging.debug("Acquired brightness: %s", brightness) # Stores the file with open(options.filename, "w+") as f: for a, b in zip(angles, brightness): f.write("%f\t%f\n" % (a, b)) # Show on a graph plt.plot(angles, brightness) plt.show() except Exception: logging.exception("Unexpected error while performing action.") return 129 return 0
def main(args): """ Handles the command line arguments args is the list of arguments passed return (int): value to return to the OS as program exit code """ global n ccd = model.getComponent(role="ccd") # TODO: decrease exposure time until it seems to not follow? # How to detects drops? fps_goal = 10000 # Hz ccd.exposureTime.value = 1 / fps_goal # s prev_n = n ccd.data.subscribe(_on_image) try: for i in range(100): time.sleep(1) newn = n fps = newn - prev_n prev_n = newn print("%d fps" % fps) except KeyboardInterrupt: pass except Exception: logging.exception("Failed to estimate FPS due to error") finally: ccd.data.unsubscribe(_on_image) return 0
def setUpClass(cls): if driver.get_backend_status() in driver.BACKEND_RUNNING: microscope = model.getMicroscope() if microscope.role != "meteor": logging.info( "There is already running backend. It will be turned off, and the backend of METEOR will be turned on." ) test.stop_backend() test.start_backend(METEOR_CONFIG) else: logging.info( "There is METEOR backend already running. It will be used." ) else: try: logging.info("METEOR backend will be turned on.") test.start_backend(METEOR_CONFIG) except Exception: raise # get the stage components cls.stage = model.getComponent(role="stage-bare") # get the metadata stage_md = cls.stage.getMetadata() cls.stage_grid_centers = stage_md[model.MD_SAMPLE_CENTERS] cls.stage_loading = stage_md[model.MD_FAV_POS_DEACTIVE]
def main(args): """ Handles the command line arguments args is the list of arguments passed return (int): value to return to the OS as program exit code """ ebeam = model.getComponent(role="e-beam") while ebeam.resolution.value != (1, 1): raw_input("Please select spot mode and pick a point and press Enter...") wls = getNumber("Starting wavelength (in nm): ") * 1e-9 wle = getNumber("Ending wavelength (in nm): ") * 1e-9 nbp = getNumber("Number of wavelengths to acquire: ") dt = getNumber("Dwell time (in ms): ") * 1e-3 exp_time = nbp * (dt + 0.05) # 50 ms to change wavelength print("Expected duration: %s" % (units.readable_time(math.ceil(exp_time)),)) filename = raw_input("Filename to store the spectrum: ") if "." not in filename: # No extension -> force hdf5 filename += ".h5" print("Press Ctrl+C to cancel the acquisition") try: acquire_spec(wls, wle, int(nbp), dt, filename) except Exception: logging.exception("Unexpected error while performing action.") return 127 return 0
def setUpClass(cls): try: test.start_backend(DELPHI_CONFIG) except LookupError: logging.info("A running backend is already found, skipping tests") cls.backend_was_running = True return except IOError as exp: logging.error(str(exp)) raise # find components by their role cls.stage = model.getComponent(role="stage") cls.sem_stage = model.getComponent(role="sem-stage") cls.align = model.getComponent(role="align") cls.tmcm = model.getComponent(name="Sample Holder Actuators") # low level actuator
def main(args): """ Handles the command line arguments args is the list of arguments passed return (int): value to return to the OS as program exit code """ # arguments handling parser = argparse.ArgumentParser() parser.add_argument("--role", dest="role", metavar="<component>", help="display and update an image on the screen") parser.add_argument("--gridsize", dest="gridsize", nargs=2, metavar="<gridsize>", type=int, default=None, help="size of the grid of spots in x y, default 14 14") parser.add_argument("--log-level", dest="loglev", metavar="<level>", type=int, choices=[0, 1, 2], default=0, help="set verbosity level (0-2, default = 0)") options = parser.parse_args(args[1:]) # Set up logging before everything else loglev_names = [logging.WARNING, logging.INFO, logging.DEBUG] loglev = loglev_names[min(len(loglev_names) - 1, options.loglev)] # change the log format to be more descriptive handler = logging.StreamHandler() logging.getLogger().setLevel(loglev) handler.setFormatter(logging.Formatter('%(asctime)s (%(module)s) %(levelname)s: %(message)s')) logging.getLogger().addHandler(handler) if options.role: if get_backend_status() != BACKEND_RUNNING: raise ValueError("Backend is not running while role command is specified.") ccd = model.getComponent(role=options.role) live_display(ccd, ccd.data, kill_ccd=False, gridsize=options.gridsize) else: ccd = ueye.Camera("camera", "ccd", device=None) ccd.SetFrameRate(2) live_display(ccd, ccd.data, gridsize=options.gridsize) return 0
def main(args): """ Handles the command line arguments args is the list of arguments passed return (int): value to return to the OS as program exit code """ ebeam = model.getComponent(role="e-beam") while ebeam.resolution.value != (1, 1): input("Please select spot mode and pick a point and press Enter...") wls = getNumber("Starting wavelength (in nm): ") * 1e-9 wle = getNumber("Ending wavelength (in nm): ") * 1e-9 nbp = getNumber("Number of wavelengths to acquire: ") dt = getNumber("Dwell time (in ms): ") * 1e-3 exp_time = nbp * (dt + 0.05) # 50 ms to change wavelength print("Expected duration: %s" % (units.readable_time(math.ceil(exp_time)), )) filename = input("Filename to store the spectrum: ") if "." not in filename: # No extension -> force hdf5 filename += ".h5" print("Press Ctrl+C to cancel the acquisition") try: acquire_spec(wls, wle, int(nbp), dt, filename) except Exception: logging.exception("Unexpected error while performing action.") return 127 return 0
def acquire_timelapse(num, period, filename): # find components by their role # ebeam = model.getComponent(role="ebeam") sed = model.getComponent(role="se-detector") images = [] try: for i in range(num): logging.info("Acquiring image %d/%d", i + 1, num) start = time.time() images.append(sed.data.get()) left = period - (time.time() - start) if left < 0: logging.warning("Acquisition took longer than the period (%g s overdue)", -left) else: logging.info("Sleeping for another %g s", left) time.sleep(left) except KeyboardInterrupt: logging.info("Closing after only %d images acquired", i + 1) except Exception: logging.exception("Failed to acquire all the images, will try to save anyway") # save the file exporter = dataio.find_fittest_exporter(filename) exporter.export(filename, images)
def acquire_angles(polarizer, angles): """ Acquire an image from "ccd" for the given polarizer for each angle returns (list of float): the average brightness for each of these angles. """ logging.info("Preparing to acquire brightness of %d angles on %s", len(angles), polarizer.name) # find component by their role ccd = model.getComponent(role="ccd") origpos = polarizer.position.value['rz'] brightness = [] i = 0 try: for a in angles: i += 1 logging.info("Request move to target position %.8f rad (%d/%d)", a, i, len(angles)) polarizer.moveAbs({'rz': a % (2 * math.pi)}).result() brightness.append(numpy.average(ccd.data.get())) finally: # return to original position polarizer.moveAbs({"rz": origpos}) return brightness
def acquire(det, fn_beg): scanner = model.getComponent(role="laser-mirror") min_dt = scanner.dwellTime.range[0] for zoom in (1, 50, 1.1, 1.25, 1.5, 1.75, 2, 4, 8, 16, 20, 30): for kdt in (1, 2, 4, 8, 12, 16, 24, 32, 40, 64, 80): dt = min_dt * kdt if dt > scanner.dwellTime.range[1]: continue det.gain.value = int(GAIN_INIT - math.log(kdt, 2) * GAIN_DECREASE) logging.info("Gain is now %g", det.gain.value) for xres in (64, 128, 256, 512, 1024, 2048): #for yres in (64, 128, 256, 512, 1024, 2048): yres = xres # only square images fn = "%s_z%g_d%g_r%dx%d.tiff" % (fn_beg, zoom, dt * 1e6, xres, yres) logging.info("Acquiring %s", fn) im = acquire_settings(scanner, det, (xres, yres), zoom, dt) if im is not None: tiff.export(fn, im) # Acquire at the end another time the first image, to check the drift zoom = 1 dt = min_dt xres = yres = 2048 im = acquire_settings(scanner, det, (xres, yres), zoom, dt) fn = "%s_z%g_d%g_r%dx%d_after.tiff" % (fn_beg, zoom, dt * 1e6, xres, yres) tiff.export(fn, im)
def main(args): """ Handles the command line arguments args is the list of arguments passed return (int): value to return to the OS as program exit code """ global n ccd = model.getComponent(role="ccd") # TODO: decrease exposure time until it seems to not follow? # How to detects drops? fps_goal = 10000 # Hz ccd.exposureTime.value = 1 / fps_goal # s prev_n = n ccd.data.subscribe(_on_image) try: for i in range(100): time.sleep(1) newn = n fps = newn - prev_n prev_n = newn print "%d fps" % fps except KeyboardInterrupt: pass except Exception: logging.exception("Failed to estimate FPS due to error") finally: ccd.data.unsubscribe(_on_image) return 0
def __init__(self, dt, roi, pxs, subpx=1, lpower=0.2): """ pxs (0<float): distance in m between center of each tile subpx (1<=int): number of sub-pixels """ if subpx < 1 or (math.sqrt(subpx) % 1) != 0: raise ValueError("subpx must be square of an integer") self.dt = dt self.roi = roi subpx_x = math.trunc(math.sqrt(subpx)) self.pxs = pxs self.subpxs = pxs / subpx_x logging.info("Sub-pixels will be spaced by %f nm", self.subpxs * 1e9) self.tile_shape = (subpx_x, subpx_x) # for now always the same in x and y self.lpower = lpower # Get the components we need self.sed = model.getComponent(role="se-detector") self.ebeam = model.getComponent(role="e-beam") self.light = model.getComponent(role="light") self.ccd = model.getComponent(role="ccd") self.stage = model.getComponent(role="stage") lprng = self.light.power.range if not (lprng[0] < lpower < lprng[1]): raise ValueError("starting light power value must be between %s", lprng) # counter-intuitively, to get the smaller pixel size, no sub-pixel # should be used. That's because when there is no sub-pixel we can use # spot mode, which allows to go at less than scale=1. # It could easily be fixed by allowsing scale down to 0.1 in the driver. if (self.ebeam.pixelSize.value[0] > 10 * pxs or self.ebeam.pixelSize.value[0] > self.subpxs): raise ValueError("Pixel size requested (%g nm/%g nm) is too small " "compared to recommended SEM pixel size (%g nm)" % (pxs * 1e9, self.subpxs * 1e9, self.ebeam.pixelSize.value[0] * 1e9)) elif self.ebeam.pixelSize.value[0] > pxs: logging.warning("Pixel size requested (%g nm) is smaller than " "recommended SEM pixel size (%g nm) at the current " "mag.", pxs * 1e9, self.ebeam.pixelSize.value[0] * 1e9) self._hw_settings = () # will be used to save/resume SEM settings
def __init__(self, microscope, main_app): super(RGBCLIntensity, self).__init__(microscope, main_app) # Can only be used on a SPARC with a CL-intensity detector if not microscope: return try: self.ebeam = model.getComponent(role="e-beam") self.cldetector = model.getComponent(role="cl-detector") self.filterwheel = model.getComponent(role="cl-filter") self.sed = model.getComponent(role="se-detector") # We could also check the filter wheel has at least 3 filters, but # let's not be too picky, if the user has installed the plugin, he # probably wants to use it anyway. except LookupError: logging.info("Hardware not found, cannot use the RGB CL plugin") return # The SEM survey and CLi stream (will be updated when showing the window) self._survey_s = None self._cl_int_s = None self._acqui_tab = main_app.main_data.getTabByName("sparc_acqui").tab_data_model # The settings to be displayed in the dialog # TODO: pick better default filters than first 3 filters # => based on the wavelengths fitting best RGB, or the names (eg, "Blue"), # and avoid "pass-through". fbchoices = self.filterwheel.axes["band"].choices if isinstance(fbchoices, dict): fbvalues = sorted(fbchoices.keys()) else: fbvalues = fbchoices # FloatEnumerated because filter positions can be in rad (ie, not int positions) self.filter1 = model.FloatEnumerated(fbvalues[0], choices=fbchoices) self.filter2 = model.FloatEnumerated(fbvalues[min(1, len(fbvalues) - 1)], choices=fbchoices) self.filter3 = model.FloatEnumerated(fbvalues[min(2, len(fbvalues) - 1)], choices=fbchoices) self._filters = [self.filter1, self.filter2, self.filter3] self._colours = [(0, 0, 255), (0, 255, 0), (255, 0, 0)] # B, G, R self.filename = model.StringVA("a.tiff") self.expectedDuration = model.VigilantAttribute(1, unit="s", readonly=True) self.addMenu("Acquisition/RGB CL intensity...", self.start)
def setUpClass(cls): try: test.start_backend(SPARC2_FOCUS_CONFIG) except LookupError: logging.info("A running backend is already found, skipping tests") cls.backend_was_running = True return except IOError as exp: logging.error(str(exp)) raise # find components by their role cls.ccd = model.getComponent(role="ccd") cls.spectrometer = model.getComponent(role="spectrometer-integrated") cls.focus = model.getComponent(role="focus") cls._good_focus = cls.focus.position.value["z"]
def setUpClass(cls): try: test.start_backend(SECOM_FLIM_CONFIG) except LookupError: logging.info("A running backend is already found, skipping tests") cls.backend_was_running = True return except IOError as exp: logging.error(str(exp)) raise # Find confocal (light + laser-mirror) and FLIM (time-correlator) components cls.sft = model.getComponent(role="time-correlator") cls.tc_scanner = model.getComponent(role="tc-scanner") cls.ex_light = model.getComponent(role="light") cls.lscanner = model.getComponent(role="laser-mirror") cls.apd = model.getComponent(role="tc-detector") cls.tcdl = model.getComponent(role="tc-detector-live") cls.detector = model.getComponent(role="photo-detector0") cls.ex_light.period.value = 0.0001 em = [0] * len(cls.ex_light.emissions.value) cls.ex_light.emissions.value = em cls.ex_light.power.value = 0.25
def setUpClass(cls): try: test.start_backend(SPARC2_FOCUS_CONFIG) except LookupError: logging.info("A running backend is already found, skipping tests") cls.backend_was_running = True return except IOError as exp: logging.error(str(exp)) raise # find components by their role cls.ccd = model.getComponent(role="ccd") cls.spccd = model.getComponent(role="sp-ccd") cls.focus = model.getComponent(role="focus") cls.bl = model.getComponent(role="brightlight") cls.spgr = model.getComponent(role="spectrograph") cls.spgr_ded = model.getComponent(role="spectrograph-dedicated") cls.aligner = model.getComponent(role="fiber-aligner") cls.microscope = model.getMicroscope() cls.optmngr = path.OpticalPathManager(cls.microscope) cls.specline_ccd = stream.BrightfieldStream("Spectrograph_line_ccd", cls.ccd, cls.ccd.data, cls.bl) cls.specline_spccd = stream.BrightfieldStream("Spectrograph_line_spccd", cls.spccd, cls.spccd.data, cls.bl) # The good focus position is the start up position cls._good_focus = cls.focus.position.value["z"]
def setUpClass(cls): try: test.start_backend(SPEC_CONFIG) except LookupError: logging.info("A running backend is already found, skipping tests") cls.backend_was_running = True return except IOError as exp: logging.error(str(exp)) raise # Microscope component cls.microscope = model.getComponent(role="sparc") # Find CCD & SEM components cls.spec = model.getComponent(role="spectrometer") cls.ebeam = model.getComponent(role="e-beam") cls.sed = model.getComponent(role="se-detector") cls.optmngr = path.OpticalPathManager(cls.microscope)
def get_component(comp_name): """ return the component with the given name comp_name (string): name of the component to find raises ValueError if the component doesn't exist other exception if there is an error while contacting the backend """ logging.debug("Looking for component %s", comp_name) try: return model.getComponent(name=comp_name) except LookupError: try: comp = model.getComponent(role=comp_name) logging.info("Using component %s with role %s", comp.name, comp.role) return comp except LookupError: raise ValueError("No component found with name or role '%s'" % comp_name)
def setUpClass(cls): try: test.start_backend(SECOM_CONFIG) except LookupError: logging.info("A running backend is already found, skipping tests") cls.backend_was_running = True return except IOError as exp: logging.error(str(exp)) raise # find components by their role cls.ebeam = model.getComponent(role="e-beam") cls.sed = model.getComponent(role="se-detector") cls.ccd = model.getComponent(role="ccd") cls.light = model.getComponent(role="light") cls.light_filter = model.getComponent(role="filter")
def __init__(self, microscope, main_app): super(SpecExtraPlugin, self).__init__(microscope, main_app) # Can only be used with a SPARC with spectrometer(s) main_data = self.main_app.main_data if microscope and main_data.role.startswith("sparc"): self._tab = self.main_app.main_data.getTabByName("sparc_acqui") stctrl = self._tab.streambar_controller try: # It's normally not handled by the GUI, to need to get it ourselves self._lens2 = model.getComponent(role="lens-switch") except LookupError: logging.info("%s plugin cannot load as there is no lens 2", self.name) return if hasattr(main_data, "spectrometers"): # From Odemis 2.10 sptms = main_data.spectrometers else: # Odemis 2.9 sptms = [main_data.spectrometer, main_data.spectrometer_int] sptms = [s for s in sptms if s is not None] if not sptms: logging.info("%s plugin cannot load as there are no spectrometers", self.name) return else: logging.info("%s plugin cannot load as the microscope is not a SPARC", self.name) return for sptm in sptms: if len(sptms) <= 1: actname = "LA Spectrum" else: actname = "LA Spectrum with %s" % (sptm.name,) act = functools.partial(self.addSpectrum, name=actname, detector=sptm) stctrl.add_action(actname, act) # We "patch" the gui.conf.data for our special stream data.STREAM_SETTINGS_CONFIG[LASpectrumSettingsStream] = ( OrderedDict(( ("polarization", { # "control_type": odemis.gui.CONTROL_COMBO, }), ("wavelength", { "tooltip": "Center wavelength of the spectrograph", "control_type": odemis.gui.CONTROL_FLT, "range": (0.0, 1900e-9), }), ("grating", {}), ("slit-in", { "label": "Input slit", "tooltip": u"Opening size of the spectrograph input slit.\nA wide opening means more light and a worse resolution.", }), )) )
def setUpClass(cls): try: test.start_backend(CLSPOTS_CONFIG) except LookupError: logging.debug("A running backend is already found, skipping tests") cls.backend_was_running = True return except IOError as exp: logging.error(str(exp)) raise if TEST_NOHW: raise unittest.SkipTest('No HW present. Skipping tests.') # find components by their role cls.diagnostic_cam = model.getComponent(role="diagnostic-ccd") cls.stage = model.getComponent(role="stage") cls.ofocus = model.getComponent(role="diagnostic-cam-focus") cls._optimal_focus = 40e-6 # update with actual value
def setUpClass(cls): if driver.get_backend_status() == driver.BACKEND_RUNNING: logging.info("A running backend is already found, skipping tests") cls.backend_was_running = True return # run the backend as a daemon # we cannot run it normally as the child would also think he's in a unittest cmd = ODEMISD_CMD + ODEMISD_ARG + [SPARC_CONFIG] ret = subprocess.call(cmd) if ret != 0: logging.error("Failed starting backend with '%s'", cmd) time.sleep(1) # time to start # Find CCD & SEM components cls.ccd = model.getComponent(role="ccd") cls.spec = model.getComponent(role="spectrometer") cls.ebeam = model.getComponent(role="e-beam") cls.sed = model.getComponent(role="se-detector")
def __init__(self, res): """ res (int, int): number of pixel in X and Y """ self.res = res self.escan = model.getComponent(role="e-beam") try: self.edet = model.getComponent(role="se-detector") except LookupError: self.edet = model.getComponent(role="bs-detector") self.ccd = model.getComponent(role="ccd") self._must_stop = False self._ccd_data = [] self._ccd_data_received = threading.Event() self._sem_data = [] self._sem_data_received = threading.Event() self._hw_settings = None
def __init__(self, fn, number): self.number = number # get the components self.light = model.getComponent(role="light") self.ccd = model.getComponent(role="ccd") # prepare the data export self.exporter = dataio.find_fittest_converter(fn) # Make the name "fn" -> "~/Pictures + fn + fn-XXXX.ext" path, base = os.path.split(fn) bn, ext = os.path.splitext(base) tmpl = os.path.join(path, bn, bn + "-%05d." + ext) if path.startswith("/"): # if fn starts with / => don't add ~/Pictures self.fntmpl = tmpl else: self.fntmpl = os.path.join(get_picture_folder(), tmpl) self._n = 0
def _getComponent(self, role): """ same as model.getComponent, but optimised by caching the result return Component raise LookupError: if no component found """ try: comp = self._known_comps[role] except LookupError: comp = model.getComponent(role=role) self._known_comps[role] = comp return comp