sed-model 0.3.0__tar.gz → 0.3.2__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.
Files changed (74) hide show
  1. {sed_model-0.3.0 → sed_model-0.3.2}/.github/workflows/build.yml +31 -28
  2. {sed_model-0.3.0 → sed_model-0.3.2}/.github/workflows/docs.yml +6 -6
  3. {sed_model-0.3.0 → sed_model-0.3.2}/CHANGELOG.md +22 -0
  4. {sed_model-0.3.0 → sed_model-0.3.2}/CITATION.cff +1 -1
  5. {sed_model-0.3.0 → sed_model-0.3.2}/PKG-INFO +4 -4
  6. {sed_model-0.3.0 → sed_model-0.3.2}/README.md +3 -3
  7. sed_model-0.3.2/docs/favicon.png +0 -0
  8. {sed_model-0.3.0 → sed_model-0.3.2}/docs/index.md +1 -1
  9. {sed_model-0.3.0 → sed_model-0.3.2}/docs/testing.md +5 -5
  10. {sed_model-0.3.0 → sed_model-0.3.2}/meson.build +1 -1
  11. {sed_model-0.3.0 → sed_model-0.3.2}/mkdocs.yml +1 -1
  12. {sed_model-0.3.0 → sed_model-0.3.2}/sed_model/filters.py +4 -1
  13. sed_model-0.3.2/tests/_data_paths.py +29 -0
  14. {sed_model-0.3.0 → sed_model-0.3.2}/tests/test_forward.py +1 -12
  15. {sed_model-0.3.0 → sed_model-0.3.2}/tests/test_inverse.py +1 -12
  16. {sed_model-0.3.0 → sed_model-0.3.2}/tests/test_kernels.py +23 -0
  17. sed_model-0.3.0/fortran/private/cc_api.f90 +0 -271
  18. {sed_model-0.3.0 → sed_model-0.3.2}/.f2py_f2cmap +0 -0
  19. {sed_model-0.3.0 → sed_model-0.3.2}/.gitattributes +0 -0
  20. {sed_model-0.3.0 → sed_model-0.3.2}/.gitignore +0 -0
  21. {sed_model-0.3.0 → sed_model-0.3.2}/CODE_OF_CONDUCT.md +0 -0
  22. {sed_model-0.3.0 → sed_model-0.3.2}/CONTRIBUTING.md +0 -0
  23. {sed_model-0.3.0 → sed_model-0.3.2}/LICENSE +0 -0
  24. {sed_model-0.3.0 → sed_model-0.3.2}/MIGRATION.md +0 -0
  25. {sed_model-0.3.0 → sed_model-0.3.2}/Makefile +0 -0
  26. {sed_model-0.3.0 → sed_model-0.3.2}/SECURITY.md +0 -0
  27. {sed_model-0.3.0 → sed_model-0.3.2}/demos/api_usage.py +0 -0
  28. {sed_model-0.3.0 → sed_model-0.3.2}/demos/demo_forward.py +0 -0
  29. {sed_model-0.3.0 → sed_model-0.3.2}/demos/demo_inverse.py +0 -0
  30. {sed_model-0.3.0 → sed_model-0.3.2}/demos/demo_param_modes.py +0 -0
  31. {sed_model-0.3.0 → sed_model-0.3.2}/demos/extinction_prescription_comparison.py +0 -0
  32. {sed_model-0.3.0 → sed_model-0.3.2}/demos/plot_utils.py +0 -0
  33. {sed_model-0.3.0 → sed_model-0.3.2}/demos/sed_playground_demo.py +0 -0
  34. {sed_model-0.3.0 → sed_model-0.3.2}/demos/simbad_query_inverse.py +0 -0
  35. {sed_model-0.3.0 → sed_model-0.3.2}/demos/single_test.py +0 -0
  36. {sed_model-0.3.0 → sed_model-0.3.2}/docs/SED_Model_logo.jpeg +0 -0
  37. {sed_model-0.3.0 → sed_model-0.3.2}/docs/api.md +0 -0
  38. {sed_model-0.3.0 → sed_model-0.3.2}/docs/demos/api-usage.md +0 -0
  39. {sed_model-0.3.0 → sed_model-0.3.2}/docs/demos/extinction-comparison.md +0 -0
  40. {sed_model-0.3.0 → sed_model-0.3.2}/docs/demos/forward.md +0 -0
  41. {sed_model-0.3.0 → sed_model-0.3.2}/docs/demos/index.md +0 -0
  42. {sed_model-0.3.0 → sed_model-0.3.2}/docs/demos/inverse.md +0 -0
  43. {sed_model-0.3.0 → sed_model-0.3.2}/docs/demos/param-modes.md +0 -0
  44. {sed_model-0.3.0 → sed_model-0.3.2}/docs/demos/playground.md +0 -0
  45. {sed_model-0.3.0 → sed_model-0.3.2}/docs/guide/extinction.md +0 -0
  46. {sed_model-0.3.0 → sed_model-0.3.2}/docs/guide/forward.md +0 -0
  47. {sed_model-0.3.0 → sed_model-0.3.2}/docs/guide/grids-and-filters.md +0 -0
  48. {sed_model-0.3.0 → sed_model-0.3.2}/docs/guide/inverse.md +0 -0
  49. {sed_model-0.3.0 → sed_model-0.3.2}/docs/guide/parameters.md +0 -0
  50. {sed_model-0.3.0 → sed_model-0.3.2}/docs/guide/results-io.md +0 -0
  51. {sed_model-0.3.0 → sed_model-0.3.2}/docs/installation.md +0 -0
  52. {sed_model-0.3.0 → sed_model-0.3.2}/docs/quickstart.md +0 -0
  53. {sed_model-0.3.0 → sed_model-0.3.2}/fortran/cc_api.f90 +0 -0
  54. {sed_model-0.3.0 → sed_model-0.3.2}/fortran/private/bolometric.f90 +0 -0
  55. {sed_model-0.3.0 → sed_model-0.3.2}/fortran/private/colors_utils.f90 +0 -0
  56. {sed_model-0.3.0 → sed_model-0.3.2}/fortran/private/hermite_interp.f90 +0 -0
  57. {sed_model-0.3.0 → sed_model-0.3.2}/fortran/private/hermite_interp_bounded.f90 +0 -0
  58. {sed_model-0.3.0 → sed_model-0.3.2}/fortran/private/linear_interp.f90 +0 -0
  59. {sed_model-0.3.0 → sed_model-0.3.2}/fortran/private/synthetic.f90 +0 -0
  60. {sed_model-0.3.0 → sed_model-0.3.2}/fortran/public/colors_def.f90 +0 -0
  61. {sed_model-0.3.0 → sed_model-0.3.2}/fortran/public/colors_lib.f90 +0 -0
  62. {sed_model-0.3.0 → sed_model-0.3.2}/meson_options.txt +0 -0
  63. {sed_model-0.3.0 → sed_model-0.3.2}/pyproject.toml +0 -0
  64. {sed_model-0.3.0 → sed_model-0.3.2}/sed_model/__init__.py +0 -0
  65. {sed_model-0.3.0 → sed_model-0.3.2}/sed_model/_cc_ext.py +0 -0
  66. {sed_model-0.3.0 → sed_model-0.3.2}/sed_model/forward.py +0 -0
  67. {sed_model-0.3.0 → sed_model-0.3.2}/sed_model/grid.py +0 -0
  68. {sed_model-0.3.0 → sed_model-0.3.2}/sed_model/inverse.py +0 -0
  69. {sed_model-0.3.0 → sed_model-0.3.2}/sed_model/io.py +0 -0
  70. {sed_model-0.3.0 → sed_model-0.3.2}/sed_model/params.py +0 -0
  71. {sed_model-0.3.0 → sed_model-0.3.2}/sed_model/sed_extinction.py +0 -0
  72. {sed_model-0.3.0 → sed_model-0.3.2}/tests/fortran/smoke.f90 +0 -0
  73. {sed_model-0.3.0 → sed_model-0.3.2}/tools/ci/build_fortran_lib.sh +0 -0
  74. {sed_model-0.3.0 → sed_model-0.3.2}/tools/post_install_fortran.py +0 -0
@@ -31,16 +31,16 @@ jobs:
31
31
  # ---------------------------------------------------------------------------
32
32
  sdist:
33
33
  name: Source distribution
34
- runs-on: ubuntu-latest
34
+ runs-on: ubuntu-24.04
35
35
  outputs:
36
36
  version: ${{ steps.version.outputs.version }}
37
37
  is_new: ${{ steps.pypi.outputs.is_new }}
38
38
  steps:
39
- - uses: actions/checkout@v4
39
+ - uses: actions/checkout@v7
40
40
  with:
41
41
  fetch-depth: 0 # meson dist builds from git
42
42
 
43
- - uses: actions/setup-python@v5
43
+ - uses: actions/setup-python@v7
44
44
  with:
45
45
  python-version: "3.12"
46
46
 
@@ -75,7 +75,7 @@ jobs:
75
75
  python -c "import sed_model, sed_model.cc_api"
76
76
  python -m pytest tests/test_kernels.py -p no:cacheprovider
77
77
 
78
- - uses: actions/upload-artifact@v4
78
+ - uses: actions/upload-artifact@v7
79
79
  with:
80
80
  name: sdist
81
81
  path: dist/*.tar.gz
@@ -86,13 +86,13 @@ jobs:
86
86
  # ---------------------------------------------------------------------------
87
87
  pure_wheel:
88
88
  name: Pure-Python wheel
89
- runs-on: ubuntu-latest
89
+ runs-on: ubuntu-24.04
90
90
  steps:
91
- - uses: actions/checkout@v4
91
+ - uses: actions/checkout@v7
92
92
  with:
93
93
  fetch-depth: 0
94
94
 
95
- - uses: actions/setup-python@v5
95
+ - uses: actions/setup-python@v7
96
96
  with:
97
97
  python-version: "3.12"
98
98
 
@@ -112,7 +112,7 @@ jobs:
112
112
  print("sed_model", sed_model.__version__, "- pure wheel OK")
113
113
  PY
114
114
 
115
- - uses: actions/upload-artifact@v4
115
+ - uses: actions/upload-artifact@v7
116
116
  with:
117
117
  name: pure-wheel
118
118
  path: dist/*.whl
@@ -129,7 +129,7 @@ jobs:
129
129
  fail-fast: false
130
130
  matrix:
131
131
  include:
132
- - { os: ubuntu-latest, label: linux-x86_64 }
132
+ - { os: ubuntu-24.04, label: linux-x86_64 }
133
133
  - { os: ubuntu-24.04-arm, label: linux-aarch64 }
134
134
  # The Fortran runtime is linked statically on macOS (see meson.build),
135
135
  # so the wheel's minimum macOS is this target, not whatever the
@@ -138,11 +138,11 @@ jobs:
138
138
  - { os: macos-14, label: macos-arm64, macos_target: "14.0" }
139
139
  - { os: macos-15-intel, label: macos-x86_64, macos_target: "15.0" }
140
140
  steps:
141
- - uses: actions/checkout@v4
141
+ - uses: actions/checkout@v7
142
142
  with:
143
143
  fetch-depth: 0
144
144
 
145
- - uses: actions/setup-python@v5
145
+ - uses: actions/setup-python@v7
146
146
  with:
147
147
  python-version: "3.12"
148
148
 
@@ -157,7 +157,7 @@ jobs:
157
157
  env:
158
158
  CIBW_ENVIRONMENT_MACOS: MACOSX_DEPLOYMENT_TARGET=${{ matrix.macos_target }}
159
159
 
160
- - uses: actions/upload-artifact@v4
160
+ - uses: actions/upload-artifact@v7
161
161
  with:
162
162
  name: wheels-${{ matrix.label }}
163
163
  path: wheelhouse/*.whl
@@ -173,12 +173,12 @@ jobs:
173
173
  fail-fast: false
174
174
  matrix:
175
175
  include:
176
- - { os: ubuntu-latest, label: linux-x86_64, image: quay.io/pypa/manylinux_2_28_x86_64 }
176
+ - { os: ubuntu-24.04, label: linux-x86_64, image: quay.io/pypa/manylinux_2_28_x86_64 }
177
177
  - { os: ubuntu-24.04-arm, label: linux-aarch64, image: quay.io/pypa/manylinux_2_28_aarch64 }
178
178
  - { os: macos-14, label: macos-arm64, macos_target: "14.0" }
179
179
  - { os: macos-15-intel, label: macos-x86_64, macos_target: "15.0" }
180
180
  steps:
181
- - uses: actions/checkout@v4
181
+ - uses: actions/checkout@v7
182
182
  with:
183
183
  fetch-depth: 0
184
184
 
@@ -201,7 +201,7 @@ jobs:
201
201
  version=$(git describe --tags --always)
202
202
  tar -C stage -czf "sed_model-fortran-${version}-${{ matrix.label }}.tar.gz" sed_model-fortran
203
203
 
204
- - uses: actions/upload-artifact@v4
204
+ - uses: actions/upload-artifact@v7
205
205
  with:
206
206
  name: fortran-${{ matrix.label }}
207
207
  path: sed_model-fortran-*.tar.gz
@@ -226,7 +226,7 @@ jobs:
226
226
  && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v'))
227
227
  && needs.sdist.outputs.is_new == 'true'
228
228
  needs: [sdist, pure_wheel, wheels, fortran_lib]
229
- runs-on: ubuntu-latest
229
+ runs-on: ubuntu-24.04
230
230
  environment: pypi
231
231
  concurrency:
232
232
  group: publish
@@ -234,11 +234,11 @@ jobs:
234
234
  permissions:
235
235
  id-token: write # trusted publishing
236
236
  steps:
237
- - uses: actions/download-artifact@v4
237
+ - uses: actions/download-artifact@v8
238
238
  with:
239
239
  path: artifacts
240
240
 
241
- - uses: actions/setup-python@v5
241
+ - uses: actions/setup-python@v7
242
242
  with:
243
243
  python-version: "3.12"
244
244
 
@@ -292,12 +292,12 @@ jobs:
292
292
  strategy:
293
293
  fail-fast: false
294
294
  matrix:
295
- os: [ubuntu-latest, ubuntu-24.04-arm, macos-14, macos-15-intel]
295
+ os: [ubuntu-24.04, ubuntu-24.04-arm, macos-14, macos-15-intel]
296
296
  python: ["3.10", "3.14"]
297
297
  steps:
298
- - uses: actions/checkout@v4
298
+ - uses: actions/checkout@v7
299
299
 
300
- - uses: actions/setup-python@v5
300
+ - uses: actions/setup-python@v7
301
301
  with:
302
302
  python-version: ${{ matrix.python }}
303
303
 
@@ -328,11 +328,11 @@ jobs:
328
328
  release:
329
329
  name: GitHub release
330
330
  needs: [sdist, verify_pypi]
331
- runs-on: ubuntu-latest
331
+ runs-on: ubuntu-24.04
332
332
  permissions:
333
333
  contents: write
334
334
  steps:
335
- - uses: actions/download-artifact@v4
335
+ - uses: actions/download-artifact@v8
336
336
  with:
337
337
  path: artifacts
338
338
 
@@ -345,11 +345,14 @@ jobs:
345
345
  fi
346
346
  # An existing tag must already point at the commit that was just built;
347
347
  # otherwise the release would attach these artifacts to different code.
348
- tag_sha=$(gh api "repos/$GITHUB_REPOSITORY/commits/$tag" --jq .sha 2>/dev/null || true)
349
- if [ -n "$tag_sha" ] && [ "$tag_sha" != "$GITHUB_SHA" ]; then
350
- echo "::error::Tag $tag already exists at $tag_sha, but this build is $GITHUB_SHA." \
351
- "Move or delete the tag (or bump the version) and re-run."
352
- exit 1
348
+ # gh prints the API error body to stdout on failure, so test the exit
349
+ # status rather than the output: a missing tag means nothing to compare.
350
+ if tag_sha=$(gh api "repos/$GITHUB_REPOSITORY/commits/$tag" --jq .sha 2>/dev/null); then
351
+ if [ "$tag_sha" != "$GITHUB_SHA" ]; then
352
+ echo "::error::Tag $tag already exists at $tag_sha, but this build is $GITHUB_SHA." \
353
+ "Move or delete the tag (or bump the version) and re-run."
354
+ exit 1
355
+ fi
353
356
  fi
354
357
  gh release create "$tag" --repo "$GITHUB_REPOSITORY" --target "$GITHUB_SHA" \
355
358
  --title "$tag" --generate-notes \
@@ -16,11 +16,11 @@ concurrency:
16
16
 
17
17
  jobs:
18
18
  build:
19
- runs-on: ubuntu-latest
19
+ runs-on: ubuntu-24.04
20
20
  steps:
21
- - uses: actions/checkout@v4
21
+ - uses: actions/checkout@v7
22
22
 
23
- - uses: actions/setup-python@v5
23
+ - uses: actions/setup-python@v7
24
24
  with:
25
25
  python-version: "3.11"
26
26
 
@@ -34,16 +34,16 @@ jobs:
34
34
  - name: Build site
35
35
  run: mkdocs build --strict
36
36
 
37
- - uses: actions/upload-pages-artifact@v3
37
+ - uses: actions/upload-pages-artifact@v5
38
38
  with:
39
39
  path: site
40
40
 
41
41
  deploy:
42
42
  needs: build
43
- runs-on: ubuntu-latest
43
+ runs-on: ubuntu-24.04
44
44
  environment:
45
45
  name: github-pages
46
46
  url: ${{ steps.deployment.outputs.page_url }}
47
47
  steps:
48
48
  - id: deployment
49
- uses: actions/deploy-pages@v4
49
+ uses: actions/deploy-pages@v5
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.2] — 2026-10-25
4
+
5
+ - **Filter files from SED_Tools 0.4.0 load again.** SED_Tools 0.4.0 puts its
6
+ metadata on the column row (`Wavelength,Transmission,FilterID=...;DetectorType=...`);
7
+ the loader now reads only the first two columns instead of failing with
8
+ `expected two-column file`. Required for SED_Tools >= 0.4.0 filter files.
9
+ The metadata itself is not read yet.
10
+ - Tests find their data in `~/.sed_tools/data` as well as the older locations
11
+ and `$MESA_DIR/data/colors_data`.
12
+
13
+ ## [0.3.1] — 2026-10-23
14
+
15
+ Packaging and CI only; no numerical changes.
16
+
17
+ - README logos use absolute URLs, so they render on the PyPI project page.
18
+ - Square `docs/favicon.png` for the documentation site.
19
+ - Release job: the tag guard no longer misreads the API error body as a commit
20
+ when the tag does not yet exist.
21
+ - CI: actions moved to current majors (Node 24), and runners pinned to
22
+ `ubuntu-24.04` instead of `ubuntu-latest`.
23
+ - Removed the legacy, uncompiled `fortran/private/cc_api.f90`.
24
+
3
25
  ## [0.3.0] — 2026-10-21
4
26
 
5
27
  Fortran kernels synchronised with the current MESA `colors` module, and
@@ -7,7 +7,7 @@ authors:
7
7
  - family-names: "Miller"
8
8
  given-names: "Niall"
9
9
  email: "niall.j.miller@gmail.com"
10
- version: "0.3.0"
10
+ version: "0.3.2"
11
11
  repository-code: "https://github.com/nialljmiller/SED_Model"
12
12
  url: "https://nialljmiller.github.io/SED_Model/"
13
13
  license: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sed-model
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: Forward and inverse stellar photometry from SED grids.
5
5
  Keywords: astronomy,astrophysics,stellar astronomy,synthetic photometry,spectral energy distributions,sed,stellar parameters,bayesian inference,mcmc
6
6
  Author-Email: Niall Miller <niall.j.miller@gmail.com>
@@ -27,7 +27,7 @@ Requires-Dist: matplotlib; extra == "demo"
27
27
  Description-Content-Type: text/markdown
28
28
 
29
29
  <p align="center">
30
- <img src="docs/SED_Model_logo.jpeg" alt="SED_Model logo" width="600"/>
30
+ <img src="https://raw.githubusercontent.com/nialljmiller/SED_Model/main/docs/SED_Model_logo.jpeg" alt="SED_Model logo" width="600"/>
31
31
  </p>
32
32
 
33
33
  <h1 align="center">SED_Model</h1>
@@ -36,7 +36,7 @@ Description-Content-Type: text/markdown
36
36
 
37
37
  SED_Model is a Python package for computing observer-ready synthetic spectral energy distributions (SEDs) and broadband magnitudes from stellar atmosphere grids, and for recovering stellar parameters from observed photometry via Bayesian MCMC inference. It is designed to work directly downstream of `SED_Tools` and as a standalone drop-in for workflows that use MESA-style atmosphere grids and filter transmission curves.
38
38
 
39
- Version: `0.3.0`
39
+ Version: `0.3.2`
40
40
 
41
41
  **Documentation:** https://nialljmiller.github.io/SED_Model/
42
42
 
@@ -461,5 +461,5 @@ SED_Model uses a mixed-license structure. The Python source code, documentation,
461
461
  ---
462
462
 
463
463
  <p align="center">
464
- <img src="docs/SED_Model_Logo_full.png" alt="SED_Model: The Pythonic Inside Story of MCMC-Based Stellar Parameter Inference from Photometric Grids, by Niall Miller" width="360"/>
464
+ <img src="https://raw.githubusercontent.com/nialljmiller/SED_Model/main/docs/SED_Model_Logo_full.png" alt="SED_Model: The Pythonic Inside Story of MCMC-Based Stellar Parameter Inference from Photometric Grids, by Niall Miller" width="360"/>
465
465
  </p>
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src="docs/SED_Model_logo.jpeg" alt="SED_Model logo" width="600"/>
2
+ <img src="https://raw.githubusercontent.com/nialljmiller/SED_Model/main/docs/SED_Model_logo.jpeg" alt="SED_Model logo" width="600"/>
3
3
  </p>
4
4
 
5
5
  <h1 align="center">SED_Model</h1>
@@ -8,7 +8,7 @@
8
8
 
9
9
  SED_Model is a Python package for computing observer-ready synthetic spectral energy distributions (SEDs) and broadband magnitudes from stellar atmosphere grids, and for recovering stellar parameters from observed photometry via Bayesian MCMC inference. It is designed to work directly downstream of `SED_Tools` and as a standalone drop-in for workflows that use MESA-style atmosphere grids and filter transmission curves.
10
10
 
11
- Version: `0.3.0`
11
+ Version: `0.3.2`
12
12
 
13
13
  **Documentation:** https://nialljmiller.github.io/SED_Model/
14
14
 
@@ -433,5 +433,5 @@ SED_Model uses a mixed-license structure. The Python source code, documentation,
433
433
  ---
434
434
 
435
435
  <p align="center">
436
- <img src="docs/SED_Model_Logo_full.png" alt="SED_Model: The Pythonic Inside Story of MCMC-Based Stellar Parameter Inference from Photometric Grids, by Niall Miller" width="360"/>
436
+ <img src="https://raw.githubusercontent.com/nialljmiller/SED_Model/main/docs/SED_Model_Logo_full.png" alt="SED_Model: The Pythonic Inside Story of MCMC-Based Stellar Parameter Inference from Photometric Grids, by Niall Miller" width="360"/>
437
437
  </p>
Binary file
@@ -8,7 +8,7 @@
8
8
 
9
9
  SED_Model is a Python package for computing observer-ready synthetic spectral energy distributions (SEDs) and broadband magnitudes from stellar atmosphere grids, and for recovering stellar parameters from observed photometry via Bayesian MCMC inference. It works directly downstream of [SED_Tools](https://github.com/nialljmiller/SED_Tools) and as a standalone drop-in for workflows that use MESA-style atmosphere grids and filter transmission curves.
10
10
 
11
- Current version: **0.3.0** ([PyPI](https://pypi.org/project/sed-model/))
11
+ Current version: **0.3.2** ([PyPI](https://pypi.org/project/sed-model/))
12
12
 
13
13
  ## Two paired models, one parameter language
14
14
 
@@ -9,13 +9,13 @@ Both suites skip gracefully — with an explanatory reason — when the Fortran
9
9
 
10
10
  ## Data locations
11
11
 
12
- The tests look for SED_Tools data products at `~/SED_Tools/data/...` by default, overridable via environment variables:
12
+ The tests look for SED_Tools data products in `~/.sed_tools/data`, then `~/SED_Tools/data`, then `$MESA_DIR/data/colors_data`, using the first location that exists. Each path can be overridden with an environment variable:
13
13
 
14
- | Variable | Default |
14
+ | Variable | Path under the data root |
15
15
  |---|---|
16
- | `CC_KURUCZ_DIR` | `~/SED_Tools/data/stellar_models/Kurucz2003all` |
17
- | `CC_JOHNSON_DIR` | `~/SED_Tools/data/filters/Generic/Johnson` |
18
- | `CC_VEGA_SED` | `~/SED_Tools/data/stellar_models/vega_flam.csv` |
16
+ | `CC_KURUCZ_DIR` | `stellar_models/Kurucz2003all` |
17
+ | `CC_JOHNSON_DIR` | `filters/Generic/Johnson` |
18
+ | `CC_VEGA_SED` | `stellar_models/vega_flam.csv` |
19
19
 
20
20
  ## Forward model: validated against MESA
21
21
 
@@ -2,7 +2,7 @@
2
2
  # and for the others the checks below give a readable error if one is missing.
3
3
  project(
4
4
  'sed_model',
5
- version: '0.3.0',
5
+ version: '0.3.2',
6
6
  meson_version: '>=1.1.0',
7
7
  )
8
8
 
@@ -8,7 +8,7 @@ edit_uri: edit/main/docs/
8
8
  theme:
9
9
  name: material
10
10
  logo: SED_Model_logo.jpeg
11
- favicon: SED_Model_logo.jpeg
11
+ favicon: favicon.png
12
12
  palette:
13
13
  - media: "(prefers-color-scheme: light)"
14
14
  scheme: default
@@ -227,8 +227,11 @@ def _load_filter_dat(path: Path) -> tuple[np.ndarray, np.ndarray]:
227
227
  raise FileNotFoundError(f"Filter file not found: {path}")
228
228
 
229
229
  delimiter = _sniff_delimiter(path)
230
+ # usecols: SED_Tools >= 0.4.0 appends a metadata field to the column row
231
+ # (``Wavelength,Transmission,FilterID=...;DetectorType=...``), which would
232
+ # otherwise make genfromtxt expect three columns.
230
233
  data = np.genfromtxt(path, comments="#", delimiter=delimiter,
231
- invalid_raise=False)
234
+ usecols=(0, 1), invalid_raise=False)
232
235
 
233
236
  if data.ndim == 2:
234
237
  mask = np.isfinite(data[:, 0]) & np.isfinite(data[:, 1])
@@ -0,0 +1,29 @@
1
+ """Locations of the SED_Tools data products the tests use.
2
+
3
+ Each path can be set with an environment variable; otherwise the first
4
+ existing candidate is used (SED_Tools' own cache, the older ``~/SED_Tools``
5
+ layout, then the data shipped with a MESA checkout).
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import os
11
+
12
+ _ROOTS = [
13
+ os.path.expanduser("~/.sed_tools/data"),
14
+ os.path.expanduser("~/SED_Tools/data"),
15
+ ]
16
+ if os.environ.get("MESA_DIR"):
17
+ _ROOTS.append(os.path.join(os.environ["MESA_DIR"], "data", "colors_data"))
18
+
19
+
20
+ def _find(env: str, *parts: str) -> str:
21
+ if os.environ.get(env):
22
+ return os.environ[env]
23
+ candidates = [os.path.join(root, *parts) for root in _ROOTS]
24
+ return next((c for c in candidates if os.path.exists(c)), candidates[0])
25
+
26
+
27
+ KURUCZ_DIR = _find("CC_KURUCZ_DIR", "stellar_models", "Kurucz2003all")
28
+ JOHNSON_DIR = _find("CC_JOHNSON_DIR", "filters", "Generic", "Johnson")
29
+ VEGA_SED = _find("CC_VEGA_SED", "stellar_models", "vega_flam.csv")
@@ -33,18 +33,7 @@ import numpy as np
33
33
  # ---------------------------------------------------------------------------
34
34
  # Path configuration
35
35
  # ---------------------------------------------------------------------------
36
- KURUCZ_DIR = os.environ.get(
37
- "CC_KURUCZ_DIR",
38
- os.path.expanduser("~/SED_Tools/data/stellar_models/Kurucz2003all"),
39
- )
40
- JOHNSON_DIR = os.environ.get(
41
- "CC_JOHNSON_DIR",
42
- os.path.expanduser("~/SED_Tools/data/filters/Generic/Johnson"),
43
- )
44
- VEGA_SED = os.environ.get(
45
- "CC_VEGA_SED",
46
- os.path.expanduser("~/SED_Tools/data/stellar_models/vega_flam.csv"),
47
- )
36
+ from _data_paths import KURUCZ_DIR, JOHNSON_DIR, VEGA_SED
48
37
 
49
38
  R_SUN = 6.957e10
50
39
  D_10PC = 3.0857e19
@@ -34,18 +34,7 @@ import pytest
34
34
  # ---------------------------------------------------------------------------
35
35
  # Paths
36
36
  # ---------------------------------------------------------------------------
37
- KURUCZ_DIR = os.environ.get(
38
- "CC_KURUCZ_DIR",
39
- os.path.expanduser("~/SED_Tools/data/stellar_models/Kurucz2003all"),
40
- )
41
- JOHNSON_DIR = os.environ.get(
42
- "CC_JOHNSON_DIR",
43
- os.path.expanduser("~/SED_Tools/data/filters/Generic/Johnson"),
44
- )
45
- VEGA_SED = os.environ.get(
46
- "CC_VEGA_SED",
47
- os.path.expanduser("~/SED_Tools/data/stellar_models/vega_flam.csv"),
48
- )
37
+ from _data_paths import KURUCZ_DIR, JOHNSON_DIR, VEGA_SED
49
38
 
50
39
  R_SUN = 6.957e10
51
40
  D_10PC = 3.0857e19
@@ -142,3 +142,26 @@ def test_linear_interp_handles_nan_cube_node():
142
142
  flux, ierr = cc.interp_sed_linear(0.4, 0.0, 0.0, x, one, one, cube)
143
143
  assert np.all(np.isfinite(flux))
144
144
  assert ierr >= 1
145
+
146
+
147
+ def test_filter_header_row_with_metadata_field(tmp_path):
148
+ """SED_Tools >= 0.4.0 appends ``;``-separated metadata as a third comma
149
+ field of the column row. The loader reads only the two data columns, for
150
+ that layout, the bare row, and the older leading ``# Key: value`` lines."""
151
+ from sed_model.filters import load_filters
152
+
153
+ rows = "3200.0,2.4e-08\n3300.0,0.5\n3400.0,0.9\n3500.0,0.0\n"
154
+ layouts = {
155
+ "bare": "Wavelength,Transmission\n" + rows,
156
+ "meta": ("Wavelength,Transmission,FilterID=GAIA/GAIA3.G;DetectorType=photon;"
157
+ "DetectorTypeSource=svo-curve-match;WavelengthUnit=Angstrom;"
158
+ "Components=filter+qe+instrument\n" + rows),
159
+ "comments": "# FilterID: GAIA/GAIA3.G\n# DetectorType: photon\nWavelength,Transmission\n" + rows,
160
+ }
161
+ waves = {}
162
+ for name, text in layouts.items():
163
+ (tmp_path / f"{name}.dat").write_text(text)
164
+ (f,) = load_filters([tmp_path / f"{name}.dat"])
165
+ waves[name] = (f.wavelengths.tolist(), f.transmission.tolist())
166
+ assert waves["meta"] == waves["bare"] == waves["comments"]
167
+ assert waves["meta"][0] == [3200.0, 3300.0, 3400.0, 3500.0]
@@ -1,271 +0,0 @@
1
- ! ***********************************************************************
2
- ! fortran/private/cc_api.f90 — NOT COMPILED
3
- !
4
- ! This file is a legacy reference copy that routes through colors_lib.f90
5
- ! (the public aggregation module). It is NOT included in the Makefile or
6
- ! meson.build build sources and is therefore never compiled.
7
- !
8
- ! The file that IS compiled is fortran/cc_api.f90 (one level up), which
9
- ! uses the private kernels directly. That workaround exists because the
10
- ! pinned f2py cannot wrap a module that only re-exports procedures from
11
- ! other modules (see fortran/cc_api.f90 header and MIGRATION.md).
12
- !
13
- ! This copy is kept for reference only. All changes to the compiled API
14
- ! must go into fortran/cc_api.f90, NOT this file.
15
- ! ***********************************************************************
16
-
17
- module cc_api
18
- use colors_lib, only: dp, &
19
- hermite_interp_vector, &
20
- trilinear_interp_vector, &
21
- lib_dilute_flux => dilute_flux, &
22
- lib_trapz => trapezoidal_integration, &
23
- lib_simpson => simpson_integration, &
24
- lib_interp_filter => interp_filter_onto_sed, &
25
- lib_synthetic_flux => calculate_synthetic_flux, &
26
- lib_magnitude => magnitude, &
27
- lib_bol_phot => calculate_bolometric_phot, &
28
- lib_vega_zp => compute_vega_zero_point, &
29
- lib_ab_zp => compute_ab_zero_point, &
30
- lib_st_zp => compute_st_zero_point
31
-
32
- implicit none
33
- private
34
-
35
- public :: interp_sed_hermite
36
- public :: interp_sed_linear
37
- public :: dilute_flux
38
- public :: synthetic_magnitude
39
- public :: bolometric
40
- public :: vega_zero_point
41
- public :: ab_zero_point
42
- public :: st_zero_point
43
- public :: trapz
44
- public :: simpson
45
-
46
- contains
47
-
48
- ! -------------------------------------------------------------------------
49
- ! interp_sed_hermite
50
- !
51
- ! Interpolate a full SED at (teff, logg, meta) using cubic Hermite
52
- ! tensor interpolation on the preloaded flux cube. Forwards straight
53
- ! to hermite_interp_vector in fortran/private/hermite_interp.f90.
54
- ! -------------------------------------------------------------------------
55
- subroutine interp_sed_hermite(teff, logg, meta, &
56
- teff_grid, nt, &
57
- logg_grid, nl, &
58
- meta_grid, nm, &
59
- flux_cube, nw, &
60
- result_flux, ierr)
61
- !f2py intent(in) :: teff, logg, meta
62
- !f2py intent(in) :: teff_grid, logg_grid, meta_grid
63
- !f2py intent(in) :: nt, nl, nm, nw
64
- !f2py intent(in) :: flux_cube
65
- !f2py intent(out) :: result_flux
66
- !f2py intent(out) :: ierr
67
- real(dp), intent(in) :: teff, logg, meta
68
- integer, intent(in) :: nt, nl, nm, nw
69
- real(dp), intent(in) :: teff_grid(nt), logg_grid(nl), meta_grid(nm)
70
- real(dp), intent(in) :: flux_cube(nt, nl, nm, nw)
71
- real(dp), intent(out) :: result_flux(nw)
72
- integer, intent(out) :: ierr
73
-
74
- call hermite_interp_vector(teff, logg, meta, &
75
- teff_grid, logg_grid, meta_grid, &
76
- flux_cube, nw, result_flux, ierr)
77
- end subroutine interp_sed_hermite
78
-
79
-
80
- ! -------------------------------------------------------------------------
81
- ! interp_sed_linear
82
- !
83
- ! Same interface as interp_sed_hermite but using trilinear interpolation.
84
- ! -------------------------------------------------------------------------
85
- subroutine interp_sed_linear(teff, logg, meta, &
86
- teff_grid, nt, &
87
- logg_grid, nl, &
88
- meta_grid, nm, &
89
- flux_cube, nw, &
90
- result_flux, ierr)
91
- !f2py intent(in) :: teff, logg, meta
92
- !f2py intent(in) :: teff_grid, logg_grid, meta_grid
93
- !f2py intent(in) :: nt, nl, nm, nw
94
- !f2py intent(in) :: flux_cube
95
- !f2py intent(out) :: result_flux
96
- !f2py intent(out) :: ierr
97
- real(dp), intent(in) :: teff, logg, meta
98
- integer, intent(in) :: nt, nl, nm, nw
99
- real(dp), intent(in) :: teff_grid(nt), logg_grid(nl), meta_grid(nm)
100
- real(dp), intent(in) :: flux_cube(nt, nl, nm, nw)
101
- real(dp), intent(out) :: result_flux(nw)
102
- integer, intent(out) :: ierr
103
-
104
- call trilinear_interp_vector(teff, logg, meta, &
105
- teff_grid, logg_grid, meta_grid, &
106
- flux_cube, nw, result_flux, ierr)
107
- end subroutine interp_sed_linear
108
-
109
-
110
- ! -------------------------------------------------------------------------
111
- ! dilute_flux
112
- !
113
- ! Apply (R/d)^2 dilution to convert surface flux to observed flux.
114
- ! -------------------------------------------------------------------------
115
- subroutine dilute_flux(surface_flux, nw, R, d, observed_flux)
116
- !f2py intent(in) :: surface_flux, nw, R, d
117
- !f2py intent(out) :: observed_flux
118
- integer, intent(in) :: nw
119
- real(dp), intent(in) :: surface_flux(nw), R, d
120
- real(dp), intent(out) :: observed_flux(nw)
121
- call lib_dilute_flux(surface_flux, R, d, observed_flux)
122
- end subroutine dilute_flux
123
-
124
-
125
- ! -------------------------------------------------------------------------
126
- ! synthetic_magnitude
127
- !
128
- ! Compute a synthetic magnitude in a single filter from a diluted SED.
129
- !
130
- ! Steps performed internally:
131
- ! 1. Interpolate filter transmission onto the SED wavelength grid
132
- ! 2. Photon-counting in-band flux integration
133
- ! 3. m = -2.5 log10(F_band / F_zp)
134
- !
135
- ! Parameters
136
- ! ----------
137
- ! sed_wave(nw) : SED wavelength grid (A)
138
- ! obs_flux(nw) : diluted (observer-frame) SED flux (erg/s/cm^2/A)
139
- ! filt_wave(nf) : filter wavelength grid (A)
140
- ! filt_trans(nf) : filter transmission [0,1]
141
- ! zero_point : precomputed photometric zero-point
142
- ! mag : output magnitude
143
- ! band_flux : output in-band flux (before zero-point)
144
- ! ierr : 0=ok, 1=integration failure, 2=non-positive flux
145
- ! -------------------------------------------------------------------------
146
- subroutine synthetic_magnitude(sed_wave, obs_flux, nw, &
147
- filt_wave, filt_trans, nf, &
148
- zero_point, &
149
- mag, band_flux, ierr)
150
- !f2py intent(in) :: sed_wave, obs_flux, nw
151
- !f2py intent(in) :: filt_wave, filt_trans, nf
152
- !f2py intent(in) :: zero_point
153
- !f2py intent(out) :: mag, band_flux, ierr
154
- integer, intent(in) :: nw, nf
155
- real(dp), intent(in) :: sed_wave(nw), obs_flux(nw)
156
- real(dp), intent(in) :: filt_wave(nf), filt_trans(nf)
157
- real(dp), intent(in) :: zero_point
158
- real(dp), intent(out) :: mag, band_flux
159
- integer, intent(out) :: ierr
160
-
161
- real(dp) :: filt_on_sed(nw)
162
- integer :: ierr2
163
-
164
- call lib_interp_filter(filt_wave, filt_trans, sed_wave, filt_on_sed, ierr)
165
- if (ierr /= 0) then
166
- mag = -99.9_dp; band_flux = -1.0_dp; return
167
- end if
168
-
169
- call lib_synthetic_flux(sed_wave, obs_flux * filt_on_sed, filt_on_sed, band_flux)
170
- if (band_flux <= 0.0_dp) then
171
- mag = -99.9_dp; ierr = 1; return
172
- end if
173
-
174
- call lib_magnitude(band_flux, zero_point, mag, ierr2)
175
- if (ierr2 /= 0) ierr = ierr2
176
- end subroutine synthetic_magnitude
177
-
178
-
179
- ! -------------------------------------------------------------------------
180
- ! bolometric
181
- !
182
- ! Compute bolometric flux and magnitude from a diluted SED.
183
- ! -------------------------------------------------------------------------
184
- subroutine bolometric(sed_wave, obs_flux, nw, bol_flux, bol_mag, ierr)
185
- !f2py intent(in) :: sed_wave, obs_flux, nw
186
- !f2py intent(out) :: bol_flux, bol_mag, ierr
187
- integer, intent(in) :: nw
188
- real(dp), intent(in) :: sed_wave(nw), obs_flux(nw)
189
- real(dp), intent(out) :: bol_flux, bol_mag
190
- integer, intent(out) :: ierr
191
-
192
- call lib_bol_phot(sed_wave, obs_flux, bol_mag, bol_flux, ierr)
193
- end subroutine bolometric
194
-
195
-
196
- ! -------------------------------------------------------------------------
197
- ! Zero-point subroutines (called once at init from Python)
198
- !
199
- ! colors_lib's compute_*_zero_point functions return the MESA-style
200
- ! function value with -1.0 as the failure sentinel; ierr here is
201
- ! derived from that sentinel to keep the existing ierr-based Python
202
- ! contract unchanged.
203
- ! -------------------------------------------------------------------------
204
-
205
- subroutine vega_zero_point(vega_wave, vega_flux, nv, &
206
- filt_wave, filt_trans, nf, &
207
- zp, ierr)
208
- !f2py intent(in) :: vega_wave, vega_flux, nv
209
- !f2py intent(in) :: filt_wave, filt_trans, nf
210
- !f2py intent(out) :: zp, ierr
211
- integer, intent(in) :: nv, nf
212
- real(dp), intent(in) :: vega_wave(nv), vega_flux(nv)
213
- real(dp), intent(in) :: filt_wave(nf), filt_trans(nf)
214
- real(dp), intent(out) :: zp
215
- integer, intent(out) :: ierr
216
-
217
- zp = lib_vega_zp(vega_wave, vega_flux, filt_wave, filt_trans)
218
- ierr = merge(0, 1, zp > 0.0_dp)
219
- end subroutine vega_zero_point
220
-
221
-
222
- subroutine ab_zero_point(filt_wave, filt_trans, nf, zp, ierr)
223
- !f2py intent(in) :: filt_wave, filt_trans, nf
224
- !f2py intent(out) :: zp, ierr
225
- integer, intent(in) :: nf
226
- real(dp), intent(in) :: filt_wave(nf), filt_trans(nf)
227
- real(dp), intent(out) :: zp
228
- integer, intent(out) :: ierr
229
-
230
- zp = lib_ab_zp(filt_wave, filt_trans)
231
- ierr = merge(0, 1, zp > 0.0_dp)
232
- end subroutine ab_zero_point
233
-
234
-
235
- subroutine st_zero_point(filt_wave, filt_trans, nf, zp, ierr)
236
- !f2py intent(in) :: filt_wave, filt_trans, nf
237
- !f2py intent(out) :: zp, ierr
238
- integer, intent(in) :: nf
239
- real(dp), intent(in) :: filt_wave(nf), filt_trans(nf)
240
- real(dp), intent(out) :: zp
241
- integer, intent(out) :: ierr
242
-
243
- zp = lib_st_zp(filt_wave, filt_trans)
244
- ierr = merge(0, 1, zp > 0.0_dp)
245
- end subroutine st_zero_point
246
-
247
-
248
- ! -------------------------------------------------------------------------
249
- ! Standalone integration (exposed for testing / Python use)
250
- ! -------------------------------------------------------------------------
251
-
252
- subroutine trapz(x, y, n, result)
253
- !f2py intent(in) :: x, y, n
254
- !f2py intent(out) :: result
255
- integer, intent(in) :: n
256
- real(dp), intent(in) :: x(n), y(n)
257
- real(dp), intent(out) :: result
258
- call lib_trapz(x, y, result)
259
- end subroutine trapz
260
-
261
-
262
- subroutine simpson(x, y, n, result)
263
- !f2py intent(in) :: x, y, n
264
- !f2py intent(out) :: result
265
- integer, intent(in) :: n
266
- real(dp), intent(in) :: x(n), y(n)
267
- real(dp), intent(out) :: result
268
- call lib_simpson(x, y, result)
269
- end subroutine simpson
270
-
271
- end module cc_api
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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes