Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a942ef6

Browse files
authored
Merge pull request #116 from jgieseler/main
Re-implement background subtraction for spectra and update pytest workflow
2 parents 98c0faf + b344ad4 commit a942ef6

31 files changed

Lines changed: 459 additions & 116 deletions

File tree

.github/workflows/pytest.yml

Lines changed: 92 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,32 @@ on:
1313
# branches: [ "main" ]
1414

1515
jobs:
16-
build:
16+
lint:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@v6
20+
- name: Set up uv
21+
uses: astral-sh/setup-uv@v7
22+
with:
23+
enable-cache: true
24+
- name: Install ruff
25+
run: |
26+
uv venv .venv
27+
source .venv/bin/activate
28+
uv pip install ruff
29+
- name: Lint with ruff
30+
run: |
31+
source .venv/bin/activate
32+
# stop the build if there are Python syntax errors or undefined names
33+
ruff check . --select=E9,F63,F7,F82 --exclude=.venv
34+
# summary first, then run again with exit-zero to show all errors as warnings (and ignore line length)
35+
ruff check . --select=E,F,C90 --ignore=E501 --exclude=.venv --statistics --quiet --exit-zero
36+
# exit-zero treats all errors as warnings. ignore line length (E501)
37+
ruff check . --select=E,F,C90 --ignore=E501 --exclude=.venv --exit-zero
1738
39+
40+
build-linux:
41+
needs: lint
1842
runs-on: ubuntu-latest
1943
strategy:
2044
fail-fast: false
@@ -24,35 +48,86 @@ jobs:
2448

2549
steps:
2650
- uses: actions/checkout@v6
27-
- name: Set up Python ${{ matrix.python-version }}
28-
uses: actions/setup-python@v6
51+
- name: Set up uv
52+
uses: astral-sh/setup-uv@v7
2953
with:
30-
python-version: ${{ matrix.python-version }}
54+
enable-cache: true
55+
- name: Set up Python ${{ matrix.python-version }}
56+
run: uv python install ${{ matrix.python-version }}
3157
- name: Install dependencies
3258
run: |
33-
python -m pip install --upgrade pip
34-
python -m pip install flake8 nbmake pytest pytest-doctestplus pytest-cov pytest-mpl pytest-xdist pytest-split
35-
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
36-
pip freeze > ${{ matrix.python-version }}-${{ matrix.group }}_pip_freeze.txt
37-
- name: Lint with flake8
38-
run: |
39-
# stop the build if there are Python syntax errors or undefined names
40-
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
41-
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
42-
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
59+
uv venv .venv --python ${{ matrix.python-version }}
60+
source .venv/bin/activate
61+
uv pip install nbmake pytest pytest-doctestplus pytest-cov pytest-mpl pytest-xdist pytest-split
62+
if [ -f requirements.txt ]; then uv pip install -r requirements.txt; fi
63+
uv pip freeze > ${{ matrix.python-version }}-${{ matrix.group }}_pip_freeze.txt
4364
- name: Test with pytest
4465
run: |
66+
source .venv/bin/activate
4567
pytest -ra --mpl --mpl-baseline-path=baseline --mpl-baseline-relative --mpl-generate-summary=html --mpl-results-path='/home/runner/work/sep_tools/tests_report/' --cov --cov-report=xml --nbmake -n=auto --nbmake-kernel=python3 --nbmake-timeout=500 --ignore=SEP_Multi-Instrument-Plot.ipynb --ignore=SEP_PyOnset.ipynb --durations=0 --splits 5 --group ${{ matrix.group }} --splitting-algorithm=least_duration
4668
- name: Upload coverage reports to Codecov
4769
uses: codecov/codecov-action@v6
4870
with:
4971
token: ${{ secrets.CODECOV_TOKEN }}
50-
51-
- name: Save pytest-mpl report and pip freeze as artifcat
72+
- name: Save pytest-mpl report and pip freeze as artifact
5273
if: always()
5374
uses: actions/upload-artifact@v7
5475
with:
55-
name: ${{ matrix.python-version }}-${{ matrix.group }}-pytest-mpl-report-artifact
76+
name: ubuntu-${{ matrix.python-version }}-${{ matrix.group }}-pytest-mpl-report-artifact
5677
path: |
5778
${{ matrix.python-version }}-${{ matrix.group }}_pip_freeze.txt
5879
/home/runner/work/sep_tools/tests_report/
80+
81+
82+
build-windows:
83+
needs: lint
84+
# Only run on pull requests to avoid doubling job count on every push
85+
if: github.event_name == 'pull_request'
86+
runs-on: windows-latest
87+
strategy:
88+
fail-fast: false
89+
matrix:
90+
# Only test oldest and newest Python versions on Windows
91+
python-version: ["3.10", "3.14"]
92+
# Only use 2 groups on Windows to limit job count
93+
group: [1, 2]
94+
95+
steps:
96+
- uses: actions/checkout@v6
97+
- name: Set up uv
98+
uses: astral-sh/setup-uv@v7
99+
with:
100+
enable-cache: true
101+
- name: Set up Python ${{ matrix.python-version }}
102+
run: uv python install ${{ matrix.python-version }}
103+
- name: Install dependencies
104+
run: |
105+
uv venv .venv --python ${{ matrix.python-version }}
106+
.venv\Scripts\activate
107+
uv pip install nbmake pytest pytest-doctestplus pytest-cov pytest-mpl pytest-xdist pytest-split
108+
if (Test-Path requirements.txt) { uv pip install -r requirements.txt }
109+
uv pip freeze > ${{ matrix.python-version }}-${{ matrix.group }}_pip_freeze.txt
110+
shell: pwsh
111+
- name: Test with pytest
112+
run: |
113+
.venv\Scripts\activate
114+
pytest -ra --mpl --mpl-baseline-path=baseline --mpl-baseline-relative `
115+
--mpl-generate-summary=html `
116+
--mpl-results-path='D:\a\sep_tools\tests_report\' `
117+
--cov --cov-report=xml --nbmake -n=auto --nbmake-kernel=python3 `
118+
--nbmake-timeout=500 --ignore=SEP_Multi-Instrument-Plot.ipynb `
119+
--ignore=SEP_PyOnset.ipynb --durations=0 `
120+
--splits 2 --group ${{ matrix.group }} --splitting-algorithm=least_duration
121+
shell: pwsh
122+
- name: Upload coverage reports to Codecov
123+
uses: codecov/codecov-action@v6
124+
with:
125+
token: ${{ secrets.CODECOV_TOKEN }}
126+
- name: Save pytest-mpl report and pip freeze as artifact
127+
if: always()
128+
uses: actions/upload-artifact@v7
129+
with:
130+
name: windows-${{ matrix.python-version }}-${{ matrix.group }}-pytest-mpl-report-artifact
131+
path: |
132+
${{ matrix.python-version }}-${{ matrix.group }}_pip_freeze.txt
133+
D:\a\sep_tools\tests_report\

multi_inst_plots/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,10 @@ def __init__(self):
146146
value=tuple(range(0,L1_3DP_P_CH_MAX,1)), rows=10, style=_style)
147147
self.l1_av_sep = w.FloatText(value=10, step=0.1, description="3DP+EPHIN averaging", style=_style)
148148
self.l1_av_erne = w.FloatText(value=10, step=0.1, description="ERNE averaging", style=_style)
149-
149+
150+
self.wind_flux_thres_e = None
151+
self.wind_flux_thres_p = None
152+
150153
self.ster_sc = w.Dropdown(description="STEREO A/B", options=["A", "B"], style=_style)
151154
self.ster_sept_e = w.Checkbox(description="SEPT Electrons", value=True)
152155
self.ster_sept_p = w.Checkbox(description="SEPT Protons", value=True)

multi_inst_plots/l1_tools.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,14 @@ def load_data(options):
260260
if options.mag.value == False:
261261
options.polarity.value = False
262262

263-
wind_flux_thres = None
263+
# Check if thresholds for Wind/3DP data were manually set with values in the options class
264+
# thresholds need to be divided by 1e6 since the plotting is also doing this conversion to plot in MeV instead of eV
265+
if options.wind_flux_thres_e is not None:
266+
print(f"Loading Wind/3DP e data with threshold = {options.wind_flux_thres_e}!")
267+
options.wind_flux_thres_e = options.wind_flux_thres_e / 1e6
268+
if options.wind_flux_thres_p is not None:
269+
print(f"Loading Wind/3DP p data with threshold = {options.wind_flux_thres_p}!")
270+
options.wind_flux_thres_p = options.wind_flux_thres_p / 1e6
264271

265272
dataset_num = (options.l1_wind_e.value or options.l1_wind_p.value) + options.radio.value + options.l1_ephin.value \
266273
+ options.l1_erne.value + (options.mag.value or options.mag_angles.value) \
@@ -275,17 +282,17 @@ def load_data(options):
275282
edic_, meta_e = wind3dp_load(dataset="WI_SFSP_3DP",
276283
startdate=startdate,
277284
enddate=enddate,
278-
resample=0,
285+
resample=None,
279286
multi_index=False,
280287
path=path,
281-
threshold=wind_flux_thres)
288+
threshold=options.wind_flux_thres_e)
282289
pdic_, meta_p = wind3dp_load(dataset="WI_SOSP_3DP",
283290
startdate=startdate,
284291
enddate=enddate,
285-
resample=0,
292+
resample=None,
286293
multi_index=False,
287294
path=path,
288-
threshold=wind_flux_thres)
295+
threshold=options.wind_flux_thres_p)
289296

290297
data["3dp_e"] = edic_
291298
data["3dp_p"] = pdic_

noxfile.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# noxfile.py
2+
import nox
3+
4+
nox.options.sessions = ["lint", "tests"]
5+
nox.options.default_venv_backend = "uv"
6+
7+
PYTHON_VERSIONS = ["3.10", "3.11", "3.12", "3.13", "3.14"]
8+
GROUPS = [1, 2, 3, 4, 5]
9+
SPLITS = 5
10+
11+
DEPENDENCIES = [
12+
"nbmake", "pytest", "pytest-doctestplus", "pytest-cov",
13+
"pytest-mpl", "pytest-xdist", "pytest-split",
14+
]
15+
16+
COMMON_PYTEST_ARGS = [
17+
"-ra",
18+
"--mpl",
19+
"--mpl-baseline-path=baseline",
20+
"--mpl-baseline-relative",
21+
"--mpl-generate-summary=html",
22+
"--nbmake",
23+
"-n=auto",
24+
"--nbmake-kernel=python3",
25+
"--nbmake-timeout=500",
26+
"--ignore=SEP_Multi-Instrument-Plot.ipynb",
27+
"--ignore=SEP_PyOnset.ipynb",
28+
"--durations=0",
29+
"--store-durations",
30+
]
31+
32+
33+
@nox.session(venv_backend="uv")
34+
def lint(session: nox.Session) -> None:
35+
"""Run ruff linting."""
36+
session.install("ruff")
37+
session.run("ruff", "check", ".", "--select=E9,F63,F7,F82",
38+
"--exclude=.venv")
39+
session.run("ruff", "check", ".", "--select=E,F,C90", "--ignore=E501",
40+
"--exclude=.venv", "--statistics", "--quiet", "--exit-zero")
41+
session.run("ruff", "check", ".", "--select=E,F,C90", "--ignore=E501",
42+
"--exclude=.venv", "--exit-zero")
43+
44+
45+
@nox.session(python=PYTHON_VERSIONS, venv_backend="uv")
46+
def tests(session: nox.Session) -> None:
47+
"""Run full test suite locally without splitting."""
48+
session.install(*DEPENDENCIES)
49+
session.install("-r", "requirements.txt")
50+
session.env["MPLBACKEND"] = "Agg"
51+
session.run(
52+
"pytest",
53+
*COMMON_PYTEST_ARGS,
54+
f"--mpl-results-path=tests_report/{session.python}",
55+
f"--cov-report=xml:coverage-{session.python}.xml",
56+
)
57+
58+
59+
@nox.session(python=PYTHON_VERSIONS, venv_backend="uv")
60+
@nox.parametrize("group", GROUPS)
61+
def tests_split(session: nox.Session, group: int) -> None:
62+
"""Mirror CI exactly — use to reproduce a specific CI group failure."""
63+
session.install(*DEPENDENCIES)
64+
session.install("-r", "requirements.txt")
65+
session.env["MPLBACKEND"] = "Agg"
66+
session.run(
67+
"pytest",
68+
*COMMON_PYTEST_ARGS,
69+
f"--mpl-results-path=tests_report/{session.python}-group{group}",
70+
f"--cov-report=xml:coverage-{session.python}-group{group}.xml",
71+
f"--splits={SPLITS}",
72+
f"--group={group}",
73+
"--splitting-algorithm=least_duration",
74+
)

0 commit comments

Comments
 (0)