Exemplo n.º 1
0
    def __init__(self, microscope, main_app):
        super(ZStackPlugin, self).__init__(microscope, main_app)
        # Can only be used with a microscope
        main_data = self.main_app.main_data
        
        if not microscope or main_data.focus is None:
            return

        self.focus = main_data.focus
        self._zrange = self.focus.axes['z'].range
        zunit = self.focus.axes['z'].unit
        self._old_pos = self.focus.position.value
        z = max(self._zrange[0], min(self._old_pos['z'], self._zrange[1]))
        self.zstart = model.FloatContinuous(z, range=self._zrange, unit=zunit)
        self.zstep = model.FloatContinuous(1e-6, range=(-1e-5, 1e-5), unit=zunit, setter=self._setZStep)
        self.numberOfAcquisitions = model.IntContinuous(3, (2, 999), setter=self._setNumberOfAcquisitions)

        self.filename = model.StringVA("a.h5")
        self.expectedDuration = model.VigilantAttribute(1, unit="s", readonly=True)

        self.zstep.subscribe(self._update_exp_dur)
        self.numberOfAcquisitions.subscribe(self._update_exp_dur)
        
        # Two acquisition order possible:
        # * for each Z, all the streams (aka intertwined): Z exactly the same for each stream
        # * for each stream, the whole Z stack: Might be faster (if filter wheel used for changing wavelength)
        self._streams_intertwined = True
        if main_data.light_filter and len(main_data.light_filter.axes["band"].choices) > 1:
            logging.info("Filter-wheel detected, Z-stack will be acquired stream-per-stream")
            self._streams_intertwined = False

        self._acq_streams = None  # previously folded streams, for optimisation
        self._dlg = None
        self.addMenu("Acquisition/ZStack...\tCtrl+B", self.start)
Exemplo n.º 2
0
    def __init__(self, scanner, detector):
        """
        :param scanner: (Emitter) A component with a .dwellTime, .translation, .scale.
        :param detector: (Detector) To acquire the signal.
        """
        super(AnchorDriftCorrector, self).__init__()
        self._scanner = scanner
        self._detector = detector
        self._dc_estimator = None
        self._period_acq = None  # number of acq left until next drift correction is performed

        # roi: the anchor region, it must be set to something different from
        #  UNDEFINED_ROI to run.
        # dwellTime: dwell time used when acquiring anchor region
        # period is the (approximate) time between two acquisition of the
        #  anchor (and drift compensation). The exact period is determined so
        #  that it fits with the region of acquisition.
        # Note: the scale used for the acquisition of the anchor region is
        #  selected by the AnchoredEstimator, to be as small as possible while
        #  still not scanning too many pixels.
        self.roi = model.TupleContinuous(UNDEFINED_ROI,
                                         range=((0, 0, 0, 0), (1, 1, 1, 1)),
                                         cls=(int, long, float),
                                         setter=self._setROI)
        self.dwellTime = model.FloatContinuous(scanner.dwellTime.range[0],
                                               range=scanner.dwellTime.range, unit="s")
        # in seconds, default to "fairly frequent" to work hopefully in most cases
        self.period = model.FloatContinuous(10, range=(0.1, 1e6), unit="s")
Exemplo n.º 3
0
    def __init__(self, name, detector, emitter, spectrograph, opm=None):
        """
        name (string): user-friendly name of this stream
        detector (Detector): the monochromator
        emitter (Emitter): the emitter (eg: ebeam scanner)
        spectrograph (Actuator): the spectrograph
        """
        self.name = model.StringVA(name)

        # Hardware Components
        self._detector = detector
        self._emitter = emitter
        self._sgr = spectrograph
        self._opm = opm

        self.is_active = model.BooleanVA(False)

        wlr = spectrograph.axes["wavelength"].range
        self.startWavelength = model.FloatContinuous(400e-9, wlr, unit="m")
        self.endWavelength = model.FloatContinuous(500e-9, wlr, unit="m")
        self.numberOfPixels = model.IntContinuous(51, (2, 10001), unit="px")
        # TODO: could be a local attribute?
        self.dwellTime = model.FloatContinuous(
            1e-3, range=self._emitter.dwellTime.range, unit="s")
        self.emtTranslation = model.TupleContinuous(
            (0, 0),
            range=self._emitter.translation.range,
            cls=(int, long, float),
            unit="px")

        # For acquisition
        self._pt_acq = threading.Event()
        self._data = []
        self._md = {}
Exemplo n.º 4
0
    def __init__(self, microscope, main_app):
        super(ZStackPlugin, self).__init__(microscope, main_app)
        # Can only be used with a microscope
        main_data = self.main_app.main_data

        if not microscope or main_data.focus is None:
            return

        self.focus = main_data.focus
        self._zrange = self.focus.axes['z'].range
        zunit = self.focus.axes['z'].unit
        self.old_pos = self.focus.position.value
        self.zstart = model.FloatContinuous(self.old_pos['z'],
                                            range=self._zrange,
                                            unit=zunit)
        self.zstep = model.FloatContinuous(1e-6,
                                           range=(-1e-5, 1e-5),
                                           unit=zunit,
                                           setter=self._setZStep)
        self.numberofAcquisitions = model.IntContinuous(
            3, (2, 999), setter=self._setNumberOfAcquisitions)

        self.filename = model.StringVA("a.h5")
        self.expectedDuration = model.VigilantAttribute(1,
                                                        unit="s",
                                                        readonly=True)

        self.zstep.subscribe(self._update_exp_dur)
        self.numberofAcquisitions.subscribe(self._update_exp_dur)

        self._acq_streams = None  # previously folded streams, for optimisation
        self._dlg = None
        self.addMenu("Acquisition/ZStack...\tCtrl+B", self.start)
Exemplo n.º 5
0
    def __init__(self, name, detector, sed, emitter, opm=None):
        """
        name (string): user-friendly name of this stream
        detector (Detector): the monochromator
        sed (Detector): the se-detector
        emitter (Emitter): the emitter (eg: ebeam scanner)
        spectrograph (Actuator): the spectrograph
        """
        self.name = model.StringVA(name)

        # Hardware Components, detector is the correlator, sed is the secondary electron image and the emitter is the electron beam
        self._detector = detector
        self._sed = sed
        self._emitter = emitter
        self._opm = opm

        self.is_active = model.BooleanVA(False)

        #dwell time and exposure time are the same thing in this case
        self.dwellTime = model.FloatContinuous(1, range=self._emitter.dwellTime.range,
                                               unit="s")
        # pixelDuration of correlator, this can be shortened once implemented as choices.
        self.pixelDuration = model.FloatEnumerated(512e-12,
                                choices={4e-12, 8e-12, 16e-12, 32e-12, 64e-12, 128e-12, 256e-12, 512e-12},
                                unit="s",
                                )
        #Sync Offset time correlator
        self.syncOffset = self._detector.syncOffset
        #Sync Divider time correlator
        self.syncDiv = self._detector.syncDiv 
        
        # Distance between the center of each pixel
        self.stepsize = model.FloatContinuous(1e-6, (1e-9, 1e-4), unit="m")

        # Region of acquisition. ROI form is LEFT Top RIGHT Bottom, relative to full field size
        self.roi = model.TupleContinuous((0, 0, 1, 1),
                                         range=((0, 0, 0, 0), (1, 1, 1, 1)),
                                         cls=(int, long, float))

        # Cropvalue that  can be used to crop the data for better visualization in odemis
        self.cropvalue = model.IntContinuous(1024, (1, 65536), unit="px")

        # For drift correction
        self.dcRegion = model.TupleContinuous(UNDEFINED_ROI,
                                              range=((0, 0, 0, 0), (1, 1, 1, 1)),
                                              cls=(int, long, float))
        self.dcDwellTime = model.FloatContinuous(emitter.dwellTime.range[0],
                                                 range=emitter.dwellTime.range, unit="s")
        #number of drift corrections per scanning pixel
        self.nDC = model.IntContinuous(1, (1, 20))

        # For acquisition
        self.tc_data = None
        self.tc_data_received = threading.Event()
        self.sem_data = []
        self.sem_data_received = threading.Event()
        self._hw_settings = None
Exemplo n.º 6
0
    def __init__(self, name, role, parent, hfw_nomag, **kwargs):
        model.Emitter.__init__(self, name, role, parent=parent, **kwargs)
        self.parent = parent

        # Distance between borders if magnification = 1. It should be found out
        # via calibration.
        self._hfw_nomag = hfw_nomag  # m

        self.magnification = model.FloatContinuous(
            self.parent.GetMagnification(),
            unit="",
            readonly=True,
            range=MAGNIFICATION_RANGE)
        fov_range = (self._hfw_nomag / MAGNIFICATION_RANGE[1],
                     self._hfw_nomag / MAGNIFICATION_RANGE[0])
        self.horizontalFoV = model.FloatContinuous(
            self._hfw_nomag / self.magnification.value,
            range=fov_range,
            unit="m",
            setter=self._setHorizontalFoV)
        self.horizontalFoV.subscribe(self._onHorizontalFoV)

        self.blanker = model.VAEnumerated(self.parent.GetBlankBeam(),
                                          choices={True, False},
                                          setter=self._setBlanker)

        self.external = model.VAEnumerated(self.parent.GetExternal(),
                                           choices={True, False},
                                           setter=self._setExternal)

        #self.probeCurrent = model.FloatContinuous(1e-6, range=PC_RANGE, unit="A",
        #                                          setter=self._setProbeCurrent)

        self.accelVoltage = model.FloatContinuous(
            0,
            range=(VOLTAGE_RANGE[0] * 1e3, VOLTAGE_RANGE[1] * 1e3),
            unit="V",
            setter=self._setVoltage)

        # No pixelSize as there is no shape (not a full scanner)

        # To provide some rough idea of the step size when changing focus
        # Depends on the pixelSize, so will be updated whenever the HFW changes
        self.depthOfField = model.FloatContinuous(1e-6,
                                                  range=(0, 1e3),
                                                  unit="m",
                                                  readonly=True)
        self._updateDepthOfField()

        # Refresh regularly the values, from the hardware, starting from now
        self._updateSettings()
        self._va_poll = util.RepeatingTimer(5, self._updateSettings,
                                            "Settings polling")
        self._va_poll.start()
Exemplo n.º 7
0
    def __init__(self, name, detector, dataflow, emitter):
        Stream.__init__(self, name, detector, dataflow, emitter)

        # TODO: Anti-aliasing/Pixel fuzzing
        # .fuzzing: boolean
        # Might be better to automatically activate it for Spectrum, and disable
        # it for AR (without asking the user)

        try:
            self._prevDwellTime = emitter.dwellTime.value
            emitter.dwellTime.subscribe(self.onDwellTime)
        except AttributeError:
            # if emitter has no dwell time -> no problem
            pass

        # Actually use the ROI
        self.roi.subscribe(self._onROI)

        # Spot mode: when set (and stream is active), it will drive the e-beam
        # do only the center of the scanning area. Image is not updated.
        # TODO: is this the right interface? Shall we just have a different
        # stream type?
        self.spot = model.BooleanVA(False)

        # used to reset the previous settings after spot mode
        self._no_spot_settings = (None, None, None
                                  )  # dwell time, resolution, translation
        self.spot.subscribe(self._onSpot)

        # drift correction VAs:
        # dcRegion defines the anchor region, drift correction will be disabled
        #   if it is set to UNDEFINED_ROI
        # dcDwellTime: dwell time used when acquiring anchor region
        # dcPeriod is the (approximate) time between two acquisition of the
        #  anchor (and drift compensation). The exact period is determined so
        #  that it fits with the region of acquisition.
        # Note: the scale used for the acquisition of the anchor region is the
        #  same as the scale of the SEM. We could add a dcScale if it's needed.
        self.dcRegion = model.TupleContinuous(UNDEFINED_ROI,
                                              range=((0, 0, 0, 0), (1, 1, 1,
                                                                    1)),
                                              cls=(int, long, float),
                                              setter=self._setDCRegion)
        self.dcDwellTime = model.FloatContinuous(emitter.dwellTime.range[0],
                                                 range=emitter.dwellTime.range,
                                                 unit="s")
        self.dcPeriod = model.FloatContinuous(
            10,  # s, default to "fairly frequent" to work hopefully in most cases
            range=[0.1, 1e6],
            unit="s")
Exemplo n.º 8
0
    def __init__(self, name):
        Stream.__init__(self, name, None, None, None)  #pylint: disable=W0233

        # For imitating also a FluoStream
        self.excitation = model.FloatContinuous(488e-9,
                                                range=[200e-9, 1000e-9],
                                                unit="m")
        self.emission = model.FloatContinuous(507e-9,
                                              range=[200e-9, 1000e-9],
                                              unit="m")
        defaultTint = conversion.wave2rgb(self.emission.value)
        self.tint = model.VigilantAttribute(defaultTint, unit="RGB")

        self.histogram._edges = (0, 0)
        self._calibrated = None
Exemplo n.º 9
0
    def __init__(self, microscope, main_app):
        super(TileAcqPlugin, self).__init__(microscope, main_app)

        self._dlg = None
        self._tab = None  # the acquisition tab
        self.ft = model.InstantaneousFuture()  # acquisition future
        self.microscope = microscope

        # Can only be used with a microscope
        if not microscope:
            return
        else:
            # Check if microscope supports tiling (= has a sample stage)
            main_data = self.main_app.main_data
            if main_data.stage:
                self.addMenu("Acquisition/Tile...\tCtrl+G", self.show_dlg)
            else:
                logging.info(
                    "Tile acquisition not available as no stage present")
                return

        self._ovrl_stream = None  # stream for fine alignment

        self.nx = model.IntContinuous(5, (1, 1000), setter=self._set_nx)
        self.ny = model.IntContinuous(5, (1, 1000), setter=self._set_ny)
        self.overlap = model.FloatContinuous(20, (-80, 80), unit="%")
        self.angle = model.FloatContinuous(0, (-90, 90), unit=u"°")
        self.filename = model.StringVA("a.ome.tiff")
        self.expectedDuration = model.VigilantAttribute(1,
                                                        unit="s",
                                                        readonly=True)
        self.totalArea = model.TupleVA((1, 1), unit="m", readonly=True)
        self.stitch = model.BooleanVA(True)
        self.fineAlign = model.BooleanVA(False)
        # TODO: manage focus (eg, autofocus or ask to manual focus on the corners
        # of the ROI and linearly interpolate)

        self.nx.subscribe(self._update_exp_dur)
        self.ny.subscribe(self._update_exp_dur)
        self.fineAlign.subscribe(self._update_exp_dur)
        self.nx.subscribe(self._update_total_area)
        self.ny.subscribe(self._update_total_area)
        self.overlap.subscribe(self._update_total_area)

        # Warn if memory will be exhausted
        self.nx.subscribe(self._memory_check)
        self.ny.subscribe(self._memory_check)
        self.stitch.subscribe(self._memory_check)
Exemplo n.º 10
0
    def __init__(self, name, ccd, emitter, emd):
        """
        name (string): user-friendly name of this stream
        ccd (Camera): the ccd
        emitter (Emitter): the emitter (eg: ebeam scanner)
        emd (Detector): the SEM detector (eg: SED)
        """
        self.name = model.StringVA(name)

        # Hardware Components
        self._detector = emd
        self._emitter = emitter
        self._ccd = ccd

        # 0.1s is a bit small, but the algorithm will automaticaly try with
        # longer dwell times if no spot is visible first.
        self.dwellTime = model.FloatContinuous(0.1,
                                               range=emitter.dwellTime.range,
                                               unit="s")
        # The number of points in the grid
        self.repetition = model.ResolutionVA(
            (4, 4),  # good default
            range=((2, 2), (16, 16)))

        # Future generated by find_overlay
        self._overlay_future = None
Exemplo n.º 11
0
    def __init__(self, detector, selector=None):
        """
        detector (Detector): the probe current detector (which has a data of shape
         (1,)
        selector (Actuator or None): If available, will use it to "activate" the
          probe current detector. It requires a "x" axis with True/False choices,
          and where True is active.
        """
        LeechAcquirer.__init__(self)

        self._detector = detector
        self._selector = selector
        if selector:
            if "x" not in selector.axes:
                raise ValueError("Selector needs a x axis")
            choices = selector.axes["x"].choices
            if isinstance(choices, set) and not {True, False} <= choices:
                raise ValueError("Selector axis x has not True and False positions")
            # TODO: also handle choices as a dict val -> True/False

        # How often the acquisition should be done
        # At least one acquisition at init, and one at the end will run anyway
        self.period = model.FloatContinuous(60, (1e-9, 3600), unit="s")

        # For computing the next pixels
        self._pixels = 0  # How many pixels acquired so far
        self._acqs = 0  # How many (internal) acquisitions done so far
        self._pxs = 1  # (1<=float) number of pixels per period
        self._tot_acqs = 1  # How many acquisitions should be done (including the first one)

        # Ordered measurements done so far
        self._measurements = []  # (float, float) -> time, current (Amp)
Exemplo n.º 12
0
    def __init__(self, fake_img):
        """
        Use .fake_img to change the image sent by the ccd
        Args:
            fake_img: 2D DataArray
        """
        super(FakeCCD, self).__init__("testccd", "ccd")
        self.exposureTime = model.FloatContinuous(0.1, (1e-6, 1000), unit="s")
        res = fake_img.shape[1], fake_img.shape[0]  # X, Y
        depth = 2 ** (fake_img.dtype.itemsize * 8)
        self.shape = (res[0], res[1], depth)
        self.binning = model.TupleContinuous((1, 1), [(1, 1), (8, 8)],
                                       cls=(int, long, float), unit="")
        self.resolution = model.ResolutionVA(res, [(1, 1), res])
        self.readoutRate = model.FloatVA(1e9, unit="Hz", readonly=True)

        pxs_sens = fake_img.metadata.get(model.MD_SENSOR_PIXEL_SIZE, (10e-6, 10e-6))
        self.pixelSize = model.VigilantAttribute(pxs_sens, unit="m", readonly=True)

        self.data = CCDDataFlow(self)
        self._acquisition_thread = None
        self._acquisition_lock = threading.Lock()
        self._acquisition_init_lock = threading.Lock()
        self._acquisition_must_stop = threading.Event()
        self.fake_img = fake_img

        self._metadata = fake_img.metadata
Exemplo n.º 13
0
    def __init__(self, microscope, main_app):
        super(CLAcqPlugin, self).__init__(microscope, main_app)
        # Can only be used with a microscope
        if not microscope:
            return
        else:
            # Check which stream the microscope supports
            main_data = self.main_app.main_data
            if not (main_data.ccd and main_data.ebeam):
                return

        self.exposureTime = main_data.ccd.exposureTime
        self.binning = main_data.ccd.binning
        # Trick to pass the component (ccd to binning_1d_from_2d())
        self.vaconf["binning"]["choices"] = (
            lambda cp, va, cf: gui.conf.util.binning_1d_from_2d(
                main_data.ccd, va, cf))
        self.xres = model.IntContinuous(10, (1, 1000), unit="px")
        self.yres = model.IntContinuous(10, (1, 1000), unit="px")
        self.stepsize = model.FloatVA(1e-6, unit="m")  # Just to show
        # Maximum margin is half the CCD FoV
        ccd_rect = get_ccd_fov(main_data.ccd)
        max_margin = max(ccd_rect[2] - ccd_rect[0],
                         ccd_rect[3] - ccd_rect[1]) / 2
        self.roi_margin = model.FloatContinuous(0, (0, max_margin), unit="m")
        self.filename = model.StringVA("a.tiff")

        self.xres.subscribe(self._update_stepsize)
        self.yres.subscribe(self._update_stepsize)

        self.addMenu("Acquisition/CL acquisition...", self.start)
Exemplo n.º 14
0
 def __init__(self, *args, **kwargs):
     model.HwComponent.__init__(self, *args, **kwargs)
     self.data = FakeDataFlow()
     # TODO automatically register the property when serializing the Component
     self.prop = model.IntVA(42)
     self.cont = model.FloatContinuous(2.0, [-1, 3.4])
     self.enum = model.StringEnumerated("a", {"a", "c", "bfds"})
Exemplo n.º 15
0
    def __init__(self, name, role, mag, pole_pos=None, **kwargs):
        """
        name (string): should be the name of the product (for metadata)
        mag (float > 0): magnification ratio
        pole_pos (2 floats > 0): position of the pole on the CCD (in px, without
          binning). Used for angular resolved imaging on SPARC (only).
          cf MD_AR_POLE
        """
        assert (mag > 0)
        model.HwComponent.__init__(self, name, role, **kwargs)

        self._swVersion = "N/A (Odemis %s)" % odemis.__version__
        self._hwVersion = name

        # allow the user to modify the value, if the lens is manually changed
        self.magnification = model.FloatContinuous(mag,
                                                   range=[1e-3, 1e6],
                                                   unit="")

        if pole_pos is not None:
            if (not isinstance(pole_pos, collections.Iterable)
                    or len(pole_pos) != 2 or any(v < 0 for v in pole_pos)):
                raise ValueError("pole_pos must be 2 positive values, got %s" %
                                 pole_pos)
            self.polePosition = model.ResolutionVA(pole_pos,
                                                   range=[(0, 0), (1e6, 1e6)])
Exemplo n.º 16
0
    def __init__(self, microscope, main_app):
        super(AveragePlugin, self).__init__(microscope, main_app)
        # Can only be used with a microscope
        if not microscope:
            return

        # Check which stream the microscope supports
        main_data = self.main_app.main_data
        if not main_data.ebeam:
            return

        self.addMenu("Acquisition/Averaged frame...", self.start)

        dt = main_data.ebeam.dwellTime
        dtrg = (dt.range[0], min(dt.range[1], 1))
        self.dwellTime = model.FloatContinuous(dt.value,
                                               range=dtrg,
                                               unit=dt.unit)
        self.scale = main_data.ebeam.scale
        # Trick to pass the component (ebeam to binning_1d_from_2d())
        self.vaconf["scale"]["choices"] = (
            lambda cp, va, cf: odemis.gui.conf.util.binning_1d_from_2d(
                self.main_app.main_data.ebeam, va, cf))
        self.resolution = main_data.ebeam.resolution  # Just for info
        self.accumulations = model.IntContinuous(10, (1, 10000))
        self.filename = model.StringVA("a.h5")
        self.expectedDuration = model.VigilantAttribute(1,
                                                        unit="s",
                                                        readonly=True)

        self.dwellTime.subscribe(self._update_exp_dur)
        self.accumulations.subscribe(self._update_exp_dur)
        self.scale.subscribe(self._update_exp_dur)
Exemplo n.º 17
0
    def __init__(self, microscope, main_app):
        super(TimelapsePlugin, self).__init__(microscope, main_app)
        # Can only be used with a microscope
        if not microscope:
            return

        self.period = model.FloatContinuous(10, (1e-3, 10000),
                                            unit="s",
                                            setter=self._setPeriod)
        # TODO: prevent period < acquisition time of all streams
        self.numberOfAcquisitions = model.IntContinuous(100, (2, 100000))
        self.semOnlyOnLast = model.BooleanVA(False)
        self.filename = model.StringVA("a.h5")
        self.expectedDuration = model.VigilantAttribute(1,
                                                        unit="s",
                                                        readonly=True)

        self.period.subscribe(self._update_exp_dur)
        self.numberOfAcquisitions.subscribe(self._update_exp_dur)

        # On SECOM/DELPHI, propose to only acquire the SEM at the end
        if microscope.role in ("secom", "delphi"):
            self.vaconf["semOnlyOnLast"][
                "control_type"] = odemis.gui.CONTROL_CHECK

        self._dlg = None
        self.addMenu("Acquisition/Timelapse...\tCtrl+T", self.start)

        self._to_store = queue.Queue(
        )  # queue of tuples (str, [DataArray]) for saving data
        self._sthreads = []  # the saving threads
        self._exporter = None  # dataio exporter to use
Exemplo n.º 18
0
    def __init__(self, name, role, port, baudrate=9600, idn=None, **kwargs):
        '''
        port (str): port name. Can be a pattern, in which case it will pick the
          first one which responds well
        baudrate (int): the baudrate setting for the RS232 connection
        idn (str or None): If present, a regex to match the *IDN command. For
         instance "KEITHLEY.+MODEL 6485.+12345678".
        '''
        model.Detector.__init__(self, name, role, **kwargs)

        self._ser_access = threading.Lock()
        self._serial = None
        self._file = None
        self._port, self._idn = self._findDevice(
            port, baudrate, idn)  # sets ._serial and ._file
        logging.info("Found SPCI device on port %s", self._port)

        driver_name = driver.getSerialDriver(self._port)
        self._swVersion = "serial driver: %s" % (driver_name, )
        self._hwVersion = self._idn

        # Just for logging, check if there are any errors reported
        while True:
            n, msg = self.ReadNextError()
            if n is not None:
                logging.warning("Discarding previous error %s (%d)", msg, n)
            else:
                break

        stat = self.ReadStatusByte()
        if stat & (1 << 2):  # Bit 2 = error available
            # It seems that some status is not bad anyway
            logging.warning("Status byte is %d", stat)

        self.ClearStatus()

        self._lfr = self.GetLineFrequency()

        # Force range to auto
        self._sendOrder(":CURR:RANG:AUTO ON")
        self._checkError()
        # Prepare to measure current
        self.ConfigureCurrent()
        self._checkError()

        # TODO: that's probably very Keithley 6485
        rate = self.GetIntegrationRate()
        self._checkError()
        # Note: the lowest noise is at rate between 1 and 10, so ~20ms to 200ms
        # The max rate is the line frequency (=> 1 s)
        self.dwellTime = model.FloatContinuous(rate / self._lfr,
                                               (0.01 / self._lfr, 1),
                                               unit="s",
                                               setter=self._setDwellTime)

        self._shape = (float("inf"), )  # only one point, with float values
        self._generator = None
        self.data = BasicDataFlow(self)
        self._metadata[model.MD_DET_TYPE] = model.MD_DT_NORMAL
Exemplo n.º 19
0
    def __init__(self, name):
        self._calibrated = None
        Stream.__init__(self, name, None, None, None)
        self.histogram._edges = (0, 0)

        minb, maxb = 0, 1  # unknown/unused
        pixel_width = 0.01

        self.centerWavelength = model.FloatContinuous((1 + minb) / 2,
                                                      range=(minb, maxb),
                                                      unit="m")
        max_bw = maxb - minb
        self.bandwidth = model.FloatContinuous(max_bw / 12,
                                               range=(pixel_width, max_bw),
                                               unit="m")

        self.fitToRGB = model.BooleanVA(True)
Exemplo n.º 20
0
    def __init__(self, name, detector, dataflow, emitter):
        self.name = model.StringVA(name)

        # Hardware Components
        self._detector = detector  # the spectrometer
        self._emitter = emitter  # the e-beam
        # To acquire simultaneously other detector (ex: SEM secondary electrons)
        # a separate stream must be used, and the acquisition manager will take
        # care of doing both at the same time

        # data-flow of the spectrometer
        self._dataflow = dataflow

        self.raw = []  # to contain data during acquisition (from MD streams)

        # all the information needed to acquire an image (in addition to the
        # hardware component settings which can be directly set).

        # ROI + repetition is sufficient, but pixel size is nicer for the user
        # and allow us to ensure each pixel is square. (Non-square pixels are
        # not a problem for the hardware, but annoying to display data in normal
        # software).

        # We ensure in the setters that all the data is always consistent:
        # roi set: roi + pxs → repetition + roi + pxs
        # pxs set: roi + pxs → repetition + roi (small changes)
        # repetition set: repetition + roi + pxs → repetition + pxs + roi (small changes)

        # Region of interest as left, top, right, bottom (in ratio from the
        # whole area of the emitter => between 0 and 1)
        self.roi = model.TupleContinuous((0, 0, 1, 1),
                                         range=[(0, 0, 0, 0), (1, 1, 1, 1)],
                                         cls=(int, long, float),
                                         setter=self._setROI)
        # the number of pixels acquired in each dimension
        # it will be assigned to the resolution of the emitter (but cannot be
        # directly set, as one might want to use the emitter while configuring
        # the stream).
        self.repetition = model.ResolutionVA(emitter.resolution.value,
                                             emitter.resolution.range,
                                             setter=self._setRepetition)

        # the size of the pixel, horizontally and vertically
        # actual range is dynamic, as it changes with the magnification
        self.pixelSize = model.FloatContinuous(emitter.pixelSize.value[0],
                                               range=[0, 1],
                                               unit="m",
                                               setter=self._setPixelSize)

        # exposure time of each pixel is the exposure time of the detector,
        # the dwell time of the emitter will be adapted before acquisition.

        # Update the pixel size whenever SEM magnification changes
        # This allows to keep the ROI at the same place in the SEM FoV.
        # Note: this is to be done only if the user needs to manually update the
        # magnification.
        self._prev_mag = emitter.magnification.value
        emitter.magnification.subscribe(self._onMagnification)
Exemplo n.º 21
0
    def __init__(self, name, detector, dataflow, emitter):
        CameraStream.__init__(self, name, detector, dataflow, emitter)
        self._raw_date = []  # time of each raw acquisition (=count)
        self.image.value = model.DataArray([])  # start with an empty array

        # time over which to accumulate the data. 0 indicates that only the last
        # value should be included
        # TODO: immediately cut window when the value changes
        self.windowPeriod = model.FloatContinuous(30, range=[0, 1e6], unit="s")
Exemplo n.º 22
0
    def test_continuous(self):
        prop = model.FloatContinuous(2.0, [-1, 3.4])
        self.assertEqual(prop.value, 2)
        self.assertEqual(prop.range, (-1, 3.4))

        self.called = 0
        prop.subscribe(self.callback_test_notify)
        # now count
        prop.value = 3.0  # +1
        self.assertEqual(prop.value, 3)

        try:
            prop.value = 4.0
            self.fail("Assigning out of bound should not be allowed.")
        except IndexError:
            pass  # as it should be

        try:
            prop.range = [-4.0, 1.0]
            self.fail(
                "Assigning range not containing current value should not be allowed."
            )
        except IndexError:
            pass  # as it should be

        try:
            prop.clip_on_range = True
            self.assertEqual(prop.value, 3.0,
                             "Value should not have changed yet")
            prop.range = [-4.0, 1.0]
            self.assertEqual(prop.value, 1.0, "Value should have been clipped")
            prop.clip_on_range = False
        except IndexError:
            pass  # as it should be

        try:
            prop.range = [12]
            self.fail("Range should be allowed only if it's a 2-tuple.")
        except TypeError:
            pass  # as it should be

        self.assertTrue(self.called == 2)

        # "value" update for each change for range change
        prop.range = [-4.0, 4.0]
        self.assertTrue(self.called == 3)

        prop.unsubscribe(self.callback_test_notify)

        # Test a bit the IntContinuous
        prop2 = model.IntContinuous(2, [1, 34], unit="px")
        self.assertEqual(prop2.value, 2)
        self.assertEqual(prop2.range, (1, 34))

        prop2.value = 30
        self.assertEqual(prop2.value, 30)
        self.assertIsInstance(prop2.value, int)
Exemplo n.º 23
0
    def __init__(self, name, role, parent, **kwargs):
        """
        Note: parent should have a child "scanner" already initialised
        """
        # It will set up ._shape and .parent
        model.Detector.__init__(self, name, role, parent=parent, **kwargs)
        self.data = SEMDataFlow(self, parent)
        self._acquisition_thread = None
        self._acquisition_lock = threading.Lock()
        self._acquisition_init_lock = threading.Lock()
        self._acquisition_must_stop = threading.Event()

        self.fake_img = self.parent.fake_img
        # The shape is just one point, the depth
        idt = numpy.iinfo(self.fake_img.dtype)
        data_depth = idt.max - idt.min + 1
        self._shape = (data_depth,) # only one point

        # 8 or 16 bits image
        if data_depth == 255:
            bpp = 8
        else:
            bpp = 16
        self.bpp = model.IntEnumerated(bpp, {8, 16})

        # Simulate the Hw brightness/contrast, but don't actually do anything
        self.contrast = model.FloatContinuous(0.5, [0, 1], unit="")
        self.brightness = model.FloatContinuous(0.5, [0, 1], unit="")

        self.drift_factor = 2  # dummy value for drift in pixels
        self.current_drift = 0
        # Given that max resolution is half the shape of fake_img,
        # we set the drift bound to stay inside the fake_img bounds
        self.drift_bound = min(v // 4 for v in self.fake_img.shape[::-1])
        self._update_drift_timer = util.RepeatingTimer(parent._drift_period,
                                                       self._update_drift,
                                                       "Drift update")
        if parent._drift_period:
            self._update_drift_timer.start()

        # Special event to request software unblocking on the scan
        self.softwareTrigger = model.Event()

        self._metadata[model.MD_DET_TYPE] = model.MD_DT_NORMAL
Exemplo n.º 24
0
    def __init__(self, microscope, main_app):
        super(SpikeRemovalPlugin, self).__init__(microscope, main_app)
        self.addMenu("Data correction/Spike removal...", self.start)
        self._dlg = None
        self._spec_stream = None

        # create VA for threshold
        self.threshold = model.FloatContinuous(8, range=(1, 20), unit="")
        self.npixels = model.IntVA(0, unit="", readonly=True)
        self.nspikes = model.IntVA(0, unit="", readonly=True)
Exemplo n.º 25
0
    def test_va_connector(self):
        va = model.FloatContinuous(0.3, (0.0, 1.0))

        slider = UnitFloatSlider(self.panel, value=0.5, size=(-1, 18), unit="s",
                                 min_val=0.0, max_val=1.0)

        self.add_control(slider, flags=wx.EXPAND | wx.ALL)

        self.assertEqual(slider.GetValue(), 0.5)

        test.gui_loop(0.5)

        # Setting and getting the value directly should give the same value
        slider.SetValue(0.6)
        test.gui_loop(0.2)
        self.assertEqual(slider.GetValue(), 0.6)

        # After connecting the VA the control should have the same value as the VA
        con = widgets.VigilantAttributeConnector(va, slider, events=wx.EVT_SLIDER)
        test.gui_loop(0.2)
        self.assertEqual(slider.GetValue(), 0.3)

        # Chaning the VA changes the control value
        va.value = 0.8
        test.gui_loop(0.2)
        self.assertEqual(slider.GetValue(), 0.8)

        # When pausing the VA, the control value should not change when the VA's does
        con.pause()
        va.value = 0.9
        test.gui_loop(0.2)
        self.assertEqual(slider.GetValue(), 0.8)

        # Resuming the connection should update the control to the VA's current value
        con.resume()
        test.gui_loop(0.2)
        self.assertEqual(slider.GetValue(), 0.9)

        # When the control is manipulated, the VA's value is updated
        slider.SetValue(0.1)
        slider._send_slider_update_event()  # Simulate a real user generated event
        test.gui_loop(0.2)
        self.assertEqual(va.value, 0.1)

        # When the connection is paused, changes in the control are not passed to the VA
        con.pause()
        slider.SetValue(0.2)
        slider._send_slider_update_event()  # Simulate a real user generated event
        test.gui_loop(0.2)
        self.assertEqual(va.value, 0.1)

        # Resuming causes the value of the **VA** to be passed to the control
        con.resume()
        test.gui_loop(0.2)
        self.assertEqual(slider.GetValue(), 0.1)
Exemplo n.º 26
0
    def __init__(self, microscope, main_app):
        super(SimplePlugin, self).__init__(microscope, main_app)
        # if not microscope:
        #     return

        self.main_data = self.main_app.main_data
        #         if not self.main_data.ccd:
        #             return

        self.addMenu("Acquisition/Fancy acquisition...", self.start)
        self.exposureTime = model.FloatContinuous(2, (0, 10), unit="s")
        self.filename = model.StringVA("boo.h5")
Exemplo n.º 27
0
    def __init__(self, name, role, parent, daemon=None, **kwargs):
        super(DelayGenerator, self).__init__(name, role, parent=parent, daemon=daemon, **kwargs)  # init HwComponent

        self.parent = parent

        self._metadata[model.MD_HW_VERSION] = "Simulated delay generator DG645"

        range_trigDelay = [0.0, 1]  # sec
        # set default value according to timeRange setting (look up in MD)
        self.triggerDelay = model.FloatContinuous(0.0, range_trigDelay, setter=self._setTriggerDelay, unit="s")

        self._metadata[model.MD_TRIGGER_DELAY] = self.triggerDelay.value
        self._metadata[model.MD_TRIGGER_RATE] = 1000000
Exemplo n.º 28
0
    def __init__(self, name, role, **kwargs):
        model.Emitter.__init__(self, name, role, **kwargs)

        self._shape = ()
        self.power = model.FloatContinuous(0., [0., 100.], unit="W")
        self.power.subscribe(self._updatePower)
        # just one band: white
        # emissions is list of 0 <= floats <= 1. Always 1.0: cannot lower it.
        self.emissions = model.ListVA([1.0], unit="", setter=lambda x: [1.0])
        self.spectra = model.ListVA(
            [(380e-9, 160e-9, 560e-9, 960e-9, 740e-9)],
            unit="m",
            readonly=True)  # list of 5-tuples of floats
Exemplo n.º 29
0
    def __init__(self, name, role, ports, **kwargs):
        """
        ports (string): pattern of the name of the serial ports to try to connect to
          find the devices. It can have a "glob", for example: "/dev/ttyUSB*"
        """
        model.Emitter.__init__(self, name, role, **kwargs)
        self._ports = ports
        self._master, self._devices = self._getAvailableDevices(ports)
        if not self._devices:
            raise HwError(
                "No Omicron xX device found for ports '%s', check "
                "that '%s' is turned on and connected to the computer." %
                (ports, name))

        spectra = [
        ]  # list of tuples: 99% low, 25% low, centre, 25% high, 99% high in m
        max_power = []  # list of float (W)
        for d in self._devices:
            spectra.append(d.wavelength)
            max_power.append(d.max_power)

        self._shape = ()

        # power of the whole device (=> max power of the device with max power)
        self.power = model.FloatContinuous(0., (0., max(max_power)), unit="W")
        self.power.subscribe(self._updatePower)

        # ratio of power per device
        # => if some device don't support max power, clamped before 1
        self.emissions = model.ListVA([0.] * len(self._devices),
                                      unit="",
                                      setter=self._setEmissions)
        # info on what device is which wavelength
        self.spectra = model.ListVA(spectra, unit="m", readonly=True)

        # Ensure the whole Hub is turned on
        if self._master:
            try:
                self._master.PowerOn()
            except OXXError:
                raise HwError(
                    "Failed to power on the master device, check the interlock."
                )

        # make sure everything is off (turning on the HUB will turn on the lights)
        self._updateIntensities(self.power.value, self.emissions.value)

        # set SW version
        driver_name = self._devices[0].acc.driver
        self._swVersion = "%s (serial driver: %s)" % (odemis.__version__,
                                                      driver_name)
Exemplo n.º 30
0
    def __init__(self, name, role, parent, **kwargs):
        '''
        parent (symphotime.Controller): a symphotime server parent object
        '''
        # we will fill the set of children with Components later in ._children
        model.Emitter.__init__(self, name, role, parent=parent, **kwargs)
        self._shape = (2048, 2048) # Max resolution

        # Define VA's as references to the parent.
        self.filename = model.StringVA(setter=self._setFilename)
        self.directory = model.StringVA(setter=self._setDirectory)
        self.resolution = model.ResolutionVA((64, 64), ((1, 1), (2048, 2048)))
        self.bidirectional = model.BooleanVA(value=False)
        self.dwellTime = model.FloatContinuous(value=10e-6, range=DWELLTIME_RNG, unit="s")