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)
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)