コード例 #1
0
 def test_build_spec_table_not_copy(self):
     """build_spec_table should not copy tables if not neccessary"""
     xs = np.arange(3)
     # float32 table will force a copy because Orange X is float64
     X = np.ones([4, 3], dtype=np.float32)
     data = build_spec_table(xs, X)
     self.assertFalse(np.may_share_memory(data.X, X))
     # float64 will not force a copy
     X = np.ones([4, 3], dtype=np.float64)
     data = build_spec_table(xs, X)
     self.assertTrue(np.may_share_memory(data.X, X))
コード例 #2
0
 def test_build_spec_table_not_copy(self):
     """build_spec_table should not copy tables if not neccessary"""
     xs = np.arange(3)
     # float32 table will force a copy because Orange X is float64
     X = np.ones([4, 3], dtype=np.float32)
     data = build_spec_table(xs, X)
     self.assertFalse(np.may_share_memory(data.X, X))
     # float64 will not force a copy
     X = np.ones([4, 3], dtype=np.float64)
     data = build_spec_table(xs, X)
     self.assertTrue(np.may_share_memory(data.X, X))
コード例 #3
0
def process_stack(data,
                  xat,
                  yat,
                  upsample_factor=100,
                  use_sobel=False,
                  ref_frame_num=0):
    hypercube, lsx, lsy = get_hypercube(data, xat, yat)
    if bn.anynan(hypercube):
        raise NanInsideHypercube(True)

    calculate_shift = RegisterTranslation(upsample_factor=upsample_factor)
    filterfn = sobel if use_sobel else lambda x: x
    shifts, aligned_stack = alignstack(hypercube.T,
                                       shiftfn=calculate_shift,
                                       ref_frame_num=ref_frame_num,
                                       filterfn=filterfn)

    xmin, ymin = shifts[:, 0].min(), shifts[:, 1].min()
    xmax, ymax = shifts[:, 0].max(), shifts[:, 1].max()
    xmin, xmax = int(round(xmin)), int(round(xmax))
    ymin, ymax = int(round(ymin)), int(round(ymax))

    shape = hypercube.shape
    slicex = slice(max(xmax, 0), min(shape[1], shape[1] + xmin))
    slicey = slice(max(ymax, 0), min(shape[0], shape[0] + ymin))
    cropped = np.array(aligned_stack).T[slicey, slicex]

    # transform numpy array back to Orange.data.Table
    return shifts, build_spec_table(
        *_spectra_from_image(cropped, getx(data),
                             np.linspace(*lsx)[slicex],
                             np.linspace(*lsy)[slicey]))
コード例 #4
0
def process_stack(data, xat, yat, upsample_factor=100, use_sobel=False, ref_frame_num=0):
    hypercube, lsx, lsy = get_hypercube(data, xat, yat)

    calculate_shift = RegisterTranslation(upsample_factor=upsample_factor)
    filterfn = sobel if use_sobel else lambda x: x
    shifts, aligned_stack = alignstack(hypercube.T,
                                       shiftfn=calculate_shift,
                                       ref_frame_num=ref_frame_num,
                                       filterfn=filterfn)

    xmin, ymin = shifts[:, 0].min(), shifts[:, 1].min()
    xmax, ymax = shifts[:, 0].max(), shifts[:, 1].max()
    xmin, xmax = int(round(xmin)), int(round(xmax))
    ymin, ymax = int(round(ymin)), int(round(ymax))

    shape = hypercube.shape
    slicex = slice(max(xmax, 0), min(shape[1], shape[1]+xmin))
    slicey = slice(max(ymax, 0), min(shape[0], shape[0]+ymin))
    cropped = np.array(aligned_stack).T[slicey, slicex]

    # transform numpy array back to Orange.data.Table
    return shifts, build_spec_table(*_spectra_from_image(cropped,
                                                         getx(data),
                                                         np.linspace(*lsx)[slicex],
                                                         np.linspace(*lsy)[slicey]))
コード例 #5
0
def orange_table_from_3d(image3d):
    info = _spectra_from_image(image3d,
                               range(5),
                               range(image3d[:, :, 0].shape[1]),
                               range(image3d[:, :, 0].shape[0]))
    data = build_spec_table(*info)
    return data
コード例 #6
0
    def test_image_computation(self):
        spectra = [[[0, 0, 2, 0],
                    [0, 0, 1, 0]],
                   [[1, 2, 2, 0],
                    [0, 1, 1, 0]]]
        wns = [0, 1, 2, 3]
        x_locs = [0, 1]
        y_locs = [0, 1]
        data = build_spec_table(*_spectra_from_image(spectra, wns, x_locs, y_locs))

        def last_called_array(m):
            arrays = [a[0][0] for a in m.call_args_list
                      if a and a[0] and isinstance(a[0][0], np.ndarray)]
            return arrays[-1]

        wrap = self.widget.imageplot.img

        # integrals from zero; default
        self.send_signal("Data", data)
        with patch.object(wrap, 'setImage', wraps=wrap.setImage) as m:
            wait_for_image(self.widget)
            called = last_called_array(m)
            target = [[2, 1], [4.5, 2]]
            np.testing.assert_equal(called.squeeze(), target)

        # peak from zero
        self.widget.integration_method = \
            self.widget.integration_methods.index(IntegrateFeaturePeakSimple)
        self.widget._change_integral_type()
        with patch.object(wrap, 'setImage', wraps=wrap.setImage) as m:
            wait_for_image(self.widget)
            called = last_called_array(m)
            target = [[2, 1], [2, 1]]
            np.testing.assert_equal(called.squeeze(), target)

        # single wavenumber (feature)
        self.widget.controls.value_type.buttons[1].click()
        self.widget.attr_value = data.domain.attributes[1]
        self.widget.update_feature_value()
        with patch.object(wrap, 'setImage', wraps=wrap.setImage) as m:
            wait_for_image(self.widget)
            called = last_called_array(m)
            target = [[0, 0], [2, 1]]
            np.testing.assert_equal(called.squeeze(), target)

        # RGB
        self.widget.controls.value_type.buttons[2].click()
        self.widget.rgb_red_value = data.domain.attributes[0]
        self.widget.rgb_green_value = data.domain.attributes[1]
        self.widget.rgb_blue_value = data.domain.attributes[2]
        self.widget.update_rgb_value()
        with patch.object(wrap, 'setImage', wraps=wrap.setImage) as m:
            wait_for_image(self.widget)
            called = last_called_array(m)
            # first three wavenumbers (features) should be passed to setImage
            target = [data.X[0, :3], data.X[1, :3]], [data.X[2, :3], data.X[3, :3]]
            np.testing.assert_equal(called, target)
コード例 #7
0
def process_stack(data,
                  xat,
                  yat,
                  upsample_factor=100,
                  use_sobel=False,
                  ref_frame_num=0):
    ndom = Domain([xat, yat])
    datam = Table(ndom, data)
    coorx = datam.X[:, 0]
    coory = datam.X[:, 1]

    lsx = values_to_linspace(coorx)
    lsy = values_to_linspace(coory)
    lsz = data.X.shape[1]

    if lsx is None:
        raise InvalidAxisException("x")
    if lsy is None:
        raise InvalidAxisException("y")

    # set data
    hypercube = np.ones((lsy[2], lsx[2], lsz)) * np.nan

    xindex = index_values(coorx, lsx)
    yindex = index_values(coory, lsy)
    hypercube[yindex, xindex] = data.X

    if np.any(np.isnan(hypercube)):
        raise NanInsideHypercube(np.sum(np.isnan(hypercube)))

    calculate_shift = RegisterTranslation(upsample_factor=upsample_factor)
    filterfn = sobel if use_sobel else lambda x: x
    shifts, aligned_stack = alignstack(hypercube.T,
                                       shiftfn=calculate_shift,
                                       ref_frame_num=ref_frame_num,
                                       filterfn=filterfn)

    xmin, ymin = shifts[:, 0].min(), shifts[:, 1].min()
    xmax, ymax = shifts[:, 0].max(), shifts[:, 1].max()
    xmin, xmax = int(round(xmin)), int(round(xmax))
    ymin, ymax = int(round(ymin)), int(round(ymax))

    shape = hypercube.shape
    slicex = slice(max(xmax, 0), min(shape[1], shape[1] + xmin))
    slicey = slice(max(ymax, 0), min(shape[0], shape[0] + ymin))
    cropped = np.array(aligned_stack).T[slicey, slicex]

    # transform numpy array back to Orange.data.Table
    return shifts, build_spec_table(
        *_spectra_from_image(cropped, getx(data),
                             np.linspace(*lsx)[slicex],
                             np.linspace(*lsy)[slicey]))
コード例 #8
0
    def test_hypercube_roundtrip(self):
        d = self.mosaic
        xat = [v for v in d.domain.metas if v.name == "map_x"][0]
        yat = [v for v in d.domain.metas if v.name == "map_y"][0]
        hypercube, lsx, lsy = get_hypercube(d, xat, yat)

        features = getx(d)
        ndom = Orange.data.Domain([xat, yat])
        datam = Orange.data.Table(ndom, d)
        coorx = datam.X[:, 0]
        coory = datam.X[:, 1]
        coords = np.ones((lsx[2], lsy[2], 2))
        coords[index_values(coorx, lsx), index_values(coory, lsy)] = datam.X
        x_locs = coords[:, 0, 0]
        y_locs = coords[0, :, 1]

        features, spectra, data = _spectra_from_image(hypercube, features,
                                                      x_locs, y_locs)
        nd = build_spec_table(features, spectra, data)

        np.testing.assert_equal(d.X, nd.X)
        np.testing.assert_equal(d.Y, nd.Y)
        np.testing.assert_equal(d.metas, nd.metas)
        self.assertEqual(d.domain, nd.domain)
コード例 #9
0
    def calculateFFT(self):
        """
        Calculate FFT from input interferogram(s).
        This is a handler method for
          - bad data / data shape
          - splitting the array in the case of two interferogram sweeps per dataset.
          - multiple input interferograms

        Based on mertz module by Eric Peach, 2014
        """

        wavenumbers = None
        spectra = []
        phases = []

        zpd_fwd = []
        zpd_back = []

        # Reset info, error and warning dialogs
        self.Error.clear()
        self.Warning.clear()

        fft_single = irfft.IRFFT(
            dx=self.dx,
            apod_func=self.apod_func,
            zff=2**self.zff,
            phase_res=self.phase_resolution if self.phase_res_limit else None,
            phase_corr=self.phase_corr,
            peak_search=self.peak_search,
        )

        ifg_data = self.data.X
        stored_phase = self.stored_phase
        stored_zpd_fwd, stored_zpd_back = None, None
        # Only use first row stored phase for now
        if stored_phase is not None:
            stored_phase = stored_phase[0]
            try:
                stored_zpd_fwd = int(stored_phase["zpd_fwd"].value)
            except ValueError:
                stored_zpd_fwd = None
            try:
                stored_zpd_back = int(stored_phase["zpd_back"].value)
            except ValueError:
                stored_zpd_back = None
            stored_phase = stored_phase.x  # lowercase x for RowInstance
        # Use manual zpd value(s) if specified and enable batch processing
        elif not self.peak_search_enable:
            stored_zpd_fwd = self.zpd1
            stored_zpd_back = self.zpd2
            chunks = max(1, len(self.data) // CHUNK_SIZE)
            ifg_data = np.array_split(self.data.X, chunks, axis=0)
            fft_single = irfft.MultiIRFFT(
                dx=self.dx,
                apod_func=self.apod_func,
                zff=2**self.zff,
                phase_res=self.phase_resolution
                if self.phase_res_limit else None,
                phase_corr=self.phase_corr,
                peak_search=self.peak_search,
            )

        if self.reader == 'NeaReaderGSF':
            fft_single = irfft.ComplexFFT(
                dx=self.dx,
                apod_func=self.apod_func,
                zff=2**self.zff,
                phase_res=self.phase_resolution
                if self.phase_res_limit else None,
                phase_corr=self.phase_corr,
                peak_search=self.peak_search,
            )
            full_data = self.data.X[::2] * np.exp(self.data.X[1::2] * 1j)
            for row in full_data:
                spectrum_out, phase_out, wavenumbers = fft_single(
                    row, zpd=stored_zpd_fwd)
                spectra.append(spectrum_out)
                spectra.append(phase_out)
            spectra = np.vstack(spectra)

            if self.limit_output is True:
                wavenumbers, spectra = self.limit_range(wavenumbers, spectra)
            self.spectra_table = build_spec_table(wavenumbers,
                                                  spectra,
                                                  additional_table=self.data)
            self.Outputs.spectra.send(self.spectra_table)
            return

        for row in ifg_data:
            if self.sweeps in [2, 3]:
                # split double-sweep for forward/backward
                # forward: 2-2 = 0 , backward: 3-2 = 1
                try:
                    row = np.hsplit(row, 2)[self.sweeps - 2]
                except ValueError as e:
                    self.Error.ifg_split_error(e)
                    return

            if self.sweeps in [0, 2, 3]:
                try:
                    spectrum_out, phase_out, wavenumbers = fft_single(
                        row, zpd=stored_zpd_fwd, phase=stored_phase)
                    zpd_fwd.append(fft_single.zpd)
                except ValueError as e:
                    self.Error.fft_error(e)
                    return
            elif self.sweeps == 1:
                # Double sweep interferogram is split, solved independently and the
                # two results are averaged.
                try:
                    data = np.hsplit(row, 2)
                except ValueError as e:
                    self.Error.ifg_split_error(e)
                    return

                fwd = data[0]
                # Reverse backward sweep to match fwd sweep
                back = data[1][::-1]

                # Calculate spectrum for both forward and backward sweeps
                try:
                    spectrum_fwd, phase_fwd, wavenumbers = fft_single(
                        fwd, zpd=stored_zpd_fwd, phase=stored_phase)
                    zpd_fwd.append(fft_single.zpd)
                    spectrum_back, phase_back, wavenumbers = fft_single(
                        back, zpd=stored_zpd_back, phase=stored_phase)
                    zpd_back.append(fft_single.zpd)
                except ValueError as e:
                    self.Error.fft_error(e)
                    return

                # Calculate the average of the forward and backward sweeps
                spectrum_out = np.mean(np.array([spectrum_fwd, spectrum_back]),
                                       axis=0)
                phase_out = np.mean(np.array([phase_fwd, phase_back]), axis=0)
            else:
                return

            spectra.append(spectrum_out)
            phases.append(phase_out)

        spectra = np.vstack(spectra)
        phases = np.vstack(phases)

        self.phases_table = build_spec_table(wavenumbers,
                                             phases,
                                             additional_table=self.data)
        if not self.peak_search_enable:
            # All zpd values are equal by definition
            zpd_fwd = zpd_fwd[:1]
        self.phases_table = add_meta_to_table(
            self.phases_table, ContinuousVariable.make("zpd_fwd"), zpd_fwd)
        if zpd_back:
            if not self.peak_search_enable:
                zpd_back = zpd_back[:1]
            self.phases_table = add_meta_to_table(
                self.phases_table, ContinuousVariable.make("zpd_back"),
                zpd_back)

        if self.limit_output is True:
            wavenumbers, spectra = self.limit_range(wavenumbers, spectra)

        self.spectra_table = build_spec_table(wavenumbers,
                                              spectra,
                                              additional_table=self.data)
        self.Outputs.spectra.send(self.spectra_table)
        self.Outputs.phases.send(self.phases_table)
コード例 #10
0
    def calculateFFT(self):
        """
        Calculate FFT from input interferogram(s).
        This is a handler method for
          - bad data / data shape
          - splitting the array in the case of two interferogram sweeps per dataset.
          - multiple input interferograms

        Based on mertz module by Eric Peach, 2014
        """

        self.wavenumbers = None
        self.spectra = None
        self.phases = None

        # Reset info, error and warning dialogs
        self.error(1)  # FFT ValueError, usually wrong sweep number
        self.error(2)  # vsplit ValueError, odd number of data points
        self.warning(4)  # Phase resolution limit too low

        for row in self.data.X:
            # Check to see if interferogram is single or double sweep
            if self.sweeps == 0:
                try:
                    spectrum_out, phase_out, self.wavenumbers = self.fft_single(
                        row)
                except ValueError as e:
                    self.error(1, "FFT error: %s" % e)
                    return

            elif self.sweeps == 1:
                # Double sweep interferogram is split, solved independently and the
                # two results are averaged.
                try:
                    data = np.hsplit(row, 2)
                except ValueError as e:
                    self.error(2, "%s" % e)
                    return

                fwd = data[0]
                # Reverse backward sweep to match fwd sweep
                back = data[1][::-1]

                # Calculate spectrum for both forward and backward sweeps
                try:
                    spectrum_fwd, phase_fwd, self.wavenumbers = self.fft_single(
                        fwd)
                    spectrum_back, phase_back, self.wavenumbers = self.fft_single(
                        back)
                except ValueError as e:
                    self.error(1, "FFT error: %s" % e)
                    return

                # Calculate the average of the forward and backward sweeps
                spectrum_out = np.mean(np.array([spectrum_fwd, spectrum_back]),
                                       axis=0)
                phase_out = np.mean(np.array([phase_fwd, phase_back]), axis=0)

            else:
                return

            if self.spectra is not None:
                self.spectra = np.vstack((self.spectra, spectrum_out))
                self.phases = np.vstack((self.phases, phase_out))
            else:
                self.spectra = spectrum_out
                self.phases = phase_out

        if self.limit_output is True:
            limits = np.searchsorted(self.wavenumbers,
                                     [self.out_limit1, self.out_limit2])
            self.wavenumbers = self.wavenumbers[limits[0]:limits[1]]
            # Handle 1D array if necessary
            if self.spectra.ndim == 1:
                self.spectra = self.spectra[None, limits[0]:limits[1]]
                self.phases = self.phases[None, limits[0]:limits[1]]
            else:
                self.spectra = self.spectra[:, limits[0]:limits[1]]
                self.phases = self.phases[:, limits[0]:limits[1]]

        self.spectra_table = build_spec_table(self.wavenumbers, self.spectra)
        self.phases_table = build_spec_table(self.wavenumbers, self.phases)
        self.Outputs.spectra.send(self.spectra_table)
        self.Outputs.phases.send(self.phases_table)
コード例 #11
0
ファイル: owfft.py プロジェクト: take5v/orange-spectroscopy
    def calculateFFT(self):
        """
        Calculate FFT from input interferogram(s).
        This is a handler method for
          - bad data / data shape
          - splitting the array in the case of two interferogram sweeps per dataset.
          - multiple input interferograms

        Based on mertz module by Eric Peach, 2014
        """

        wavenumbers = None
        spectra = []
        phases = []

        zpd_fwd = []
        zpd_back = []

        # Reset info, error and warning dialogs
        self.Error.clear()
        self.Warning.clear()

        fft_single = irfft.IRFFT(dx=self.dx,
                                 apod_func=self.apod_func,
                                 zff=2**self.zff,
                                 phase_res=self.phase_resolution if self.phase_res_limit else None,
                                 phase_corr=self.phase_corr,
                                 peak_search=self.peak_search,
                                )

        stored_phase = self.stored_phase
        stored_zpd_fwd, stored_zpd_back = None, None
        # Only use first row stored phase for now
        if stored_phase is not None:
            stored_phase = stored_phase[0]
            try:
                stored_zpd_fwd = int(stored_phase["zpd_fwd"].value)
            except ValueError:
                stored_zpd_fwd = None
            try:
                stored_zpd_back = int(stored_phase["zpd_back"].value)
            except ValueError:
                stored_zpd_back = None
            stored_phase = stored_phase.x # lowercase x for RowInstance

        for row in self.data.X:
            if self.sweeps in [2, 3]:
                # split double-sweep for forward/backward
                # forward: 2-2 = 0 , backward: 3-2 = 1
                try:
                    row = np.hsplit(row, 2)[self.sweeps - 2]
                except ValueError as e:
                    self.Error.ifg_split_error(e)
                    return

            if self.sweeps in [0, 2, 3]:
                try:
                    spectrum_out, phase_out, wavenumbers = fft_single(
                        row, zpd=stored_zpd_fwd, phase=stored_phase)
                    zpd_fwd.append(fft_single.zpd)
                except ValueError as e:
                    self.Error.fft_error(e)
                    return
            elif self.sweeps == 1:
                # Double sweep interferogram is split, solved independently and the
                # two results are averaged.
                try:
                    data = np.hsplit(row, 2)
                except ValueError as e:
                    self.Error.ifg_split_error(e)
                    return

                fwd = data[0]
                # Reverse backward sweep to match fwd sweep
                back = data[1][::-1]

                # Calculate spectrum for both forward and backward sweeps
                try:
                    spectrum_fwd, phase_fwd, wavenumbers = fft_single(
                        fwd, zpd=stored_zpd_fwd, phase=stored_phase)
                    zpd_fwd.append(fft_single.zpd)
                    spectrum_back, phase_back, wavenumbers = fft_single(
                        back, zpd=stored_zpd_back, phase=stored_phase)
                    zpd_back.append(fft_single.zpd)
                except ValueError as e:
                    self.Error.fft_error(e)
                    return

                # Calculate the average of the forward and backward sweeps
                spectrum_out = np.mean(np.array([spectrum_fwd, spectrum_back]), axis=0)
                phase_out = np.mean(np.array([phase_fwd, phase_back]), axis=0)
            else:
                return

            spectra.append(spectrum_out)
            phases.append(phase_out)

        spectra = np.vstack(spectra)
        phases = np.vstack(phases)

        self.phases_table = build_spec_table(wavenumbers, phases,
                                             additional_table=self.data)
        self.phases_table = add_meta_to_table(self.phases_table,
                                              ContinuousVariable.make("zpd_fwd"),
                                              zpd_fwd)
        if zpd_back:
            self.phases_table = add_meta_to_table(self.phases_table,
                                                  ContinuousVariable.make("zpd_back"),
                                                  zpd_back)

        if self.limit_output is True:
            limits = np.searchsorted(wavenumbers,
                                     [self.out_limit1, self.out_limit2])
            wavenumbers = wavenumbers[limits[0]:limits[1]]
            # Handle 1D array if necessary
            if spectra.ndim == 1:
                spectra = spectra[None, limits[0]:limits[1]]
            else:
                spectra = spectra[:, limits[0]:limits[1]]

        self.spectra_table = build_spec_table(wavenumbers, spectra,
                                              additional_table=self.data)
        self.Outputs.spectra.send(self.spectra_table)
        self.Outputs.phases.send(self.phases_table)
コード例 #12
0
ファイル: owfft.py プロジェクト: borondics/orange-infrared
    def calculateFFT(self):
        """
        Calculate FFT from input interferogram(s).
        This is a handler method for
          - bad data / data shape
          - splitting the array in the case of two interferogram sweeps per dataset.
          - multiple input interferograms

        Based on mertz module by Eric Peach, 2014
        """

        self.wavenumbers = None
        self.spectra = None
        self.phases = None

        # Reset info, error and warning dialogs
        self.error(1)   # FFT ValueError, usually wrong sweep number
        self.error(2)   # vsplit ValueError, odd number of data points
        self.warning(4) # Phase resolution limit too low

        for row in self.data.X:
            # Check to see if interferogram is single or double sweep
            if self.sweeps == 0:
                try:
                    spectrum_out, phase_out, self.wavenumbers = self.fft_single(row)
                except ValueError as e:
                    self.error(1, "FFT error: %s" % e)
                    return

            elif self.sweeps == 1:
                # Double sweep interferogram is split, solved independently and the
                # two results are averaged.
                try:
                    data = np.hsplit(row, 2)
                except ValueError as e:
                    self.error(2, "%s" % e)
                    return

                fwd = data[0]
                # Reverse backward sweep to match fwd sweep
                back = data[1][::-1]

                # Calculate spectrum for both forward and backward sweeps
                try:
                    spectrum_fwd, phase_fwd, self.wavenumbers = self.fft_single(fwd)
                    spectrum_back, phase_back, self.wavenumbers = self.fft_single(back)
                except ValueError as e:
                    self.error(1, "FFT error: %s" % e)
                    return

                # Calculate the average of the forward and backward sweeps
                spectrum_out = np.mean( np.array([spectrum_fwd, spectrum_back]), axis=0)
                phase_out = np.mean(np.array([phase_fwd, phase_back]), axis=0)

            else:
                return

            if self.spectra is not None:
                self.spectra = np.vstack((self.spectra, spectrum_out))
                self.phases = np.vstack((self.phases, phase_out))
            else:
                self.spectra = spectrum_out
                self.phases = phase_out

        if self.limit_output is True:
            limits = np.searchsorted(self.wavenumbers,
                                     [self.out_limit1, self.out_limit2])
            self.wavenumbers = self.wavenumbers[limits[0]:limits[1]]
            # Handle 1D array if necessary
            if self.spectra.ndim == 1:
                self.spectra = self.spectra[None,limits[0]:limits[1]]
                self.phases = self.phases[None,limits[0]:limits[1]]
            else:
                self.spectra = self.spectra[:,limits[0]:limits[1]]
                self.phases = self.phases[:,limits[0]:limits[1]]

        self.spectra_table = build_spec_table(self.wavenumbers, self.spectra)
        self.phases_table = build_spec_table(self.wavenumbers, self.phases)
        self.Outputs.spectra.send(self.spectra_table)
        self.Outputs.phases.send(self.phases_table)