From 9c5d91918f065feb1fda22521a36ff29a0de32dc Mon Sep 17 00:00:00 2001 From: Dominik Demuth Date: Thu, 9 Nov 2023 17:50:29 +0100 Subject: [PATCH] added f-omega option to log-fourier transform; closes #134 --- src/gui_qt/_py/integratederive_dialog.py | 17 ++++-- src/gui_qt/main/management.py | 5 +- src/gui_qt/math/integrate_derive.py | 10 +++- src/nmreval/math/logfourier.py | 65 +++++++++++++++------ src/resources/_ui/integratederive_dialog.ui | 9 ++- 5 files changed, 78 insertions(+), 28 deletions(-) diff --git a/src/gui_qt/_py/integratederive_dialog.py b/src/gui_qt/_py/integratederive_dialog.py index 0ae75f4..f607cad 100644 --- a/src/gui_qt/_py/integratederive_dialog.py +++ b/src/gui_qt/_py/integratederive_dialog.py @@ -1,10 +1,11 @@ # -*- coding: utf-8 -*- -# Form implementation generated from reading ui file 'resources/_ui/integratederive_dialog.ui' +# Form implementation generated from reading ui file 'src/resources/_ui/integratederive_dialog.ui' # -# Created by: PyQt5 UI code generator 5.12.3 +# Created by: PyQt5 UI code generator 5.15.9 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets @@ -13,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets class Ui_Dialog(object): def setupUi(self, Dialog): Dialog.setObjectName("Dialog") - Dialog.resize(400, 308) + Dialog.resize(400, 375) self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) self.verticalLayout.setObjectName("verticalLayout") self.listWidget = QtWidgets.QListWidget(Dialog) @@ -49,6 +50,9 @@ class Ui_Dialog(object): self.log_checkbox = QtWidgets.QCheckBox(Dialog) self.log_checkbox.setObjectName("log_checkbox") self.verticalLayout.addWidget(self.log_checkbox) + self.freq_box = QtWidgets.QCheckBox(Dialog) + self.freq_box.setObjectName("freq_box") + self.verticalLayout.addWidget(self.freq_box) self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setContentsMargins(-1, 0, -1, -1) self.horizontalLayout_2.setSpacing(3) @@ -67,8 +71,8 @@ class Ui_Dialog(object): self.verticalLayout.addWidget(self.buttonBox) self.retranslateUi(Dialog) - self.buttonBox.accepted.connect(Dialog.accept) - self.buttonBox.rejected.connect(Dialog.reject) + self.buttonBox.accepted.connect(Dialog.accept) # type: ignore + self.buttonBox.rejected.connect(Dialog.reject) # type: ignore QtCore.QMetaObject.connectSlotsByName(Dialog) def retranslateUi(self, Dialog): @@ -80,4 +84,5 @@ class Ui_Dialog(object): self.ft_comboBox.setItemText(1, _translate("Dialog", "Imag")) self.ft_comboBox.setItemText(2, _translate("Dialog", "Complex")) self.log_checkbox.setText(_translate("Dialog", "use logarithmic x axis")) + self.freq_box.setText(_translate("Dialog", "return x axis as f, not omega")) self.newgraph_checkbox.setText(_translate("Dialog", "New graph")) diff --git a/src/gui_qt/main/management.py b/src/gui_qt/main/management.py index 07ee695..58128bc 100644 --- a/src/gui_qt/main/management.py +++ b/src/gui_qt/main/management.py @@ -1139,13 +1139,14 @@ class UpperManagement(QtCore.QObject): def logft(self, **kwargs): new_sets = [] ft_mode = kwargs['ft_mode'] + return_f = kwargs['return_f'] for set_id in kwargs['sets']: data_i = self.data[set_id] if ft_mode in ['cos', 'sin']: - new_data = Points(*logft(data_i.x, data_i.y, mode=ft_mode)) + new_data = Points(*logft(data_i.x, data_i.y, mode=ft_mode, return_f=return_f)) else: - new_data = Signal(*logft(data_i.x, data_i.y, mode=ft_mode)) + new_data = Signal(*logft(data_i.x, data_i.y, mode=ft_mode, return_f=return_f)) new_sets.append(self.add(new_data, color=data_i['color'], symbol=data_i['symbol'], line=data_i['line'])) self.data[new_sets[-1]].update(data_i.data.meta) diff --git a/src/gui_qt/math/integrate_derive.py b/src/gui_qt/math/integrate_derive.py index 632ed5c..8c6aaaa 100644 --- a/src/gui_qt/math/integrate_derive.py +++ b/src/gui_qt/math/integrate_derive.py @@ -16,16 +16,19 @@ class QDeriveIntegrate(QtWidgets.QDialog, Ui_Dialog): self.start_lineedit.setValidator(QtGui.QDoubleValidator()) self.stop_lineedit.setValidator(QtGui.QDoubleValidator()) self.ft_comboBox.hide() + self.freq_box.hide() elif self.mode == 'd': self.setWindowTitle('Differentiation dialog') self.widget.hide() self.ft_comboBox.hide() + self.freq_box.hide() elif self.mode == 'l': self.setWindowTitle('Logarithmic FT dialog') self.log_checkbox.hide() self.widget.hide() + self.freq_box.show() else: raise ValueError(f'Unknown mode {mode}, use "d", "i", or "l".') @@ -54,8 +57,10 @@ class QDeriveIntegrate(QtWidgets.QDialog, Ui_Dialog): self.stop_lineedit.setEnabled(full_range != QtCore.Qt.Checked) def get_options(self): - opts = {'graph': '' if self.newgraph_checkbox.isChecked() else self.graph_combobox.currentData(), - 'mode': self.mode, 'sets': []} + opts = { + 'graph': '' if self.newgraph_checkbox.isChecked() else self.graph_combobox.currentData(), + 'mode': self.mode, 'sets': [] + } if self.mode == 'i': start = None @@ -75,6 +80,7 @@ class QDeriveIntegrate(QtWidgets.QDialog, Ui_Dialog): if self.mode == 'l': opts['ft_mode'] = ['cos', 'sin', 'complex'][self.ft_comboBox.currentIndex()] + opts['return_f'] = self.freq_box.isChecked() else: opts['log'] = self.log_checkbox.isChecked() diff --git a/src/nmreval/math/logfourier.py b/src/nmreval/math/logfourier.py index 1b717e0..e150b05 100644 --- a/src/nmreval/math/logfourier.py +++ b/src/nmreval/math/logfourier.py @@ -27,10 +27,13 @@ More details can be found in [Blo] """ -def logft_cos(x, y, new_x=None): - n = x.size - if new_x is None: - new_x = 2*np.pi * np.geomspace(1/np.max(x), 1/np.min(x), num=n) +def logft_cos( + x: np.ndarray, + y: np.ndarray, + new_x: np.ndarray = None, + return_f: bool = True, +): + n, new_x, divide_by = _prepare_calculation(x, new_x, return_f) dydx = np.diff(y) / np.diff(x) @@ -48,13 +51,16 @@ def logft_cos(x, y, new_x=None): ret_val /= new_x**2 - return new_x, ret_val + return new_x/divide_by, ret_val -def logft_sin(x, y, new_x=None): - n = x.size - if new_x is None: - new_x = 2*np.pi * np.geomspace(1/np.max(x), 1/np.min(x), num=n) +def logft_sin( + x: np.ndarray, + y: np.ndarray, + new_x: np.ndarray = None, + return_f: bool = True, +): + n, new_x, divide_by = _prepare_calculation(x, new_x, return_f) dydx = np.diff(y) / np.diff(x) @@ -73,13 +79,20 @@ def logft_sin(x, y, new_x=None): ret_val /= new_x**2 ret_val += y[0] / new_x - return new_x, ret_val + return new_x/divide_by, ret_val -def logft_cmplx(x, y, new_x=None, backward: bool = False): - n = x.size - if new_x is None: - new_x = 2 * np.pi * np.geomspace(1/np.max(x), 1/np.min(x), num=n) +def logft_cmplx( + x: np.ndarray, + y: np.ndarray, + new_x: np.ndarray = None, + backward: bool = False, + return_f: bool = True, +): + if backward: + return_f = False + + n, new_x, divide_by = _prepare_calculation(x, new_x, return_f) dydx = np.diff(y) / np.diff(x) @@ -98,16 +111,22 @@ def logft_cmplx(x, y, new_x=None, backward: bool = False): ret_val /= new_x**2 ret_val += sign * 1j*y[0]/new_x - return new_x, ret_val + return new_x/divide_by, ret_val -def logft(x, y, new_x=None, mode='cos'): +def logft( + x: np.ndarray, + y: np.ndarray, + new_x: np.ndarray = None, + mode: str = 'cos', + return_f: bool = True, +): if mode not in ['cos', 'sin', 'complex']: raise ValueError(f'Unknown mode {mode}, use "cos", "sin", "complex".') ft_func = {'cos': logft_cos, 'sin': logft_sin, 'complex': logft_cmplx}[mode] - return ft_func(x, y, new_x=new_x) + return ft_func(x, y, new_x=new_x, return_f=return_f) def logift(x, y, new_x=None, mode='cos'): @@ -120,3 +139,15 @@ def logift(x, y, new_x=None, mode='cos'): return logft_cos(x, y, new_x=new_x) else: return logft_sin(x, y, new_x=new_x) + + +def _prepare_calculation(x: np.ndarray, new_x: np.ndarray | None, return_f: bool): + divide_by = 1. + n = x.size + if new_x is None: + if return_f: + divide_by = 2*np.pi + new_x = 2 * np.pi * np.geomspace(1 / np.max(x), 1 / np.min(x), num=n) + + return n, new_x, divide_by + diff --git a/src/resources/_ui/integratederive_dialog.ui b/src/resources/_ui/integratederive_dialog.ui index c1ff520..00a392b 100644 --- a/src/resources/_ui/integratederive_dialog.ui +++ b/src/resources/_ui/integratederive_dialog.ui @@ -7,7 +7,7 @@ 0 0 400 - 308 + 375 @@ -92,6 +92,13 @@ + + + + return x axis as f, not omega + + +