Esempio n. 1
0
    def __init__(self, name, image):
        """
        Note: parameters are different from the base class.
        image (DataArray of shape (111)YX): raw data. The metadata should
          contain at least MD_POS and MD_PIXEL_SIZE. It should also contain
          MD_IN_WL and MD_OUT_WL.
        """
        # Note: it will update the image, and changing the tint will do it again
        super(StaticFluoStream, self).__init__(name, image)

        # Wavelengths
        try:
            exc_range = image.metadata[model.MD_IN_WL]
            self.excitation = VigilantAttribute(exc_range, unit="m",
                                                readonly=True)
        except KeyError:
            logging.warning("No excitation wavelength for fluorescence stream")

        default_tint = (0, 255, 0)  # green is most typical
        try:
            em_range = image.metadata[model.MD_OUT_WL]
            if isinstance(em_range, basestring):
                unit = None
            else:
                unit = "m"
                default_tint = conversion.wave2rgb(numpy.mean(em_range))
            self.emission = VigilantAttribute(em_range, unit=unit,
                                              readonly=True)
        except KeyError:
            logging.warning("No emission wavelength for fluorescence stream")

        # colouration of the image
        tint = image.metadata.get(model.MD_USER_TINT, default_tint)
        self.tint.value = tint
Esempio n. 2
0
    def __init__(self, name, image):
        """
        Note: parameters are different from the base class.
        image (DataArray of shape (111)YX): raw data. The metadata should
          contain at least MD_POS and MD_PIXEL_SIZE. It should also contain
          MD_IN_WL and MD_OUT_WL.
        """
        # Wavelengths
        try:
            exc_range = image.metadata[model.MD_IN_WL]
            self.excitation = VigilantAttribute(exc_range, unit="m",
                                                readonly=True)
        except KeyError:
            logging.warning("No excitation wavelength for fluorescence stream")

        try:
            em_range = image.metadata[model.MD_OUT_WL]
            self.emission = VigilantAttribute(em_range, unit="m",
                                              readonly=True)

            default_tint = conversion.wave2rgb(numpy.mean(em_range))
        except KeyError:
            logging.warning("No emission wavelength for fluorescence stream")
            default_tint = (0, 255, 0) # green is most typical

        # colouration of the image
        tint = image.metadata.get(model.MD_USER_TINT, default_tint)
        self.tint = model.ListVA(tint, unit="RGB") # 3-tuple R,G,B
        self.tint.subscribe(self.onTint)

        # Do it at the end, as it forces it the update of the image
        StaticStream.__init__(self, name, image)
Esempio n. 3
0
    def __init__(self, name, image):
        """
        Note: parameters are different from the base class.
        image (DataArray of shape (111)YX): raw data. The metadata should
          contain at least MD_POS and MD_PIXEL_SIZE. It should also contain
          MD_IN_WL and MD_OUT_WL.
        """
        # Wavelengths
        try:
            exc_range = image.metadata[model.MD_IN_WL]
            self.excitation = VigilantAttribute(exc_range,
                                                unit="m",
                                                readonly=True)
        except KeyError:
            logging.warning("No excitation wavelength for fluorescence stream")

        try:
            em_range = image.metadata[model.MD_OUT_WL]
            self.emission = VigilantAttribute(em_range,
                                              unit="m",
                                              readonly=True)

            default_tint = conversion.wave2rgb(numpy.mean(em_range))
        except KeyError:
            logging.warning("No emission wavelength for fluorescence stream")
            default_tint = (0, 255, 0)  # green is most typical

        # colouration of the image
        tint = image.metadata.get(model.MD_USER_TINT, default_tint)
        self.tint = model.ListVA(tint, unit="RGB")  # 3-tuple R,G,B
        self.tint.subscribe(self.onTint)

        # Do it at the end, as it forces it the update of the image
        StaticStream.__init__(self, name, image)
Esempio n. 4
0
    def __init__(self, name, raw):
        """
        Note: parameters are different from the base class.
        raw (DataArray of shape (111)YX): raw data. The metadata should
          contain at least MD_POS and MD_PIXEL_SIZE. It should also contain
          MD_IN_WL and MD_OUT_WL.
        """
        # Note: it will update the image, and changing the tint will do it again
        super(StaticFluoStream, self).__init__(name, raw)

        # Wavelengths
        try:
            exc_range = raw.metadata[model.MD_IN_WL]
            self.excitation = VigilantAttribute(exc_range, unit="m",
                                                readonly=True)
        except KeyError:
            logging.warning("No excitation wavelength for fluorescence stream")

        default_tint = (0, 255, 0)  # green is most typical
        try:
            em_range = raw.metadata[model.MD_OUT_WL]
            if isinstance(em_range, basestring):
                unit = None
            else:
                unit = "m"
                default_tint = conversion.wave2rgb(numpy.mean(em_range))
            self.emission = VigilantAttribute(em_range, unit=unit,
                                              readonly=True)
        except KeyError:
            logging.warning("No emission wavelength for fluorescence stream")

        # colouration of the image
        tint = raw.metadata.get(model.MD_USER_TINT, default_tint)
        self.tint.value = tint
Esempio n. 5
0
 def test_wave2rgb(self):
     #         (input) (expected output)
     values = [(200.51513e-9, (255, 0, 255)),
               (350e-9, (255, 0, 255)),
               (490e-9, (0, 255, 255)),
               (700e-9, (255, 0, 0)),
               (900.5e-9, (255, 0, 0)),
               ]
     for (i, eo) in values:
         o = conversion.wave2rgb(i)
         self.assertEquals(o, eo, u"%f nm -> %s should be %s" % (i * 1e9, o, eo))
Esempio n. 6
0
 def test_wave2rgb(self):
     #         (input) (expected output)
     values = [(200.51513e-9, (255, 0, 255)),
               (350e-9, (255, 0, 255)),
               (490e-9, (0, 255, 255)),
               (700e-9, (255, 0, 0)),
               (900.5e-9, (255, 0, 0)),
               ]
     for (i, eo) in values:
         o = conversion.wave2rgb(i)
         self.assertEquals(o, eo, u"%f nm -> %s should be %s" % (i * 1e9, o, eo))
Esempio n. 7
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
Esempio 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
Esempio n. 9
0
    def __init__(self, name):
        Stream.__init__(self, name, None, None, None)

        # For imitating a FluoStream
        self.excitation = model.VAEnumerated(
            (4.2e-07, 4.3e-07, 4.38e-07, 4.45e-07, 4.55e-07),
            # multiple spectra
            choices={(4.2e-07, 4.3e-07, 4.38e-07, 4.45e-07, 4.55e-07),
                     (3.75e-07, 3.9e-07, 4e-07, 4.02e-07, 4.05e-07),
                     (5.65e-07, 5.7e-07, 5.75e-07, 5.8e-07, 5.95e-07),
                     (5.25e-07, 5.4e-07, 5.5e-07, 5.55e-07, 5.6e-07),
                     (4.95e-07, 5.05e-07, 5.13e-07, 5.2e-07, 5.3e-07)},
            unit="m")
        self.emission = model.VAEnumerated(
            (500e-9, 520e-9),
            # one (fixed) multi-band
            choices={(100e-9, 150e-9), (500e-9, 520e-9), (600e-9, 650e-9)},
            unit="m")
        default_tint = conversion.wave2rgb(488e-9)
        self.tint = model.VigilantAttribute(default_tint, unit="RGB")

        self.histogram._edges = (0, 0)
Esempio n. 10
0
    def __init__(self, name):
        Stream.__init__(self, name, None, None, None)

        # For imitating a FluoStream
        self.excitation = model.VAEnumerated(
            (4.2e-07, 4.3e-07, 4.38e-07, 4.45e-07, 4.55e-07),
            # multiple spectra
            choices={(4.2e-07, 4.3e-07, 4.38e-07, 4.45e-07, 4.55e-07),
                     (3.75e-07, 3.9e-07, 4e-07, 4.02e-07, 4.05e-07),
                     (5.65e-07, 5.7e-07, 5.75e-07, 5.8e-07, 5.95e-07),
                     (5.25e-07, 5.4e-07, 5.5e-07, 5.55e-07, 5.6e-07),
                     (4.95e-07, 5.05e-07, 5.13e-07, 5.2e-07, 5.3e-07)},
            unit="m")
        self.emission = model.VAEnumerated(
            (500e-9, 520e-9),
            # one (fixed) multi-band
            choices={(100e-9, 150e-9), (500e-9, 520e-9), (600e-9, 650e-9)},
            unit="m")
        default_tint = conversion.wave2rgb(488e-9)
        self.tint = model.VigilantAttribute(default_tint, unit="RGB")

        self.histogram._edges = (0, 0)
Esempio n. 11
0
    def __init__(self, name, detector, dataflow, emitter, em_filter):
        """
        name (string): user-friendly name of this stream
        detector (Detector): the detector which has the dataflow
        dataflow (Dataflow): the dataflow from which to get the data
        emitter (Light): the HwComponent to modify the light excitation
        filter (Filter): the HwComponent to modify the emission light filtering
        """
        CameraStream.__init__(self, name, detector, dataflow, emitter)
        self._em_filter = em_filter

        # Emission and excitation are based on the hardware capacities.
        # For excitation, compared to the hardware, only one band at a time can
        # be selected. The difficulty comes to pick the default value. The best
        # would be to use the current hardware value, but if the light is off
        # there is no default value. In that case, we pick the emission value
        # and try to pick a compatible excitation value: the first excitation
        # wavelength below the emission. However, the emission value might also
        # be difficult to know if there is a multi-band filter. In that case we
        # just pick the lowest value.
        # TODO: once the streams have their own version of the hardware settings
        # and in particular light.power, it should be possible to turn off the
        # light just by stopping the power, and so leaving the emissions as is.

        em_choices = em_filter.axes["band"].choices.copy()
        # convert any list into tuple, as lists cannot be put in a set
        for k, v in em_choices.items():
            em_choices[k] = conversion.ensureTuple(v)

        # invert the dict, to directly convert the emission to the position value
        self._emission_to_idx = dict((v, k) for k, v in em_choices.items())

        cur_pos = em_filter.position.value["band"]
        current_em = em_choices[cur_pos]
        if isinstance(current_em[0], collections.Iterable):
            # if multiband => pick the first one
            em_band = current_em[0]
        else:
            em_band = current_em
        center_em = fluo.get_center(em_band)

        exc_choices = set(emitter.spectra.value)
        current_exc = self._get_current_excitation()
        if current_exc is None:
            # pick the closest below the current emission
            current_exc = min(exc_choices, key=lambda b: b[2]) # default to the smallest
            for b in exc_choices:
                # Works because exc_choices only contains 5-float tuples
                if (b[2] < center_em and
                    center_em - b[2] < center_em - current_exc[2]):
                    current_exc = b
            logging.debug("Guessed excitation is %s, based on emission %s",
                          current_exc, current_em)

        self.excitation = model.VAEnumerated(current_exc, choices=exc_choices,
                                             unit="m")
        self.excitation.subscribe(self.onExcitation)

        # The wavelength band on the out path (set when emission changes)
        self.emission = model.VAEnumerated(current_em, choices=set(em_choices.values()),
                                           unit="m")
        self.emission.subscribe(self.onEmission)

        # colouration of the image
        default_tint = conversion.wave2rgb(center_em)
        self.tint = model.ListVA(default_tint, unit="RGB") # 3-tuple R,G,B
        self.tint.subscribe(self.onTint)
Esempio n. 12
0
    def __init__(self, name, detector, dataflow, emitter, em_filter, **kwargs):
        """
        name (string): user-friendly name of this stream
        detector (Detector): the detector which has the dataflow
        dataflow (Dataflow): the dataflow from which to get the data
        emitter (Light): the HwComponent to modify the light excitation
        em_filter (Filter): the HwComponent to modify the emission light filtering
        """
        super(FluoStream, self).__init__(name, detector, dataflow, emitter, **kwargs)
        self._em_filter = em_filter

        # Emission and excitation are based on the hardware capacities.
        # For excitation, compared to the hardware, only one band at a time can
        # be selected. The difficulty comes to pick the default value. The best
        # would be to use the current hardware value, but if the light is off
        # there is no default value. In that case, we pick the emission value
        # and try to pick a compatible excitation value: the first excitation
        # wavelength below the emission. However, the emission value might also
        # be difficult to know if there is a multi-band filter. In that case we
        # just pick the lowest value.
        # TODO: once the streams have their own version of the hardware settings
        # and in particular light.power, it should be possible to turn off the
        # light just by stopping the power, and so leaving the emissions as is.

        em_choices = em_filter.axes["band"].choices.copy()
        # convert any list into tuple, as lists cannot be put in a set
        for k, v in em_choices.items():
            em_choices[k] = conversion.ensure_tuple(v)

        # invert the dict, to directly convert the emission to the position value
        self._emission_to_idx = {v: k for k, v in em_choices.items()}

        cur_pos = em_filter.position.value["band"]
        current_em = em_choices[cur_pos]
        if isinstance(current_em[0], collections.Iterable):
            # if multiband => pick the first one
            em_band = current_em[0]
        else:
            em_band = current_em
        center_em = fluo.get_center(em_band)

        exc_choices = set(emitter.spectra.value)
        current_exc = self._get_current_excitation()
        if current_exc is None:
            # pick the closest below the current emission
            current_exc = min(exc_choices, key=lambda b: b[2])  # default to the smallest
            for b in exc_choices:
                # Works because exc_choices only contains 5-float tuples
                if (b[2] < center_em and
                    center_em - b[2] < center_em - current_exc[2]):
                    current_exc = b
            logging.debug("Guessed excitation is %s, based on emission %s",
                          current_exc, current_em)

        self.excitation = model.VAEnumerated(current_exc, choices=exc_choices,
                                             unit="m")
        self.excitation.subscribe(self.onExcitation)

        # The wavelength band on the out path (set when emission changes)
        self.emission = model.VAEnumerated(current_em, choices=set(em_choices.values()),
                                           unit="m")
        self.emission.subscribe(self.onEmission)

        # colouration of the image
        self.tint.value = conversion.wave2rgb(center_em)
Esempio n. 13
0
    def __init__(self, name, detector, dataflow, emitter, em_filter, **kwargs):
        """
        name (string): user-friendly name of this stream
        detector (Detector): the detector which has the dataflow
        dataflow (Dataflow): the dataflow from which to get the data
        emitter (Light): the HwComponent to modify the light excitation
        em_filter (Filter or None): the HwComponent to modify the emission light
          filtering. If None, it will assume it's fixed and indicated on the
          MD_OUT_WL of the detector.
        """
        if "acq_type" not in kwargs:
            kwargs["acq_type"] = model.MD_AT_FLUO
        super(FluoStream, self).__init__(name, detector, dataflow, emitter, **kwargs)
        self._em_filter = em_filter

        # Emission and excitation are based on the hardware capacities.
        # For excitation, contrary to the hardware, only one band at a time can
        # be selected. The difficulty comes to pick the default value. We try
        # to use the current hardware value, but if the light is off there is no
        # default value. In that case, we pick the emission value that matches
        # best the excitation value.

        if em_filter:
            em_choices = em_filter.axes["band"].choices.copy()
            # convert any list into tuple, as lists cannot be put in a set
            for k, v in em_choices.items():
                em_choices[k] = conversion.ensure_tuple(v)

            # invert the dict, to directly convert the emission to the position value
            self._emission_to_idx = {v: k for k, v in em_choices.items()}

            cur_pos = em_filter.position.value["band"]
            current_em = em_choices[cur_pos]
        else:
            # TODO: is that a good idea? On a system with multiple detectors
            # (eg, confocal with several photo-detectors), should we just have a
            # filter per detector, instead of having this "shortcut"?
            try:
                current_em = detector.getMetadata()[model.MD_OUT_WL]
            except KeyError:
                raise ValueError("No em_filter passed, and detector has not MD_OUT_WL")
            current_em = conversion.ensure_tuple(current_em)
            em_choices = {None: current_em}
            # No ._emission_to_idx

        center_em = fluo.get_one_center(current_em)

        exc_choices = set(emitter.spectra.value)
        current_exc = self._get_current_excitation()
        if current_exc is None:
            current_exc = fluo.get_one_band_ex(exc_choices, current_em)
            logging.debug("Guessed excitation is %s, based on emission %s",
                          current_exc, current_em)

        self.excitation = model.VAEnumerated(current_exc, choices=exc_choices,
                                             unit="m")
        self.excitation.subscribe(self.onExcitation)

        # The wavelength band on the out path (set when emission changes)
        self.emission = model.VAEnumerated(current_em, choices=set(em_choices.values()),
                                           unit="m")
        self.emission.subscribe(self.onEmission)

        # colouration of the image
        self.tint.value = conversion.wave2rgb(center_em)