Ejemplo n.º 1
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)
Ejemplo n.º 2
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,
                                )

        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)