diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..f152684 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +--- +version: 2 +updates: + + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" + assignees: + - "kerberizer" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 3c61abc..4881bb1 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -22,10 +22,10 @@ jobs: steps: - name: Checkout the repository - uses: actions/checkout@v4 + uses: actions/checkout@v4.1.7 - name: Setup Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v5.2.0 with: python-version: '3.9' @@ -38,4 +38,4 @@ jobs: run: python -m build - name: Publish package - uses: pypa/gh-action-pypi-publish@release/v1 + uses: pypa/gh-action-pypi-publish@v1.10.1 diff --git a/.gitignore b/.gitignore index 39621e7..6461b17 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,11 @@ +# vim +.*.un~ +.*.swp +Session.vim + +# VS Code +.vscode + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] @@ -20,7 +28,6 @@ parts/ sdist/ var/ wheels/ -pip-wheel-metadata/ share/python-wheels/ *.egg-info/ .installed.cfg @@ -50,6 +57,7 @@ coverage.xml *.py,cover .hypothesis/ .pytest_cache/ +cover/ # Translations *.mo @@ -72,6 +80,7 @@ instance/ docs/_build/ # PyBuilder +.pybuilder/ target/ # Jupyter Notebook @@ -82,7 +91,9 @@ profile_default/ ipython_config.py # pyenv -.python-version +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. @@ -91,7 +102,24 @@ ipython_config.py # install all needed dependencies. #Pipfile.lock -# PEP 582; used by e.g. github.com/David-OConnor/pyflow +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/latest/usage/project/#working-with-version-control +.pdm.toml +.pdm-python +.pdm-build/ + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm __pypackages__/ # Celery stuff @@ -128,11 +156,15 @@ dmypy.json # Pyre type checker .pyre/ +# pytype static type analyzer +.pytype/ -# vim -.*.un~ -.*.swp -Session.vim +# Cython debug symbols +cython_debug/ -# VS Code -.vscode +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..bd28b9c --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.9 diff --git a/setup.py b/setup.py index c18b0e8..fa0d3b4 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ NAME = 'oranchada' -VERSION = '0.0.15' +VERSION = '1.0.0' DESCRIPTION = 'Orange add-on for Raman spectroscopy' README_FILE = path.join(path.dirname(__file__), 'README.pypi') @@ -46,7 +46,7 @@ 'orange-widget-base>=4.16.1', 'pip>=9.0', # same as for Orange 3.28 'ploomber~=0.23.0', - 'ramanchada2~=0.1.1', + 'ramanchada2~=1.0', 'setuptools>=36.3', # same as for Orange 3.28 'tables~=3.9.1', # 'AnyQt>=0.0.6', @@ -101,7 +101,7 @@ } CLASSIFIERS = [ - 'Development Status :: 4 - Beta', + 'Development Status :: 5 - Production/Stable', 'Environment :: Plugins', 'Intended Audience :: Developers', 'Intended Audience :: Education', diff --git a/src/orangecontrib/oranchada/base_widget/base_widget.py b/src/orangecontrib/oranchada/base_widget/base_widget.py index b9435b7..a4c068d 100644 --- a/src/orangecontrib/oranchada/base_widget/base_widget.py +++ b/src/orangecontrib/oranchada/base_widget/base_widget.py @@ -48,7 +48,7 @@ def __init__(self): gui.checkBox(self.optionsBox, self, "should_plot_legend", "Plot legend", callback=self.auto_process) class Outputs: - out_spe = Output("RC2Spectra", RC2Spectra, default=True, auto_summary = False) + out_spe = Output("RC2Spectra", RC2Spectra, default=True, auto_summary=False) data = Output("Data", Table, default=False) def force_plot(self): @@ -91,13 +91,13 @@ def custom_plot(self, ax): def set_x_title(self, ax): xlab = '' for spe in reversed(self.out_spe): - if 'xlabel' in spe.meta.__root__: + if 'xlabel' in spe.meta.root: xlab = spe.meta['xlabel'] if not xlab: return should_warn = False for spe in self.out_spe: - if 'xlabel' in spe.meta.__root__: + if 'xlabel' in spe.meta.root: if xlab != spe.meta['xlabel']: should_warn = True else: @@ -118,7 +118,7 @@ def send_output_table(self): if self.out_spe: try: self.Outputs.data.send(self.output_table_domain()) - except: # just in case the new implementation breaks + except: # just in case the new implementation breaks self.Outputs.data.send(self.output_table_old()) def output_table_domain(self): @@ -142,7 +142,7 @@ def output_table_domain(self): row_data[column_index] = y meta_values = [] for key in all_meta_keys: - if key in spe.meta.__root__: + if key in spe.meta.root: meta_values.append(spe.meta[key]) else: meta_values.append(None) @@ -150,8 +150,6 @@ def output_table_domain(self): return Table.from_list(domain, data) - - def send_outputs(self): if self.out_spe: self.Outputs.out_spe.send(self.out_spe) diff --git a/src/orangecontrib/oranchada/processings/add_baseline.py b/src/orangecontrib/oranchada/processings/add_baseline.py index 8cd292f..59b0b65 100644 --- a/src/orangecontrib/oranchada/processings/add_baseline.py +++ b/src/orangecontrib/oranchada/processings/add_baseline.py @@ -1,13 +1,13 @@ from typing import Union -import pydantic import ramanchada2 as rc2 from AnyQt.QtWidgets import QGroupBox from Orange.widgets import gui +from pydantic import validate_call class AddBaseline: - @pydantic.validate_arguments(config=dict(arbitrary_types_allowed=True)) + @validate_call(config=dict(arbitrary_types_allowed=True)) def __init__(self, parent, *, n_freq: tuple[str, Union[None, QGroupBox]], amplitude: tuple[str, Union[None, QGroupBox]], @@ -43,7 +43,7 @@ def __init__(self, parent, *, gui.doubleSpin(quadratic[1], self._parent, self._quadratic, -100, 100, decimals=7, step=.000001, label='quadratic', callback=self.auto_process) - @pydantic.validate_arguments(config=dict(arbitrary_types_allowed=True)) + @validate_call(config=dict(arbitrary_types_allowed=True)) def __call__(self, spe: rc2.spectrum.Spectrum) -> rc2.spectrum.Spectrum: return spe.add_baseline(n_freq=self.n_freq, amplitude=self.amplitude, diff --git a/src/orangecontrib/oranchada/processings/add_noise.py b/src/orangecontrib/oranchada/processings/add_noise.py index fa8f430..c99e8de 100644 --- a/src/orangecontrib/oranchada/processings/add_noise.py +++ b/src/orangecontrib/oranchada/processings/add_noise.py @@ -1,13 +1,13 @@ from typing import Union -import pydantic import ramanchada2 as rc2 from AnyQt.QtWidgets import QGroupBox from Orange.widgets import gui +from pydantic import validate_call class AddNoise: - @pydantic.validate_arguments(config=dict(arbitrary_types_allowed=True)) + @validate_call(config=dict(arbitrary_types_allowed=True)) def __init__(self, parent, *, noise_scale: tuple[str, Union[None, QGroupBox]], ): @@ -21,7 +21,7 @@ def __init__(self, parent, *, def auto_process(self): self._parent.auto_process() - @pydantic.validate_arguments(config=dict(arbitrary_types_allowed=True)) + @validate_call(config=dict(arbitrary_types_allowed=True)) def __call__(self, spe: rc2.spectrum.Spectrum) -> rc2.spectrum.Spectrum: return spe.add_poisson_noise(self.noise_scale) diff --git a/src/orangecontrib/oranchada/processings/gen_spe.py b/src/orangecontrib/oranchada/processings/gen_spe.py index e429926..b63611d 100644 --- a/src/orangecontrib/oranchada/processings/gen_spe.py +++ b/src/orangecontrib/oranchada/processings/gen_spe.py @@ -1,13 +1,14 @@ -from Orange.widgets import gui -import ramanchada2 as rc2 +from typing import Union + import numpy as np +import ramanchada2 as rc2 from AnyQt.QtWidgets import QGroupBox -import pydantic -from typing import Union +from Orange.widgets import gui +from pydantic import validate_call class GenSpe: - @pydantic.validate_arguments(config=dict(arbitrary_types_allowed=True)) + @validate_call(config=dict(arbitrary_types_allowed=True)) def __init__(self, parent, *, spe_xmin: tuple[str, Union[None, QGroupBox]], spe_xmax: tuple[str, Union[None, QGroupBox]], @@ -44,7 +45,7 @@ def set_deltas(self): self.deltas = '620.9: 16, 795.8: 10, 1001.4: 100, 1031.8: 27, 1155.3: 13, 1450.5: 8, 1583.1: 12, 1602.3: 28, 2852.4: 9, 2904.5: 13, 3054.3: 32' # noqa: E501 self.deltas_edit.setReadOnly(True) - @pydantic.validate_arguments(config=dict(arbitrary_types_allowed=True)) + @validate_call(config=dict(arbitrary_types_allowed=True)) def __call__(self) -> rc2.spectrum.Spectrum: deltas_dict = dict([[float(j) for j in i.split(':')] for i in self.deltas.replace(' ', '').split(',')]) spe1 = rc2.spectrum.Spectrum(x=np.array(list(deltas_dict.keys())), y=np.array(list(deltas_dict.values()))) diff --git a/src/orangecontrib/oranchada/tests/process_spectra_test.py b/src/orangecontrib/oranchada/tests/process_spectra_test.py index 2532476..a874fa4 100644 --- a/src/orangecontrib/oranchada/tests/process_spectra_test.py +++ b/src/orangecontrib/oranchada/tests/process_spectra_test.py @@ -1,5 +1,5 @@ import unittest -from widgets import ProcessSpectraWidget +from widgets_pro.process_spectra import ProcessSpectraWidget class TestLoadSpectraWidget(unittest.TestCase): diff --git a/src/orangecontrib/oranchada/widgets_pro/load_file.py b/src/orangecontrib/oranchada/widgets_pro/load_file.py index 7e77339..b46c9a9 100644 --- a/src/orangecontrib/oranchada/widgets_pro/load_file.py +++ b/src/orangecontrib/oranchada/widgets_pro/load_file.py @@ -61,12 +61,12 @@ def process(self): for fname in self.filenames: name, extension = os.path.splitext(fname) if extension == ".cha": - spe = rc2.spectrum.from_chada(fname,dataset=self.dataset) + spe = rc2.spectrum.from_chada(fname, dataset=self.dataset) else: spe = rc2.spectrum.from_local_file(fname, - filetype=(self.fileformat if self.fileformat != 'Auto' else None), - ) - meta_dct = spe.meta.dict()['__root__'] + filetype=(self.fileformat if self.fileformat != 'Auto' else None), + ) + meta_dct = spe.meta.model_dump() meta_dct['xlabel'] = 'Raman shift [cm¯¹]' spe.meta = meta_dct self.out_spe.append(spe) diff --git a/src/orangecontrib/oranchada/widgets_pro/load_test_spectra.py b/src/orangecontrib/oranchada/widgets_pro/load_test_spectra.py index a252cc9..57a4578 100644 --- a/src/orangecontrib/oranchada/widgets_pro/load_test_spectra.py +++ b/src/orangecontrib/oranchada/widgets_pro/load_test_spectra.py @@ -58,7 +58,7 @@ def process(self): self.out_spe = list() for fn in data.prepend_prefix(self.selected_filenames): spe = rc2.spectrum.from_local_file(fn) - meta_dct = spe.meta.dict()['__root__'] + meta_dct = spe.meta.model_dump() meta_dct['xlabel'] = 'Raman shift [cm¯¹]' spe.meta = meta_dct self.out_spe.append(spe) diff --git a/src/orangecontrib/oranchada/widgets_pro/raman_shift_to_wavelength.py b/src/orangecontrib/oranchada/widgets_pro/raman_shift_to_wavelength.py index 4ae8e92..2c74a33 100644 --- a/src/orangecontrib/oranchada/widgets_pro/raman_shift_to_wavelength.py +++ b/src/orangecontrib/oranchada/widgets_pro/raman_shift_to_wavelength.py @@ -25,10 +25,10 @@ def process(self): self.out_spe = list() for inspe in self.in_spe: spe = inspe.shift_cm_1_to_abs_nm_filter(laser_wave_length_nm=self.laser_wl) - if 'xlabel' in spe.meta.__root__: + if 'xlabel' in spe.meta.root: if spe.meta['xlabel'] != 'Raman shift [cm¯¹]': self.Warning.x_label_not_ramanshift() - meta_dct = spe.meta.dict()['__root__'] + meta_dct = spe.meta.model_dump() meta_dct['xlabel'] = 'Wavelength [nm]' spe.meta = meta_dct self.out_spe.append(spe) diff --git a/src/orangecontrib/oranchada/widgets_pro/wavelength_to_raman_shift.py b/src/orangecontrib/oranchada/widgets_pro/wavelength_to_raman_shift.py index 6382401..0298398 100644 --- a/src/orangecontrib/oranchada/widgets_pro/wavelength_to_raman_shift.py +++ b/src/orangecontrib/oranchada/widgets_pro/wavelength_to_raman_shift.py @@ -24,10 +24,10 @@ class Warning(FilterWidget.Warning): def process(self): self.out_spe = list() for spe in self.in_spe: - if 'xlabel' in spe.meta.__root__: + if 'xlabel' in spe.meta.root: if spe.meta['xlabel'] != 'Wavelength [nm]': self.Warning.x_label_not_wavelength() - meta_dct = spe.meta.dict()['__root__'] + meta_dct = spe.meta.model_dump() meta_dct['xlabel'] = 'Raman shift [cm¯¹]' spe.meta = meta_dct self.out_spe.append(