Skip to content

Commit f51ac07

Browse files
committed
Complex FFT with phase input
1 parent 34bf46f commit f51ac07

File tree

1 file changed

+65
-16
lines changed
  • orangecontrib/spectroscopy/widgets

1 file changed

+65
-16
lines changed

orangecontrib/spectroscopy/widgets/owfft.py

Lines changed: 65 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ class Outputs:
6868
out_limit1 = settings.Setting(400)
6969
out_limit2 = settings.Setting(4000)
7070
autocommit = settings.Setting(False)
71+
use_phaseinput_for_complexfft = settings.Setting(False)
72+
asym_apod = settings.Setting(False)
7173

7274
sweep_opts = ("Single",
7375
"Forward-Backward",
@@ -95,6 +97,7 @@ class Outputs:
9597
class Warning(OWWidget.Warning):
9698
# This is not actuully called anywhere at the moment
9799
phase_res_limit_low = Msg("Phase resolution limit too low")
100+
complex_data_phase_zero = Msg("Phase data is not connected, thus it is considered zero.")
98101

99102
class Error(OWWidget.Error):
100103
fft_error = Msg("FFT error:\n{}")
@@ -204,6 +207,12 @@ def __init__(self):
204207
self.optionsBox = gui.widgetBox(None, "FFT Options")
205208
layout.addWidget(self.optionsBox, 0, 1, 3, 1)
206209

210+
cb0 = gui.checkBox(
211+
self.optionsBox, self, "use_phaseinput_for_complexfft",
212+
label="Complex FFT with phase input",
213+
callback=self.complex_fft_changed
214+
)
215+
207216
box = gui.comboBox(
208217
self.optionsBox, self, "apod_func",
209218
label="Apodization function:",
@@ -350,10 +359,14 @@ def peak_search_changed(self):
350359
self.controls.zpd2.setDisabled(self.peak_search_enable or self.sweeps == 0)
351360
self.commit.deferred()
352361

362+
def complex_fft_changed(self):
363+
self.configui_for_polar_FFT_inputphase()
364+
self.commit.deferred()
365+
353366
@gui.deferred
354367
def commit(self):
355368
if self.data is not None:
356-
if self.use_polar_FFT:
369+
if self.use_polar_FFT or self.use_phaseinput_for_complexfft:
357370
self.calculate_polar_FFT()
358371
else:
359372
self.calculateFFT()
@@ -496,21 +509,30 @@ def calculateFFT(self):
496509
self.Outputs.spectra.send(self.spectra_table)
497510
self.Outputs.phases.send(self.phases_table)
498511

512+
499513
def calculate_polar_FFT(self):
500-
# polar channel data comes in alternating channel pairs
501-
# of amplitude and phase data for the same channel for each run
502-
amplitude_in = self.data.X[::2]
503-
phases_in = self.data.X[1::2]
514+
515+
# Reset info, error and warning dialogs
516+
self.Error.clear()
517+
self.Warning.clear()
518+
519+
if self.use_phaseinput_for_complexfft:
520+
amplitude_in = self.data.X
521+
phases_in = self.stored_phase.X if self.stored_phase is not None else None
522+
else:
523+
amplitude_in = self.data.X[::2]
524+
phases_in = self.data.X[1::2]
525+
526+
if phases_in is None:
527+
phases_in = 0
528+
self.Warning.complex_data_phase_zero()
529+
504530
ifg_data = amplitude_in * np.exp(phases_in * 1j)
505531

506532
wavenumbers = None
507533
spectra = []
508534
phases = []
509535

510-
# Reset info, error and warning dialogs
511-
self.Error.clear()
512-
self.Warning.clear()
513-
514536
fft_single = irfft.ComplexFFT(
515537
dx=self.dx,
516538
apod_func=self.apod_func,
@@ -535,12 +557,21 @@ def calculate_polar_FFT(self):
535557
[ContinuousVariable.make(f"{w}") for w in wavenumbers],
536558
metas=self.data.domain.metas,
537559
)
538-
self.spectra_table = Table.from_numpy(
539-
wavenumbers_domain, X=spectra, metas=self.data.metas[::2]
540-
)
541-
phases_table = Table.from_numpy(
542-
wavenumbers_domain, X=phases, metas=self.data.metas[1::2]
543-
)
560+
561+
if self.use_phaseinput_for_complexfft:
562+
self.spectra_table = Table.from_numpy(
563+
wavenumbers_domain, X=spectra, metas=self.data.metas
564+
)
565+
phases_table = Table.from_numpy(
566+
wavenumbers_domain, X=phases, metas=self.data.metas
567+
)
568+
else:
569+
self.spectra_table = Table.from_numpy(
570+
wavenumbers_domain, X=spectra, metas=self.data.metas[::2]
571+
)
572+
phases_table = Table.from_numpy(
573+
wavenumbers_domain, X=phases, metas=self.data.metas[1::2]
574+
)
544575

545576
self.Outputs.spectra.send(self.spectra_table)
546577
self.Outputs.phases.send(phases_table)
@@ -667,6 +698,22 @@ def limit_range(self, wavenumbers, spectra):
667698
spectra = spectra[:, limits[0]:limits[1]]
668699

669700
return wavenumbers, spectra
701+
702+
def configui_for_polar_FFT_inputphase(self):
703+
"""
704+
Configure the GUI for polar FFT with phase from strored_phase input
705+
"""
706+
if self.use_phaseinput_for_complexfft:
707+
self.dx_HeNe = False
708+
self.dx_edit.setDisabled(False)
709+
self.dx_HeNe_cb.setChecked(False)
710+
self.controls.phase_corr.setDisabled(True)
711+
self.controls.phase_res_limit.setDisabled(True)
712+
self.controls.phase_resolution.setDisabled(True)
713+
else:
714+
self.controls.phase_corr.setDisabled(False)
715+
self.controls.phase_res_limit.setDisabled(False)
716+
self.controls.phase_resolution.setDisabled(False)
670717

671718

672719
def load_test_gsf() -> Orange.data.Table:
@@ -682,4 +729,6 @@ def load_test_gsf() -> Orange.data.Table:
682729
if __name__ == "__main__": # pragma: no cover
683730
# pylint: disable=ungrouped-imports
684731
from Orange.widgets.utils.widgetpreview import WidgetPreview
685-
WidgetPreview(OWFFT).run(load_test_gsf())
732+
data = Orange.data.Table("20250412-TGQ1-O2A-ifg-lowdrift.xyz")
733+
phase = Orange.data.Table("20250412-TGQ1-O2P-ifg-lowdrift.xyz")
734+
WidgetPreview(OWFFT).run(set_data=data,set_stored_phase=phase)

0 commit comments

Comments
 (0)