From c017ed29b09ba72714ec01fbeb05231c5debe193 Mon Sep 17 00:00:00 2001 From: Joe Fowler Date: Mon, 22 Jul 2024 12:24:19 -0500 Subject: [PATCH 1/6] Widen test acceptance on drift correct regression Numpy 2.0 was failing the regression tests on the drift-correct step. This is not a true regression but a different choice of "optimum" in a function that has no single minimum. Choose to broaden the acceptance criteria. Fixes #295. --- mass/core/channel.py | 2 +- tests/regression_test/test_regression.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mass/core/channel.py b/mass/core/channel.py index 073d2a47..7432e846 100644 --- a/mass/core/channel.py +++ b/mass/core/channel.py @@ -1738,7 +1738,7 @@ def drift_correct(self, attr="p_filt_value", forceNew=False, category={}): drift_corr_param, self.drift_correct_info = \ mass.core.analysis_algorithms.drift_correct(indicator, uncorrected) self.p_filt_value_dc.attrs.update(self.drift_correct_info) # Store in hdf5 file - LOG.info('chan %d best drift correction parameter: %.6f', self.channum, drift_corr_param) + LOG.info('chan %d best drift correction parameter: %.6fe6', self.channum, 1e6*drift_corr_param) self._apply_drift_correction(attr=attr) def _apply_drift_correction(self, attr): diff --git a/tests/regression_test/test_regression.py b/tests/regression_test/test_regression.py index 19712ca8..583e635d 100644 --- a/tests/regression_test/test_regression.py +++ b/tests/regression_test/test_regression.py @@ -87,7 +87,7 @@ def test_summaries(self): # test_post_filter nt.assert_allclose(self.data.datasets[0].p_filt_value, self.d['p_filt_value'], rtol=1e-6) nt.assert_allclose(self.data.datasets[0].p_filt_value_dc, - self.d['p_filt_value_dc'], rtol=1e-6) + self.d['p_filt_value_dc'], rtol=1e-4, atol=3) # test_peak_time: """Be sure that peak_time_microsec=89.0 comes out to the same answers""" From de00202debad9e9f563aab0ce04e03111a8f051b Mon Sep 17 00:00:00 2001 From: Joe Fowler Date: Mon, 22 Jul 2024 12:25:30 -0500 Subject: [PATCH 2/6] Update VERSIONS.md --- VERSIONS.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/VERSIONS.md b/VERSIONS.md index ce536750..dd142b23 100644 --- a/VERSIONS.md +++ b/VERSIONS.md @@ -1,5 +1,9 @@ ## Note on version numbers of Mass +**0.8.5** July 2024- + +* Fix problem where numpy 2.0 was failing a regression test. Not a true regression, so we broaden the acceptance criteria (issue 295). + **0.8.4** June 5, 2024 * Fix test failures on Py 3.12: store HDF5 cache files in temp directories, so tests don't share them. (issue 272). Correctly use the modern `tempfile` library's API. From fa85e7b4459fa378b2422c2af20177f7e315a250 Mon Sep 17 00:00:00 2001 From: Joe Fowler Date: Mon, 22 Jul 2024 12:35:42 -0500 Subject: [PATCH 3/6] Fix 3 ruff complaints --- mass/calibration/import_asd.py | 10 +++++----- mass/core/channel.py | 2 +- tests/core/test_core.py | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mass/calibration/import_asd.py b/mass/calibration/import_asd.py index f3bd8070..a12d981a 100644 --- a/mass/calibration/import_asd.py +++ b/mass/calibration/import_asd.py @@ -40,11 +40,11 @@ def write_asd_pickle(inputFilename, outputFilename): # Sort levels within an element/charge state by energy outputDict = {} - for iElement in energyLevelsDict.keys(): - for iCharge in energyLevelsDict[iElement].keys(): - energyOrder = np.argsort(np.array(list(energyLevelsDict[iElement][iCharge].values()))[:, 0]) - orderedKeys = np.array(list(energyLevelsDict[iElement][iCharge].keys()))[energyOrder] - orderedValues = np.array(list(energyLevelsDict[iElement][iCharge].values()))[energyOrder] + for iElement, element in energyLevelsDict.values(): + for iCharge, chargestate in element.values(): + energyOrder = np.argsort(np.array(list(chargestate.values()))[:, 0]) + orderedKeys = np.array(list(chargestate.keys()))[energyOrder] + orderedValues = np.array(list(chargestate.values()))[energyOrder] for i, iKey in enumerate(list(orderedKeys)): if iElement not in outputDict.keys(): outputDict[iElement] = {} diff --git a/mass/core/channel.py b/mass/core/channel.py index 7432e846..67c95bc4 100644 --- a/mass/core/channel.py +++ b/mass/core/channel.py @@ -1738,7 +1738,7 @@ def drift_correct(self, attr="p_filt_value", forceNew=False, category={}): drift_corr_param, self.drift_correct_info = \ mass.core.analysis_algorithms.drift_correct(indicator, uncorrected) self.p_filt_value_dc.attrs.update(self.drift_correct_info) # Store in hdf5 file - LOG.info('chan %d best drift correction parameter: %.6fe6', self.channum, 1e6*drift_corr_param) + LOG.info('chan %d best drift correction parameter: %.6fe6', self.channum, 1e6 * drift_corr_param) self._apply_drift_correction(attr=attr) def _apply_drift_correction(self, attr): diff --git a/tests/core/test_core.py b/tests/core/test_core.py index 9805cd5b..45cc94d6 100644 --- a/tests/core/test_core.py +++ b/tests/core/test_core.py @@ -217,14 +217,14 @@ def test_readonly_view(self, tmp_path): results_python = {k: ds.__dict__[k][:] for k in ds.__dict__ if k.startswith("p_")} # Be sure the Cython and Python results are pretty close - for k in results_cython: + for k, cyresult in results_cython.items(): # print(f"\n{k}:") # print(results_cython[k][:20]) # print(results_python[k][:20]) if np.any(np.isnan(results_python[k])): continue # print((results_cython[k] / results_python[k])[:20]) - assert results_cython[k] == pytest.approx(results_python[k], rel=0.003) + assert cyresult == pytest.approx(results_python[k], rel=0.003) def test_experiment_state(self, tmp_path_factory): # First test with the default experimentStateFile From cfbdf82a6069c930cc1818f65e987e685aab5cb2 Mon Sep 17 00:00:00 2001 From: Joe Fowler Date: Mon, 22 Jul 2024 13:54:49 -0500 Subject: [PATCH 4/6] Fix doctests to match numpy 2.0 output --- .github/workflows/python-app.yml | 1 - doc/gamma.rst | 6 +++--- doc/hci_lines_from_asd.rst | 10 +++++----- doc/off_style.rst | 4 ++-- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index b2693212..9c9f2771 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -38,7 +38,6 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install flake8 ruff pytest pip install -e . if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - name: Lint with flake8 and ruff (only on most recent Python version) diff --git a/doc/gamma.rst b/doc/gamma.rst index 6e8c3a95..e4eab7b0 100644 --- a/doc/gamma.rst +++ b/doc/gamma.rst @@ -380,9 +380,9 @@ me know what you think about it. :options: +NORMALIZE_WHITESPACE chan 3 fwhm=60.0 ± 1.8 (off) - chan 3 fwhm=60.1 ± 1.8 (ljh) - chan 13 fwhm=60.8 ± 2.0 (off) - chan 13 fwhm=61.6 ± 1.9 (ljh) + chan 3 fwhm=59.9 ± 1.8 (ljh) + chan 13 fwhm=60.7 ± 1.9 (off) + chan 13 fwhm=61.7 ± 1.9 (ljh) We also plot one fit from one channel for plain and off style. diff --git a/doc/hci_lines_from_asd.rst b/doc/hci_lines_from_asd.rst index 7954962e..01dc19e2 100644 --- a/doc/hci_lines_from_asd.rst +++ b/doc/hci_lines_from_asd.rst @@ -55,7 +55,7 @@ a commonly injected gas at the NIST EBIT. .. testoutput:: - ['Sn', 'Cu', 'Na', 'As', 'Zn', 'Ne', 'Ge', 'Ga', 'Rb', 'Se'] + [np.str_('Sn'), np.str_('Cu'), np.str_('Na'), np.str_('As'), np.str_('Zn'), np.str_('Ne'), np.str_('Ge'), np.str_('Ga'), np.str_('Rb'), np.str_('Se')] [9, 1, 2, 3, 4, 5, 6, 7, 8, 10] {'1s 2S J=1/2': 0.0, '2p 2P* J=1/2': 1021.5, '2s 2S J=1/2': 1021.5, '2p 2P* J=3/2': 1022.0, '3p 2P* J=1/2': 1210.8, '3s 2S J=1/2': 1210.8} 1021.5 @@ -131,7 +131,7 @@ and then add some of the lower order H- and He-like Ga lines. .. testoutput:: - [SpectralLine: Ne10 2p 2P* J=3/2, 1022.0] - [SpectralLine: O7 1s.2p 1P* J=1, 574.0] - [[SpectralLine: Ga31 2p 2P* J=1/2, 9917.0], [SpectralLine: Ga31 2s 2S J=1/2, 9918.0], [SpectralLine: Ga31 2p 2P* J=3/2, 9960.3], [SpectralLine: Ga31 3p 2P* J=1/2, 11767.7], [SpectralLine: Ga31 3s 2S J=1/2, 11768.0], [SpectralLine: Ga31 3d 2D J=3/2, 11780.5]] - [[SpectralLine: Ga30 1s.2s 3S J=1, 9535.6], [SpectralLine: Ga30 1s.2p 3P* J=0, 9571.8], [SpectralLine: Ga30 1s.2p 3P* J=1, 9574.4], [SpectralLine: Ga30 1s.2s 1S J=0, 9574.6], [SpectralLine: Ga30 1s.2p 3P* J=2, 9607.4], [SpectralLine: Ga30 1s.2p 1P* J=1, 9628.2], [SpectralLine: Ga30 1s.3s 3S J=1, 11304.6]] \ No newline at end of file + [SpectralLine: Ne10 2p 2P* J=3/2, np.float64(1022.0)] + [SpectralLine: O7 1s.2p 1P* J=1, np.float64(574.0)] + [[SpectralLine: Ga31 2p 2P* J=1/2, np.float64(9917.0)], [SpectralLine: Ga31 2s 2S J=1/2, np.float64(9918.0)], [SpectralLine: Ga31 2p 2P* J=3/2, np.float64(9960.3)], [SpectralLine: Ga31 3p 2P* J=1/2, np.float64(11767.7)], [SpectralLine: Ga31 3s 2S J=1/2, np.float64(11768.0)], [SpectralLine: Ga31 3d 2D J=3/2, np.float64(11780.5)]] + [[SpectralLine: Ga30 1s.2s 3S J=1, np.float64(9535.6)], [SpectralLine: Ga30 1s.2p 3P* J=0, np.float64(9571.8)], [SpectralLine: Ga30 1s.2p 3P* J=1, np.float64(9574.4)], [SpectralLine: Ga30 1s.2s 1S J=0, np.float64(9574.6)], [SpectralLine: Ga30 1s.2p 3P* J=2, np.float64(9607.4)], [SpectralLine: Ga30 1s.2p 1P* J=1, np.float64(9628.2)], [SpectralLine: Ga30 1s.3s 3S J=1, np.float64(11304.6)]] diff --git a/doc/off_style.rst b/doc/off_style.rst index 19349b7d..2f96040c 100644 --- a/doc/off_style.rst +++ b/doc/off_style.rst @@ -79,10 +79,10 @@ What is in a record? .. testoutput:: - (1000, 496, 556055239, 1544035816785813000, 10914.036, 22.124851, 10929.741, -10357.827, 10609.358, [-47.434967, -8.839941]) + (1000, 496, 556055239, 1544035816785813000, 10914.036, 22.124851, 10929.741, -10357.827, 10609.358, [-47.434967, -8.839941]) [('recordSamples', ' Date: Mon, 22 Jul 2024 13:55:05 -0500 Subject: [PATCH 5/6] Add test requirements to the dependency list --- pyproject.toml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index b2a559e0..d43f5f3d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,18 +20,27 @@ dependencies = [ "palettable", "pandas", "progress", - "pytest", "scikit-learn", "scipy>=0.19, !=1.11.2", # Bitbucket pipeline tests failed with scipy-1.11.2 but passed with .1 or .3. Weird, but remember it! "statsmodels>0.8", "uncertainties", - "xraydb" + "xraydb", + # The following are for testing only, but until PEP 735 is accepted, there's not an obvious way + # to separate them from run dependencies. So for the time being (July 2024), we'll just plain + # require them for all users. + "pytest", + "sphinx", + "recommonmark", + "ruff", + "flake8", ] + requires-python = ">=3.8" readme = "README.md" license = {text = "MIT"} + [project.urls] Repository = "https://github.com/usnistgov/mass.git" Issues = "https://github.com/usnistgov/mass/issues" From a6166e5c6eddc370df9bf0b95885647d59e4848f Mon Sep 17 00:00:00 2001 From: Joe Fowler Date: Mon, 22 Jul 2024 13:58:50 -0500 Subject: [PATCH 6/6] Fix @ggggggggg's typo and allow numpy 1.x --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f2a55bf0..d43f5f3d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ dependencies = [ "indexedproperty", "lmfit>=0.9.11", "matplotlib>1.5", - "numpy>=1.14,<2.0", + "numpy>=1.14", "packaging", "palettable", "pandas", @@ -64,4 +64,4 @@ mass = [ ] [tool.setuptools_scm] -version_file = "mass/_version.py" \ No newline at end of file +version_file = "mass/_version.py"