Ejemplo n.º 1
0
    def __init__(self, name, image, *args, **kwargs):
        """
        name (string)
        image (model.DataArray(Shadow) of shape (CYX), (C11YX), (CTYX), (CT1YX), (1T1YX)).
        The metadata MD_WL_POLYNOMIAL or MD_WL_LIST should be included in order to
        associate the C to a wavelength.
        The metadata MD_TIME_LIST should be included to associate the T to a timestamp

        .background is a DataArray of shape (CT111), where C & T have the same length as in the data.
        .efficiencyCompensation is always DataArray of shape C1111.

        """
        # Spectrum stream has in addition to normal stream:
        #  * information about the current bandwidth displayed (avg. spectrum)
        #  * coordinates of 1st point (1-point, line)
        #  * coordinates of 2nd point (line)

        # TODO: need to handle DAS properly, in case it's tiled (in XY), to avoid
        # loading too much data in memory.
        # Ensure the data is a DataArray, as we don't handle (yet) DAS
        if isinstance(image, model.DataArrayShadow):
            image = image.getData()

        if len(image.shape) == 3:
            # force 5D for CYX
            image = image[:, numpy.newaxis, numpy.newaxis, :, :]
        elif len(image.shape) == 4:
            # force 5D for CTYX
            image = image[:, :, numpy.newaxis, :, :]
        elif len(image.shape) != 5 or image.shape[2] != 1:
            logging.error("Cannot handle data of shape %s", image.shape)
            raise NotImplementedError(
                "StaticSpectrumStream needs 3D or 4D data")

        # This is for "average spectrum" projection
        # cached list of wavelength for each pixel pos
        self._wl_px_values, unit_bw = spectrum.get_spectrum_range(image)
        min_bw, max_bw = self._wl_px_values[0], self._wl_px_values[-1]
        cwl = (max_bw + min_bw) / 2
        width = (max_bw - min_bw) / 12

        # The selected wavelength for a temporal spectrum display
        self.selected_wavelength = model.FloatContinuous(
            self._wl_px_values[0],
            range=(min_bw, max_bw),
            unit=unit_bw,
            setter=self._setWavelength)

        # Is there time data?
        if image.shape[1] > 1:
            # cached list of timestamps for each position in the time dimension
            self._tl_px_values, unit_t = spectrum.get_time_range(image)
            min_t, max_t = self._tl_px_values[0], self._tl_px_values[-1]

            # Allow the select the time as any value within the range, and the
            # setter will automatically "snap" it to the closest existing timestamp
            self.selected_time = model.FloatContinuous(self._tl_px_values[0],
                                                       range=(min_t, max_t),
                                                       unit=unit_t,
                                                       setter=self._setTime)

        # This attribute is used to keep track of any selected pixel within the
        # data for the display of a spectrum
        self.selected_pixel = model.TupleVA((None, None))  # int, int

        # first point, second point in pixels. It must be 2 elements long.
        self.selected_line = model.ListVA([(None, None), (None, None)],
                                          setter=self._setLine)

        # The thickness of a point or a line (shared).
        # A point of width W leads to the average value between all the pixels
        # which are within W/2 from the center of the point.
        # A line of width W leads to a 1D spectrum taking into account all the
        # pixels which fit on an orthogonal line to the selected line at a
        # distance <= W/2.
        self.selectionWidth = model.IntContinuous(1, [1, 50], unit="px")
        self.selectionWidth.subscribe(self._onSelectionWidth)

        # Peak method index, None if spectrum peak fitting curve is not displayed
        self.peak_method = model.VAEnumerated("gaussian",
                                              {"gaussian", "lorentzian", None})

        # TODO: allow to pass the calibration data as argument to avoid
        # recomputing the data just after init?
        # Spectrum efficiency compensation data: None or a DataArray (cf acq.calibration)
        self.efficiencyCompensation = model.VigilantAttribute(
            None, setter=self._setEffComp)
        self.efficiencyCompensation.subscribe(self._onCalib)

        # Is there spectrum data?
        if image.shape[0] > 1:
            # low/high values of the spectrum displayed
            self.spectrumBandwidth = model.TupleContinuous(
                (cwl - width, cwl + width),
                range=((min_bw, min_bw), (max_bw, max_bw)),
                unit=unit_bw,
                cls=(int, long, float))
            self.spectrumBandwidth.subscribe(self.onSpectrumBandwidth)

            # Whether the (per bandwidth) display should be split intro 3 sub-bands
            # which are applied to RGB
            self.fitToRGB = model.BooleanVA(False)
            self.fitToRGB.subscribe(self.onFitToRGB)

        # the raw data after calibration
        self.calibrated = model.VigilantAttribute(image)

        if "acq_type" not in kwargs:
            if image.shape[0] > 1 and image.shape[1] > 1:
                kwargs["acq_type"] = model.MD_AT_TEMPSPECTRUM
            elif image.shape[0] > 1:
                kwargs["acq_type"] = model.MD_AT_SPECTRUM
            elif image.shape[1] > 1:
                kwargs["acq_type"] = model.MD_AT_TEMPORAL
            else:
                logging.warning(
                    "SpectrumStream data has no spectrum or time dimension, shape = %s",
                    image.shape)

        super(StaticSpectrumStream, self).__init__(name, [image], *args,
                                                   **kwargs)

        # Automatically select point/line if data is small (can only be done
        # after .raw is set)
        if image.shape[-2:] == (1,
                                1):  # Only one point => select it immediately
            self.selected_pixel.value = (0, 0)
        elif image.shape[
                -2] == 1:  # Horizontal line => select line immediately
            self.selected_line.value = [(0, 0), (image.shape[-1] - 1, 0)]
        elif image.shape[-1] == 1:  # Vertical line => select line immediately
            self.selected_line.value = [(0, 0), (0, image.shape[-2] - 1)]
Ejemplo n.º 2
0
    def __init__(self, name, image, *args, **kwargs):
        """
        name (string)
        image (model.DataArray(Shadow) of shape (CYX), (C11YX), (CTYX), (CT1YX), (1T1YX)).
        The metadata MD_WL_POLYNOMIAL or MD_WL_LIST should be included in order to
        associate the C to a wavelength.
        The metadata MD_TIME_LIST should be included to associate the T to a timestamp

        .background is a DataArray of shape (CT111), where C & T have the same length as in the data.
        .efficiencyCompensation is always DataArray of shape C1111.

        """
        # Spectrum stream has in addition to normal stream:
        #  * information about the current bandwidth displayed (avg. spectrum)
        #  * coordinates of 1st point (1-point, line)
        #  * coordinates of 2nd point (line)

        # TODO: need to handle DAS properly, in case it's tiled (in XY), to avoid
        # loading too much data in memory.
        # Ensure the data is a DataArray, as we don't handle (yet) DAS
        if isinstance(image, model.DataArrayShadow):
            image = image.getData()

        if len(image.shape) == 3:
            # force 5D for CYX
            image = image[:, numpy.newaxis, numpy.newaxis, :, :]
        elif len(image.shape) == 4:
            # force 5D for CTYX
            image = image[:, :, numpy.newaxis, :, :]
        elif len(image.shape) != 5 or image.shape[2] != 1:
            logging.error("Cannot handle data of shape %s", image.shape)
            raise NotImplementedError("StaticSpectrumStream needs 3D or 4D data")

        # This is for "average spectrum" projection
        # cached list of wavelength for each pixel pos
        self._wl_px_values, unit_bw = spectrum.get_spectrum_range(image)
        min_bw, max_bw = self._wl_px_values[0], self._wl_px_values[-1]
        cwl = (max_bw + min_bw) / 2
        width = (max_bw - min_bw) / 12

        # The selected wavelength for a temporal spectrum display
        self.selected_wavelength = model.FloatContinuous(self._wl_px_values[0],
                                                   range=(min_bw, max_bw),
                                                   unit=unit_bw,
                                                   setter=self._setWavelength)

        # Is there time data?
        if image.shape[1] > 1:
            # cached list of timestamps for each position in the time dimension
            self._tl_px_values, unit_t = spectrum.get_time_range(image)
            min_t, max_t = self._tl_px_values[0], self._tl_px_values[-1]

            # Allow the select the time as any value within the range, and the
            # setter will automatically "snap" it to the closest existing timestamp
            self.selected_time = model.FloatContinuous(self._tl_px_values[0],
                                                   range=(min_t, max_t),
                                                   unit=unit_t,
                                                   setter=self._setTime)

        # This attribute is used to keep track of any selected pixel within the
        # data for the display of a spectrum
        self.selected_pixel = model.TupleVA((None, None))  # int, int

        # first point, second point in pixels. It must be 2 elements long.
        self.selected_line = model.ListVA([(None, None), (None, None)], setter=self._setLine)

        # The thickness of a point or a line (shared).
        # A point of width W leads to the average value between all the pixels
        # which are within W/2 from the center of the point.
        # A line of width W leads to a 1D spectrum taking into account all the
        # pixels which fit on an orthogonal line to the selected line at a
        # distance <= W/2.
        self.selectionWidth = model.IntContinuous(1, [1, 50], unit="px")
        self.selectionWidth.subscribe(self._onSelectionWidth)

        # Peak method index, None if spectrum peak fitting curve is not displayed
        self.peak_method = model.VAEnumerated("gaussian", {"gaussian", "lorentzian", None})

        # TODO: allow to pass the calibration data as argument to avoid
        # recomputing the data just after init?
        # Spectrum efficiency compensation data: None or a DataArray (cf acq.calibration)
        self.efficiencyCompensation = model.VigilantAttribute(None, setter=self._setEffComp)
        self.efficiencyCompensation.subscribe(self._onCalib)

        # Is there spectrum data?
        if image.shape[0] > 1:
            # low/high values of the spectrum displayed
            self.spectrumBandwidth = model.TupleContinuous(
                                        (cwl - width, cwl + width),
                                        range=((min_bw, min_bw), (max_bw, max_bw)),
                                        unit=unit_bw,
                                        cls=(int, long, float))
            self.spectrumBandwidth.subscribe(self.onSpectrumBandwidth)

            # Whether the (per bandwidth) display should be split intro 3 sub-bands
            # which are applied to RGB
            self.fitToRGB = model.BooleanVA(False)
            self.fitToRGB.subscribe(self.onFitToRGB)

        # the raw data after calibration
        self.calibrated = model.VigilantAttribute(image)

        if "acq_type" not in kwargs:
            if image.shape[0] > 1 and image.shape[1] > 1:
                kwargs["acq_type"] = model.MD_AT_TEMPSPECTRUM
            elif image.shape[0] > 1:
                kwargs["acq_type"] = model.MD_AT_SPECTRUM
            elif image.shape[1] > 1:
                kwargs["acq_type"] = model.MD_AT_TEMPORAL
            else:
                logging.warning("SpectrumStream data has no spectrum or time dimension, shape = %s",
                                image.shape)

        super(StaticSpectrumStream, self).__init__(name, [image], *args, **kwargs)

        # Automatically select point/line if data is small (can only be done
        # after .raw is set)
        if image.shape[-2:] == (1, 1):  # Only one point => select it immediately
            self.selected_pixel.value = (0, 0)
        elif image.shape[-2] == 1:  # Horizontal line => select line immediately
            self.selected_line.value = [(0, 0), (image.shape[-1] - 1, 0)]
        elif image.shape[-1] == 1:  # Vertical line => select line immediately
            self.selected_line.value = [(0, 0), (0, image.shape[-2] - 1)]
Ejemplo n.º 3
0
def export(filename, data):
    '''
    Write a CSV file:
        - If the given data is AR data then just dump the phi/data array
        - If the given data is spectrum data write it as series of wavelength/intensity
    filename (unicode): filename of the file to create (including path).
    data (model.DataArray): the data to export.
       Metadata is taken directly from the DA object.
    raises:
        ValueError in case the spectrum does not contain wavelength metadata.
    '''
    if data.metadata.get(model.MD_ACQ_TYPE, None) == model.MD_AT_SPECTRUM:
        dims = data.metadata.get(model.MD_DIMS, "CTZYX"[-data.ndim:])
        if dims == "C" and data.ndim == 1:
            spectrum_range, unit = spectrum.get_spectrum_range(data)
            if unit == "m":
                spectrum_range = [s * 1e9 for s in spectrum_range]
                unit = "nm"

            logging.debug("Exporting spectrum data to CSV")

            if unit == "nm":
                # turn range to nm
                spectrum_tuples = [(s, d)
                                   for s, d in zip(spectrum_range, data)]
                headers = ['# wavelength (nm)', 'intensity']
            else:
                logging.info(
                    "Exporting spectrum without wavelength information")
                spectrum_tuples = data.reshape(data.shape[0], 1)
                headers = ['# intensity']

            with open(filename, 'w') as fd:
                csv_writer = csv.writer(fd)
                csv_writer.writerow(headers)
                csv_writer.writerows(spectrum_tuples)

        elif dims == "T" and data.ndim == 1:
            time_range, unit = spectrum.get_time_range(data)
            if unit == "s":
                time_range = [t * 1e12 for t in time_range]
                unit = "ps"
            logging.debug("Exporting chronogram data to CSV")

            if unit == "ps":
                # turn range to nm
                time_tuples = [(s, d) for s, d in zip(time_range, data)]
                headers = ['# Time (ps)', 'intensity']
            else:
                logging.info(
                    "Exporting chronogram without time list information")
                time_tuples = data.reshape(data.shape[0], 1)
                headers = ['# intensity']

            with open(filename, 'w') as fd:
                csv_writer = csv.writer(fd)
                csv_writer.writerow(headers)
                csv_writer.writerows(time_tuples)

        elif data.ndim == 2 and dims == "XC":
            logging.debug("Exporting spectrum-line data to CSV")

            spectrum_range, unit = spectrum.get_spectrum_range(data)
            if unit == "m":
                spectrum_range = [s * 1e9 for s in spectrum_range]
                unit = "nm"

            # attach distance as first row
            line_length = data.shape[1] * data.metadata[model.MD_PIXEL_SIZE][1]
            distance_lin = numpy.linspace(0, line_length, data.shape[0])
            distance_lin.shape = (distance_lin.shape[0], 1)
            data = numpy.append(distance_lin, data, axis=1)

            # Data should be in the form of (X, C+1), with the first row and column the
            # distance_from_origin\wavelength
            with open(filename, 'w') as fd:
                csv_writer = csv.writer(fd)
                # Set the 'header' in the 0,0 element
                first_row = [
                    'distance_from_origin(m)\\wavelength(' + unit + ')'
                ] + spectrum_range
                csv_writer.writerow(first_row)
                # dump the array
                csv_writer.writerows(data)
        else:
            raise ValueError("Unknown type of data to be exported as CSV")

    elif data.metadata.get(model.MD_ACQ_TYPE,
                           None) == model.MD_AT_TEMPSPECTRUM:
        spectrum_range, unit_c = spectrum.get_spectrum_range(data)
        if unit_c == "m":
            spectrum_range = [s * 1e9 for s in spectrum_range]
            unit_c = "nm"
        time_range, unit_t = spectrum.get_time_range(data)
        if unit_t == "s":
            time_range = [t * 1e12 for t in time_range]
            unit_t = "ps"

        headers = ["time(" + unit_t + ")\\wavelength(" + unit_c + ")"
                   ] + spectrum_range
        rows = [(t, ) + tuple(d) for t, d in zip(time_range, data)]

        with open(filename, 'w') as fd:
            csv_writer = csv.writer(fd)
            csv_writer.writerow(headers)
            csv_writer.writerows(rows)

    elif data.metadata.get(model.MD_ACQ_TYPE, None) == model.MD_AT_AR:
        logging.debug("Exporting AR data to CSV")
        # Data should be in the form of (Y+1, X+1), with the first row and column the angles
        with open(filename, 'w') as fd:
            csv_writer = csv.writer(fd)

            # TODO: put theta/phi angles in metadata? Read back from MD theta/phi and then add as additional line/column
            # add the phi and theta values as an extra line/column in order to be displayed in the csv-file
            # attach theta as first column
            theta_lin = numpy.linspace(0, math.pi / 2, data.shape[0])
            data = numpy.append(theta_lin.reshape(theta_lin.shape[0], 1),
                                data,
                                axis=1)
            # attach phi as first row
            phi_lin = numpy.linspace(0, 2 * math.pi, data.shape[1] - 1)
            phi_lin = numpy.append([[0]],
                                   phi_lin.reshape(1, phi_lin.shape[0]),
                                   axis=1)
            data = numpy.append(phi_lin, data, axis=0)

            # Set the 'header' in the 0,0 element
            first_row = ['theta\\phi[rad]'] + [d for d in data[0, 1:]]
            csv_writer.writerow(first_row)
            # dump the array
            csv_writer.writerows(data[1:, :])

    else:
        raise ValueError(
            "Unknown acquisition type of data to be exported as CSV")
Ejemplo n.º 4
0
Archivo: csv.py Proyecto: delmic/odemis
def export(filename, data):
    '''
    Write a CSV file:
        - If the given data is AR data then just dump the phi/data array
        - If the given data is spectrum data write it as series of wavelength/intensity
    filename (unicode): filename of the file to create (including path).
    data (model.DataArray): the data to export.
       Metadata is taken directly from the DA object.
    raises:
        ValueError in case the spectrum does not contain wavelength metadata.
    '''
    if data.metadata.get(model.MD_ACQ_TYPE, None) == model.MD_AT_SPECTRUM:
        dims = data.metadata.get(model.MD_DIMS, "CTZYX"[-data.ndim:])
        if dims == "C" and data.ndim == 1:
            spectrum_range, unit = spectrum.get_spectrum_range(data)
            if unit == "m":
                spectrum_range = [s * 1e9 for s in spectrum_range]
                unit = "nm"

            logging.debug("Exporting spectrum data to CSV")

            if unit == "nm":
                # turn range to nm
                spectrum_tuples = [(s, d) for s, d in zip(spectrum_range, data)]
                headers = ['# wavelength (nm)', 'intensity']
            else:
                logging.info("Exporting spectrum without wavelength information")
                spectrum_tuples = data.reshape(data.shape[0], 1)
                headers = ['# intensity']

            with open(filename, 'w') as fd:
                csv_writer = csv.writer(fd)
                csv_writer.writerow(headers)
                csv_writer.writerows(spectrum_tuples)

        elif dims == "T" and data.ndim == 1:
            time_range, unit = spectrum.get_time_range(data)
            if unit == "s":
                time_range = [t * 1e12 for t in time_range]
                unit = "ps"
            logging.debug("Exporting chronogram data to CSV")

            if unit == "ps":
                # turn range to nm
                time_tuples = [(s, d) for s, d in zip(time_range, data)]
                headers = ['# Time (ps)', 'intensity']
            else:
                logging.info("Exporting chronogram without time list information")
                time_tuples = data.reshape(data.shape[0], 1)
                headers = ['# intensity']

            with open(filename, 'w') as fd:
                csv_writer = csv.writer(fd)
                csv_writer.writerow(headers)
                csv_writer.writerows(time_tuples)

        elif data.ndim == 2 and dims == "XC":
            logging.debug("Exporting spectrum-line data to CSV")

            spectrum_range, unit = spectrum.get_spectrum_range(data)
            if unit == "m":
                spectrum_range = [s * 1e9 for s in spectrum_range]
                unit = "nm"

            # attach distance as first row
            line_length = data.shape[1] * data.metadata[model.MD_PIXEL_SIZE][1]
            distance_lin = numpy.linspace(0, line_length, data.shape[0])
            distance_lin.shape = (distance_lin.shape[0], 1)
            data = numpy.append(distance_lin, data, axis=1)

            # Data should be in the form of (X, C+1), with the first row and column the
            # distance_from_origin\wavelength
            with open(filename, 'w') as fd:
                csv_writer = csv.writer(fd)
                # Set the 'header' in the 0,0 element
                first_row = ['distance_from_origin(m)\\wavelength(' + unit + ')'] + spectrum_range
                csv_writer.writerow(first_row)
                # dump the array
                csv_writer.writerows(data)
        else:
            raise ValueError("Unknown type of data to be exported as CSV")
        
    elif data.metadata.get(model.MD_ACQ_TYPE, None) == model.MD_AT_TEMPSPECTRUM:
        spectrum_range, unit_c = spectrum.get_spectrum_range(data)
        if unit_c == "m":
            spectrum_range = [s * 1e9 for s in spectrum_range]
            unit_c = "nm"
        time_range, unit_t = spectrum.get_time_range(data)
        if unit_t == "s":
            time_range = [t * 1e12 for t in time_range]
            unit_t = "ps"

        headers = ["time(" + unit_t + ")\\wavelength(" + unit_c + ")"] + spectrum_range
        rows = [(t,) + tuple(d) for t, d in zip(time_range, data)]

        with open(filename, 'w') as fd:
            csv_writer = csv.writer(fd)
            csv_writer.writerow(headers)
            csv_writer.writerows(rows)

    elif data.metadata.get(model.MD_ACQ_TYPE, None) == model.MD_AT_AR:
        logging.debug("Exporting AR data to CSV")
        # Data should be in the form of (Y+1, X+1), with the first row and column the angles
        with open(filename, 'w') as fd:
            csv_writer = csv.writer(fd)

            # TODO: put theta/phi angles in metadata? Read back from MD theta/phi and then add as additional line/column
            # add the phi and theta values as an extra line/column in order to be displayed in the csv-file
            # attach theta as first column
            theta_lin = numpy.linspace(0, math.pi / 2, data.shape[0])
            data = numpy.append(theta_lin.reshape(theta_lin.shape[0], 1), data, axis=1)
            # attach phi as first row
            phi_lin = numpy.linspace(0, 2 * math.pi, data.shape[1]-1)
            phi_lin = numpy.append([[0]], phi_lin.reshape(1, phi_lin.shape[0]), axis=1)
            data = numpy.append(phi_lin, data, axis=0)

            # Set the 'header' in the 0,0 element
            first_row = ['theta\\phi[rad]'] + [d for d in data[0, 1:]]
            csv_writer.writerow(first_row)
            # dump the array
            csv_writer.writerows(data[1:, :])
            
    else:
        raise ValueError("Unknown acquisition type of data to be exported as CSV")