llwp 2.1.3__tar.gz → 2.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- llwp-2.1.4/MANIFEST.in +4 -0
- {llwp-2.1.3/llwp.egg-info → llwp-2.1.4}/PKG-INFO +1 -1
- {llwp-2.1.3 → llwp-2.1.4}/llwp/LLWP.py +150 -11
- {llwp-2.1.3 → llwp-2.1.4}/llwp/fitmethods.py +3 -0
- {llwp-2.1.3 → llwp-2.1.4/llwp.egg-info}/PKG-INFO +1 -1
- {llwp-2.1.3 → llwp-2.1.4}/llwp.egg-info/SOURCES.txt +4 -4
- {llwp-2.1.3 → llwp-2.1.4}/pyproject.toml +1 -1
- llwp-2.1.3/MANIFEST.in +0 -4
- {llwp-2.1.3 → llwp-2.1.4}/LICENSE +0 -0
- {llwp-2.1.3 → llwp-2.1.4}/README.md +0 -0
- /llwp-2.1.3/llwp/ASAP.svg → /llwp-2.1.4/llwp/IconASAP.svg +0 -0
- /llwp-2.1.3/llwp/ASAPMac.png → /llwp-2.1.4/llwp/IconASAPMac.png +0 -0
- /llwp-2.1.3/llwp/LLWP.svg → /llwp-2.1.4/llwp/IconLLWP.svg +0 -0
- /llwp-2.1.3/llwp/LLWPMac.png → /llwp-2.1.4/llwp/IconLLWPMac.png +0 -0
- {llwp-2.1.3 → llwp-2.1.4}/llwp/__init__.py +0 -0
- {llwp-2.1.3 → llwp-2.1.4}/llwp/__main__.py +0 -0
- {llwp-2.1.3 → llwp-2.1.4}/llwp.egg-info/dependency_links.txt +0 -0
- {llwp-2.1.3 → llwp-2.1.4}/llwp.egg-info/entry_points.txt +0 -0
- {llwp-2.1.3 → llwp-2.1.4}/llwp.egg-info/requires.txt +0 -0
- {llwp-2.1.3 → llwp-2.1.4}/llwp.egg-info/top_level.txt +0 -0
- {llwp-2.1.3 → llwp-2.1.4}/setup.cfg +0 -0
llwp-2.1.4/MANIFEST.in
ADDED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: llwp
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.4
|
|
4
4
|
Summary: LLWP is a fast, efficient and easy solution for exploring and assigning spectra - relying on Loomis-Wood plots.
|
|
5
5
|
Author-email: Luis Bonah <bonah@ph1.uni-koeln.de>
|
|
6
6
|
License-Expression: GPL-3.0-only
|
|
@@ -766,11 +766,11 @@ class PlotWidget(QWidget):
|
|
|
766
766
|
)
|
|
767
767
|
|
|
768
768
|
if config["convolution_kernel"]:
|
|
769
|
-
|
|
769
|
+
xmin, xmax = self.xrange
|
|
770
|
+
kernel_ys = ConvolutionWindow.kernel_at((xmin + xmax) / 2)
|
|
770
771
|
convolution_padding = len(kernel_ys) // 2
|
|
771
772
|
stepwidth = config["convolution_stepwidth"]
|
|
772
773
|
|
|
773
|
-
xmin, xmax = self.xrange
|
|
774
774
|
n_xs = (xmax - xmin) // stepwidth + 1
|
|
775
775
|
con_xs = np.arange(-n_xs, n_xs + 1) * stepwidth + (xmax + xmin) / 2
|
|
776
776
|
|
|
@@ -2745,7 +2745,7 @@ class LWPAx:
|
|
|
2745
2745
|
)
|
|
2746
2746
|
|
|
2747
2747
|
if config["convolution_kernel"]:
|
|
2748
|
-
kernel_ys =
|
|
2748
|
+
kernel_ys = ConvolutionWindow.kernel_at((xmin + xmax) / 2)
|
|
2749
2749
|
convolution_padding = len(kernel_ys) // 2
|
|
2750
2750
|
stepwidth = config["convolution_stepwidth"]
|
|
2751
2751
|
|
|
@@ -3262,6 +3262,9 @@ class LWPWidget(QGroupBox):
|
|
|
3262
3262
|
self.fig.savefig(fname)
|
|
3263
3263
|
|
|
3264
3264
|
def on_click(self, event):
|
|
3265
|
+
if event.canvas.widgetlock.locked(): # Pan or zoom of the matplotlib toolbar is active
|
|
3266
|
+
return
|
|
3267
|
+
|
|
3265
3268
|
ax = event.inaxes
|
|
3266
3269
|
index = np.asarray(np.where(self.axes == ax)).T
|
|
3267
3270
|
|
|
@@ -3908,11 +3911,11 @@ class MainWindow(QMainWindow):
|
|
|
3908
3911
|
]
|
|
3909
3912
|
for folder in possible_folders:
|
|
3910
3913
|
if sys.platform == "darwin":
|
|
3911
|
-
iconpath = os.path.join(folder, f"{APP_TAG}Mac.png")
|
|
3914
|
+
iconpath = os.path.join(folder, f"Icon{APP_TAG}Mac.png")
|
|
3912
3915
|
if os.path.isfile(iconpath):
|
|
3913
3916
|
break
|
|
3914
3917
|
|
|
3915
|
-
iconpath = os.path.join(folder, f"{APP_TAG}.svg")
|
|
3918
|
+
iconpath = os.path.join(folder, f"Icon{APP_TAG}.svg")
|
|
3916
3919
|
if os.path.isfile(iconpath):
|
|
3917
3920
|
break
|
|
3918
3921
|
|
|
@@ -4231,13 +4234,10 @@ class LLWP(QApplication):
|
|
|
4231
4234
|
mainwindow = self.mainwindow_class(self)
|
|
4232
4235
|
mainwindow.create_gui_components()
|
|
4233
4236
|
|
|
4234
|
-
if len(sys.argv) > 1:
|
|
4235
|
-
project = sys.argv[1]
|
|
4236
|
-
if project != "--ASAP":
|
|
4237
|
-
File.load_files(project)
|
|
4238
|
-
|
|
4239
4237
|
mainwindow.show()
|
|
4240
4238
|
|
|
4239
|
+
self.load_command_line_files()
|
|
4240
|
+
|
|
4241
4241
|
if messages:
|
|
4242
4242
|
notify_warning.emit("\n".join(messages))
|
|
4243
4243
|
|
|
@@ -4284,6 +4284,28 @@ class LLWP(QApplication):
|
|
|
4284
4284
|
file.color = "#000000"
|
|
4285
4285
|
file.apply_color()
|
|
4286
4286
|
|
|
4287
|
+
@staticmethod
|
|
4288
|
+
def load_command_line_files():
|
|
4289
|
+
files = []
|
|
4290
|
+
invalid_files = []
|
|
4291
|
+
for argument in sys.argv[1:]:
|
|
4292
|
+
if argument == "--ASAP":
|
|
4293
|
+
continue
|
|
4294
|
+
if os.path.isfile(argument):
|
|
4295
|
+
files.append(os.path.abspath(argument))
|
|
4296
|
+
else:
|
|
4297
|
+
invalid_files.append(argument)
|
|
4298
|
+
|
|
4299
|
+
if invalid_files:
|
|
4300
|
+
invalid_files_string = ", ".join(invalid_files)
|
|
4301
|
+
notify_warning.emit(
|
|
4302
|
+
f"The following command line arguments are not existing and were ignored: {invalid_files_string}"
|
|
4303
|
+
)
|
|
4304
|
+
|
|
4305
|
+
if files:
|
|
4306
|
+
files_by_type = File.sort_files_by_type(files)
|
|
4307
|
+
File.add_multiple_files_by_type(files_by_type)
|
|
4308
|
+
|
|
4287
4309
|
def run_init_commands(self):
|
|
4288
4310
|
try:
|
|
4289
4311
|
commands = config["commandlinedialog_commands"]
|
|
@@ -5391,6 +5413,9 @@ class AssignAllDialog(QDialog):
|
|
|
5391
5413
|
NewAssignments.get_instance().add_rows(new_assignments)
|
|
5392
5414
|
|
|
5393
5415
|
def on_click(self, event):
|
|
5416
|
+
if event.canvas.widgetlock.locked(): # Pan or zoom of the matplotlib toolbar is active
|
|
5417
|
+
return
|
|
5418
|
+
|
|
5394
5419
|
clicked_axis = event.inaxes
|
|
5395
5420
|
|
|
5396
5421
|
if not clicked_axis or event.button != 1:
|
|
@@ -7374,7 +7399,7 @@ class ConvolutionWindow(EQDockWidget):
|
|
|
7374
7399
|
def on_width_changed(self, name, value):
|
|
7375
7400
|
config["convolution_widths"] = {**config["convolution_widths"], name: value}
|
|
7376
7401
|
|
|
7377
|
-
def
|
|
7402
|
+
def compute_kernel(self, frequency=None):
|
|
7378
7403
|
function = config["convolution_function"]
|
|
7379
7404
|
|
|
7380
7405
|
if function == "Off":
|
|
@@ -7401,6 +7426,13 @@ class ConvolutionWindow(EQDockWidget):
|
|
|
7401
7426
|
p.name: config["convolution_widths"].get(p.name, p.default or 1)
|
|
7402
7427
|
for p in method.kernel_params()
|
|
7403
7428
|
}
|
|
7429
|
+
if method.frequency_dependent_kernel:
|
|
7430
|
+
if frequency is None:
|
|
7431
|
+
# Only used to fill the stored kernel, the plots call kernel_at
|
|
7432
|
+
axes = getattr(mainwindow.lwpwidget, "lwpaxes", None)
|
|
7433
|
+
axes = [] if axes is None else axes.flatten()
|
|
7434
|
+
frequency = np.mean(axes[0].xrange) if len(axes) else 0.0
|
|
7435
|
+
widths["frequency"] = frequency
|
|
7404
7436
|
kernel = method(derivative).kernel(kernel_xs, amplitude, **widths)
|
|
7405
7437
|
else: # Custom Kernel
|
|
7406
7438
|
tmp = self.custom_kernel_input.toPlainText().strip()
|
|
@@ -7409,7 +7441,23 @@ class ConvolutionWindow(EQDockWidget):
|
|
|
7409
7441
|
else:
|
|
7410
7442
|
tmp = tmp.split(",")
|
|
7411
7443
|
kernel = [float(x) for x in tmp]
|
|
7444
|
+
return kernel
|
|
7445
|
+
|
|
7446
|
+
@classmethod
|
|
7447
|
+
def kernel_at(cls, frequency):
|
|
7448
|
+
"""Convolution kernel for a plot centered at `frequency`."""
|
|
7449
|
+
self = cls.instance
|
|
7450
|
+
if config["convolution_kernel"] and config["convolution_function"] not in (
|
|
7451
|
+
"Off",
|
|
7452
|
+
"Custom",
|
|
7453
|
+
):
|
|
7454
|
+
method = self.get_method()
|
|
7455
|
+
if method is not None and method[0].frequency_dependent_kernel:
|
|
7456
|
+
return np.array(self.compute_kernel(frequency))
|
|
7457
|
+
return np.array(config["convolution_kernel"])
|
|
7412
7458
|
|
|
7459
|
+
def on_change(self):
|
|
7460
|
+
kernel = self.compute_kernel()
|
|
7413
7461
|
config["convolution_kernel"] = list(kernel)
|
|
7414
7462
|
mainwindow.lwpwidget.set_data()
|
|
7415
7463
|
|
|
@@ -8270,6 +8318,9 @@ class BlendedLinesWindow(EQDockWidget):
|
|
|
8270
8318
|
plot_widget.update_plot_requested.emit()
|
|
8271
8319
|
|
|
8272
8320
|
def add_peak(self, event):
|
|
8321
|
+
if event.canvas.widgetlock.locked(): # Pan or zoom of the matplotlib toolbar is active
|
|
8322
|
+
return
|
|
8323
|
+
|
|
8273
8324
|
x, y = event.xdata, event.ydata
|
|
8274
8325
|
is_left_mouse_button = event.button == 1
|
|
8275
8326
|
if not (x and y and is_left_mouse_button):
|
|
@@ -10964,6 +11015,9 @@ class ASAPWidget(LWPWidget):
|
|
|
10964
11015
|
mainwindow.statusbar.position_label.setText(text_cursor)
|
|
10965
11016
|
|
|
10966
11017
|
def on_click(self, event):
|
|
11018
|
+
if event.canvas.widgetlock.locked(): # Pan or zoom of the matplotlib toolbar is active
|
|
11019
|
+
return
|
|
11020
|
+
|
|
10967
11021
|
super().on_click(event)
|
|
10968
11022
|
|
|
10969
11023
|
ax = event.inaxes
|
|
@@ -11806,3 +11860,88 @@ if __name__ == "__main__":
|
|
|
11806
11860
|
# return(ts, ys)
|
|
11807
11861
|
|
|
11808
11862
|
# FIDLineshape.postprocessing_function = FID_postprocessing_function
|
|
11863
|
+
|
|
11864
|
+
|
|
11865
|
+
## Add Doppler splitted lines to fitting methods
|
|
11866
|
+
|
|
11867
|
+
# from llwp.fitmethods import Gauss, Lorentz
|
|
11868
|
+
|
|
11869
|
+
# # The splitting is proportional to the frequency. The fitted parameter is the relative
|
|
11870
|
+
# # splitting in ppm: the distance of each component from the center at the frequency f is
|
|
11871
|
+
# # delta * 1e-6 * f (in the unit of x, e.g. MHz). For 0.05 MHz at 12218 MHz this is 4.1 ppm.
|
|
11872
|
+
# START_DELTA = 2.75
|
|
11873
|
+
|
|
11874
|
+
|
|
11875
|
+
# def delta_at(frequency, delta):
|
|
11876
|
+
# """Distance of each component from the center at the given frequency."""
|
|
11877
|
+
# return delta * 1e-6 * frequency
|
|
11878
|
+
|
|
11879
|
+
|
|
11880
|
+
# # Tick "All Same Width" to use the same relative splitting for all lines.
|
|
11881
|
+
# DELTA = Param(
|
|
11882
|
+
# "delta", "Delta (ppm)", shareable=True, default=START_DELTA, in_kernel=True
|
|
11883
|
+
# )
|
|
11884
|
+
|
|
11885
|
+
|
|
11886
|
+
# class ScaledDoppler(ParametricLineshape):
|
|
11887
|
+
# """Doublet with the components at x0 +- delta_at(x0, delta).
|
|
11888
|
+
|
|
11889
|
+
# The relative splitting is fitted, starting at START_DELTA with bounds 0 and
|
|
11890
|
+
# `max_factor` times that. In the convolution window the relative splitting is entered
|
|
11891
|
+
# by hand (or taken from the last fit). The kernel is created for the frequency at the
|
|
11892
|
+
# center of the plot."""
|
|
11893
|
+
|
|
11894
|
+
# abstract = True
|
|
11895
|
+
# can_convolve = True
|
|
11896
|
+
# frequency_dependent_kernel = True # kernel() receives the plot's center frequency
|
|
11897
|
+
# component = None # Lineshape class of the two components
|
|
11898
|
+
# max_factor = 5
|
|
11899
|
+
|
|
11900
|
+
# def __init__(self, derivative=0, **options):
|
|
11901
|
+
# # Start the center of a single fit in the middle of the marked area. The highest
|
|
11902
|
+
# # point is one of the two components and not the center of the doublet.
|
|
11903
|
+
# options.setdefault("xs_weight_factor", 0)
|
|
11904
|
+
# super().__init__(derivative, **options)
|
|
11905
|
+
# self._component = self.component(derivative, **options)
|
|
11906
|
+
|
|
11907
|
+
# def initial_guess(self, guess):
|
|
11908
|
+
# guesses = super().initial_guess(guess)
|
|
11909
|
+
# guesses[-1] = (START_DELTA, 0, self.max_factor * START_DELTA)
|
|
11910
|
+
# return guesses
|
|
11911
|
+
|
|
11912
|
+
# def profile(self, x, *values):
|
|
11913
|
+
# *line, delta = values
|
|
11914
|
+
# x0, amp, *other = line
|
|
11915
|
+
# return self.doublet(x, x0, amp, other, delta_at(x0, delta))
|
|
11916
|
+
|
|
11917
|
+
# def doublet(self, x, x0, amp, other, delta):
|
|
11918
|
+
# return self._component.profile(
|
|
11919
|
+
# x, x0 - delta, amp, *other
|
|
11920
|
+
# ) + self._component.profile(x, x0 + delta, amp, *other)
|
|
11921
|
+
|
|
11922
|
+
# def kernel(self, xs, amplitude, frequency, **widths):
|
|
11923
|
+
# values = []
|
|
11924
|
+
# for param in self.params[:-1]:
|
|
11925
|
+
# if param.role == "center":
|
|
11926
|
+
# values.append(0)
|
|
11927
|
+
# elif param.role == "amplitude":
|
|
11928
|
+
# values.append(amplitude)
|
|
11929
|
+
# else:
|
|
11930
|
+
# values.append(widths.get(param.name, param.default))
|
|
11931
|
+
# delta = delta_at(frequency, widths.get("delta", START_DELTA))
|
|
11932
|
+
# _, amp, *other = values
|
|
11933
|
+
# return self.doublet(xs, 0, amp, other, delta)
|
|
11934
|
+
|
|
11935
|
+
|
|
11936
|
+
# class ScaledDopplerGauss(ScaledDoppler):
|
|
11937
|
+
# name = "Doppler Gauss (scaled)"
|
|
11938
|
+
# derivatives = (0, 1, 2)
|
|
11939
|
+
# component = Gauss
|
|
11940
|
+
# params = Gauss.params + (DELTA,)
|
|
11941
|
+
|
|
11942
|
+
|
|
11943
|
+
# class ScaledDopplerLorentz(ScaledDoppler):
|
|
11944
|
+
# name = "Doppler Lorentz (scaled)"
|
|
11945
|
+
# derivatives = (0, 1, 2)
|
|
11946
|
+
# component = Lorentz
|
|
11947
|
+
# params = Lorentz.params + (DELTA,)
|
|
@@ -11,6 +11,8 @@ its menus, depending on which capabilities a class declares:
|
|
|
11
11
|
* ``can_fit_single``: fits a single line (main axes, assign all, ...)
|
|
12
12
|
* ``can_fit_multi``: fits several lines at once (Blended Lines window)
|
|
13
13
|
* ``can_convolve``: can create a kernel to convolute a stick spectrum
|
|
14
|
+
* ``frequency_dependent_kernel``: the kernel depends on the frequency, ``kernel`` then
|
|
15
|
+
receives the keyword argument ``frequency`` (center of the plot)
|
|
14
16
|
|
|
15
17
|
Hierarchy::
|
|
16
18
|
|
|
@@ -174,6 +176,7 @@ class FitMethod:
|
|
|
174
176
|
can_fit_single = False
|
|
175
177
|
can_fit_multi = False
|
|
176
178
|
can_convolve = False
|
|
179
|
+
frequency_dependent_kernel = False
|
|
177
180
|
min_points = 2 # Minimum number of data points for a single fit
|
|
178
181
|
|
|
179
182
|
def __init_subclass__(cls, **kwargs):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: llwp
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.4
|
|
4
4
|
Summary: LLWP is a fast, efficient and easy solution for exploring and assigning spectra - relying on Loomis-Wood plots.
|
|
5
5
|
Author-email: Luis Bonah <bonah@ph1.uni-koeln.de>
|
|
6
6
|
License-Expression: GPL-3.0-only
|
|
@@ -2,11 +2,11 @@ LICENSE
|
|
|
2
2
|
MANIFEST.in
|
|
3
3
|
README.md
|
|
4
4
|
pyproject.toml
|
|
5
|
-
llwp/
|
|
6
|
-
llwp/
|
|
5
|
+
llwp/IconASAP.svg
|
|
6
|
+
llwp/IconASAPMac.png
|
|
7
|
+
llwp/IconLLWP.svg
|
|
8
|
+
llwp/IconLLWPMac.png
|
|
7
9
|
llwp/LLWP.py
|
|
8
|
-
llwp/LLWP.svg
|
|
9
|
-
llwp/LLWPMac.png
|
|
10
10
|
llwp/__init__.py
|
|
11
11
|
llwp/__main__.py
|
|
12
12
|
llwp/fitmethods.py
|
llwp-2.1.3/MANIFEST.in
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|