diskmelts 2.1__tar.gz → 2.1.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.
- {diskmelts-2.1/src/diskmelts.egg-info → diskmelts-2.1.2}/PKG-INFO +51 -61
- {diskmelts-2.1 → diskmelts-2.1.2}/README.md +50 -60
- {diskmelts-2.1 → diskmelts-2.1.2}/pyproject.toml +1 -1
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/fitting.py +27 -12
- diskmelts-2.1.2/src/diskmelts/models/Trained_model/C3H4_single_v2/net_C3H4_forward.pt +0 -0
- diskmelts-2.1.2/src/diskmelts/models/Trained_model/C6H6_single_v2/net_C6H6_forward.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/plotting.py +6 -1
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/v2_fitting.py +4 -3
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/v2_grid_fitting.py +18 -14
- {diskmelts-2.1 → diskmelts-2.1.2/src/diskmelts.egg-info}/PKG-INFO +51 -61
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts.egg-info/SOURCES.txt +2 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/tests/test_dev_v2_fitting_grids.py +63 -4
- {diskmelts-2.1 → diskmelts-2.1.2}/tests/test_io.py +25 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/tests/test_shared_area_fitting.py +38 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/tests/test_v2_package_assets.py +19 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/tests/test_workflows.py +17 -4
- {diskmelts-2.1 → diskmelts-2.1.2}/LICENSE +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/setup.cfg +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/__init__.py +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/consub/__init__.py +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/consub/_api.py +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/consub/_core.py +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/consub/cont_ranges.csv +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/consub/cont_ranges_PPan.csv +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/consub/regions/carbon_extended.csv +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/consub/regions/carbon_extended.json +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/consub/regions/carbon_rich.csv +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/consub/regions/carbon_rich.json +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/consub/regions/ttauri.csv +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/consub/regions/ttauri.json +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/consub/regions/water.csv +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/consub/regions/water.json +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/13C12CH2_single_v2/net_13C12CH2_forward.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/13CO2_single_v2/net_13CO2_forward.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/C2H2_single_v2/net_C2H2_forward.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/C2H4_single_v2/net_C2H4_forward.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/C2H6_single_v2/net_C2H6_forward.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/C2HD_single_v2/net_C2HD_forward.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/C4H2_single_v2/net_C4H2_forward.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/CH4_single_v2/net_CH4_forward.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/CO17O_single_v2/net_CO17O_forward.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/CO18O_single_v2/net_CO18O_forward.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/CO2_single_v2/net_CO2_forward.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/H2O_wavelength_bank_v2_fixed/H2O_model_bank.json +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/H2O_wavelength_bank_v2_fixed/net_H2O_w13p5to19p2_n13to19_t100to1400.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/H2O_wavelength_bank_v2_fixed/net_H2O_w19to25_n13to19_t100to1400.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/H2O_wavelength_bank_v2_fixed/net_H2O_w4p9to7p4_n13to19_t100to1400.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/H2O_wavelength_bank_v2_fixed/net_H2O_w7p2to11p2_n13to19_t100to1400.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/H2O_wavelength_bank_v2_fixed/net_H2O_w9p9to15p1_n13to19_t100to1400.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/HC3N_single_v2/net_HC3N_forward.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/models/Trained_model/HCN_single_v2/net_HCN_forward.pt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/trainmodel.py +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/v2_paper_comparison.py +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/v2_read_plot.py +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts/validation.py +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts.egg-info/dependency_links.txt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts.egg-info/requires.txt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/src/diskmelts.egg-info/top_level.txt +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/tests/test_consub_package.py +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/tests/test_detection.py +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/tests/test_dev_v2_fitting_distance.py +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/tests/test_dev_v2_read_plot.py +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/tests/test_imports.py +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/tests/test_mlp.py +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/tests/test_model_bank.py +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/tests/test_smoke.py +0 -0
- {diskmelts-2.1 → diskmelts-2.1.2}/tests/test_water_training.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: diskmelts
|
|
3
|
-
Version: 2.1
|
|
3
|
+
Version: 2.1.2
|
|
4
4
|
Summary: Machine-learning Enabled Line fitting Tool for Spectra of protoplanetary disks
|
|
5
5
|
Author: Chengyan Xie, Dingshan Deng
|
|
6
6
|
License-Expression: MIT
|
|
@@ -49,58 +49,30 @@ density (`logN`), and emitting area scaling (`A`) from observed spectra.
|
|
|
49
49
|
|
|
50
50
|
## Installation
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
DiskMELTS is available on [PyPI](https://pypi.org/project/diskmelts/).
|
|
53
|
+
The C6H6 and C3H4 checkpoints are included starting with version 2.1.2.
|
|
54
|
+
With Python 3.9 or newer, install it from any directory. These commands use
|
|
55
|
+
`python` in an activated environment; the
|
|
56
|
+
[installation guide](https://diskmelts.readthedocs.io/en/latest/installation.html)
|
|
57
|
+
shows how to create one on macOS, Linux, Windows, or Conda:
|
|
54
58
|
|
|
55
59
|
```bash
|
|
56
60
|
python -m pip install diskmelts
|
|
57
|
-
|
|
61
|
+
python -c "import diskmelts; print('DiskMELTS is ready')"
|
|
58
62
|
```
|
|
59
63
|
|
|
60
|
-
|
|
64
|
+
Optional features can be installed in the same way:
|
|
61
65
|
|
|
62
66
|
```bash
|
|
63
|
-
python -m pip install "diskmelts[io]
|
|
67
|
+
python -m pip install "diskmelts[io]" # FITS input
|
|
68
|
+
python -m pip install "diskmelts[io,notebooks]" # FITS input and JupyterLab
|
|
64
69
|
```
|
|
65
70
|
|
|
66
|
-
The package includes the production checkpoints and continuum reference
|
|
67
|
-
Full slab grids for training and direct-grid fitting are separate
|
|
68
|
-
pass their local path as `grid_root`.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
### Development checkout (macOS, Linux, Windows)
|
|
73
|
-
|
|
74
|
-
From the repository root, use a native Python 3.10 or 3.11 interpreter to
|
|
75
|
-
create a virtual environment. For FITS input and the example notebooks:
|
|
76
|
-
|
|
77
|
-
```bash
|
|
78
|
-
python3.11 -m venv .venv
|
|
79
|
-
.venv/bin/python -m pip install -e ".[io,notebooks]"
|
|
80
|
-
.venv/bin/python -c "import diskmelts; print(diskmelts.__name__)"
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
Use `python3.10` if that is the native Python available on your machine.
|
|
84
|
-
For core fitting and CSV/array inputs only, replace the install command with
|
|
85
|
-
`.venv/bin/python -m pip install -e .`. See the
|
|
86
|
-
[installation guide](https://diskmelts.readthedocs.io/en/latest/installation.html) for Windows commands.
|
|
87
|
-
|
|
88
|
-
### Conda or Mamba
|
|
89
|
-
|
|
90
|
-
The YAML files use Conda only for Python and pip; pip installs the package and
|
|
91
|
-
its declared dependencies. Choose one from the repository root:
|
|
92
|
-
|
|
93
|
-
| File | Contents |
|
|
94
|
-
| --- | --- |
|
|
95
|
-
| `environment.yaml` | Core package |
|
|
96
|
-
| `environment-notebooks.yaml` | Core package, FITS support, JupyterLab |
|
|
97
|
-
| `environment-dev.yaml` | Notebook environment, tests, documentation tools |
|
|
98
|
-
|
|
99
|
-
For the notebook setup, run `mamba env create --file environment-notebooks.yaml`
|
|
100
|
-
then `conda activate diskmelts-notebooks`. `conda env create --file` works with
|
|
101
|
-
the same files when using a current Conda release. On Apple Silicon, use a
|
|
102
|
-
native `osx-arm64` installation such as Miniforge; an older Intel Conda can
|
|
103
|
-
still spend a long time solving even these smaller files.
|
|
71
|
+
The pip package includes the production checkpoints and continuum reference
|
|
72
|
+
tables. Full slab grids for training and direct-grid fitting are separate
|
|
73
|
+
downloads; pass their local path as `grid_root`.
|
|
74
|
+
Example notebooks and spectra can be downloaded from the repository when
|
|
75
|
+
needed; they are not installed by pip.
|
|
104
76
|
|
|
105
77
|
## Runtime dependencies
|
|
106
78
|
|
|
@@ -158,34 +130,44 @@ special regions, FITS input, saving CSVs, and uncertainty diagnostics.
|
|
|
158
130
|
|
|
159
131
|
## Quick fitting example
|
|
160
132
|
|
|
133
|
+
Use a continuum-subtracted CSV with a header and `wave,flux` as its first two
|
|
134
|
+
columns, with wavelength in µm and flux in Jy. For a runnable example without
|
|
135
|
+
cloning the repository, download the
|
|
136
|
+
[J16120505 spectrum](https://github.com/wddlx/DiskMELTS/blob/main/Realobs_data/Consub_data/j16120505_v9.0_contsub_RVcorr.csv)
|
|
137
|
+
as `j16120505_contsub.csv`, or run:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
curl -L -o j16120505_contsub.csv https://raw.githubusercontent.com/wddlx/DiskMELTS/main/Realobs_data/Consub_data/j16120505_v9.0_contsub_RVcorr.csv
|
|
141
|
+
```
|
|
142
|
+
|
|
161
143
|
```python
|
|
162
|
-
from diskmelts import load_fitting_models, load_observed_spectrum
|
|
144
|
+
from diskmelts import fit_stage, load_fitting_models, load_observed_spectrum
|
|
163
145
|
|
|
164
|
-
|
|
146
|
+
models = load_fitting_models('C2H2')
|
|
165
147
|
|
|
166
148
|
obs_wav, obs_flux = load_observed_spectrum(
|
|
167
|
-
'
|
|
149
|
+
'j16120505_contsub.csv'
|
|
168
150
|
)
|
|
169
151
|
|
|
170
152
|
fit = fit_stage(
|
|
171
153
|
obs_wav,
|
|
172
154
|
obs_flux,
|
|
173
|
-
molecule='
|
|
174
|
-
wavelength_range=(
|
|
175
|
-
pretrained=
|
|
176
|
-
fit_ranges=
|
|
155
|
+
molecule='C2H2',
|
|
156
|
+
wavelength_range=(13.0, 15.0),
|
|
157
|
+
pretrained=models,
|
|
158
|
+
fit_ranges=(13.5, 14.1),
|
|
177
159
|
distance_pc=122.5,
|
|
178
|
-
n_samples=
|
|
179
|
-
n_refine=
|
|
180
|
-
n_top=
|
|
181
|
-
sigma=0.001,
|
|
160
|
+
n_samples=1024,
|
|
161
|
+
n_refine=4,
|
|
162
|
+
n_top=4,
|
|
182
163
|
)
|
|
183
164
|
|
|
184
|
-
print(fit['params'])
|
|
165
|
+
print(fit['params']['C2H2'])
|
|
185
166
|
```
|
|
186
167
|
|
|
187
168
|
You can also read spectra with your own code. DiskMELTS only requires
|
|
188
|
-
one-dimensional `obs_wav` and `obs_flux` arrays.
|
|
169
|
+
one-dimensional `obs_wav` and `obs_flux` arrays. Replace the sample CSV with
|
|
170
|
+
your own file to fit your source; update `distance_pc` and fit intervals.
|
|
189
171
|
|
|
190
172
|
For a complete staged fit-and-subtract workflow from a checkout, edit and run:
|
|
191
173
|
|
|
@@ -215,9 +197,9 @@ plotting.
|
|
|
215
197
|
|
|
216
198
|
## Training and validation data
|
|
217
199
|
|
|
218
|
-
`Model_grids/` and `Pretrain_grid/` are intentionally
|
|
219
|
-
they contain the full local training data.
|
|
220
|
-
under the top-level `Trained_model/` are also optional; the package bundles
|
|
200
|
+
Generated data under `Model_grids/` and `Pretrain_grid/` are intentionally
|
|
201
|
+
ignored by Git because they contain the full local training data. Generated
|
|
202
|
+
checkpoint directories under the top-level `Trained_model/` are also optional; the package bundles
|
|
221
203
|
only the production checkpoints needed for v2 fitting. To run
|
|
222
204
|
`examples/dev_v2_pt_validation.py` or
|
|
223
205
|
`notebooks/Example_Training_Validation.ipynb`, place the complete model grids
|
|
@@ -228,7 +210,8 @@ The maintained v2 workflow uses a hybrid design after restricting the expanded
|
|
|
228
210
|
IRIS grids to the intended physical domain. H2O uses five overlapping
|
|
229
211
|
wavelength checkpoints covering 4.9–25.0 µm, all sharing `T=100–1400 K` and
|
|
230
212
|
`logN=13–19`. Primary carbon-bearing and rarer molecules use one checkpoint
|
|
231
|
-
each
|
|
213
|
+
each and `logN=13–19.5`; C6H6 is limited to `T=100–675 K`, while the others
|
|
214
|
+
use `T=100–1400 K`.
|
|
232
215
|
The new C2HD checkpoint spans 11.5–20.5 µm to include its 19 µm band;
|
|
233
216
|
CO17O and CO18O span 13–18 µm. The updated 13C12CH2 checkpoint keeps
|
|
234
217
|
11.5–17 µm. To retrain these four grids, run:
|
|
@@ -237,6 +220,13 @@ CO17O and CO18O span 13–18 µm. The updated 13C12CH2 checkpoint keeps
|
|
|
237
220
|
DISKMELTS_MOLECULES=13C12CH2,C2HD,CO17O,CO18O python examples/dev_v2_pt_validation.py
|
|
238
221
|
```
|
|
239
222
|
|
|
223
|
+
C6H6 and C3H4 also have bundled fitting checkpoints. The C6H6 checkpoint
|
|
224
|
+
covers 13–17 µm and 100–675 K; C3H4 covers 15–18 µm and 100–1400 K. Load
|
|
225
|
+
either by name with `load_fitting_models`. Direct grid fitting
|
|
226
|
+
uses the same names with local `Model_grids/C6H6/` and `Model_grids/C3H4/`
|
|
227
|
+
files. See the [training guide](https://diskmelts.readthedocs.io/en/latest/training.html)
|
|
228
|
+
for peak audits and retraining commands.
|
|
229
|
+
|
|
240
230
|
Five to ten percent of complete `(T, logN)` grid spectra are excluded before
|
|
241
231
|
PCA or neural-network training. They are used to select the PCA dimension and
|
|
242
232
|
to validate spectral reconstruction and full parameter fitting. The
|
|
@@ -10,58 +10,30 @@ density (`logN`), and emitting area scaling (`A`) from observed spectra.
|
|
|
10
10
|
|
|
11
11
|
## Installation
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
DiskMELTS is available on [PyPI](https://pypi.org/project/diskmelts/).
|
|
14
|
+
The C6H6 and C3H4 checkpoints are included starting with version 2.1.2.
|
|
15
|
+
With Python 3.9 or newer, install it from any directory. These commands use
|
|
16
|
+
`python` in an activated environment; the
|
|
17
|
+
[installation guide](https://diskmelts.readthedocs.io/en/latest/installation.html)
|
|
18
|
+
shows how to create one on macOS, Linux, Windows, or Conda:
|
|
15
19
|
|
|
16
20
|
```bash
|
|
17
21
|
python -m pip install diskmelts
|
|
18
|
-
|
|
22
|
+
python -c "import diskmelts; print('DiskMELTS is ready')"
|
|
19
23
|
```
|
|
20
24
|
|
|
21
|
-
|
|
25
|
+
Optional features can be installed in the same way:
|
|
22
26
|
|
|
23
27
|
```bash
|
|
24
|
-
python -m pip install "diskmelts[io]
|
|
28
|
+
python -m pip install "diskmelts[io]" # FITS input
|
|
29
|
+
python -m pip install "diskmelts[io,notebooks]" # FITS input and JupyterLab
|
|
25
30
|
```
|
|
26
31
|
|
|
27
|
-
The package includes the production checkpoints and continuum reference
|
|
28
|
-
Full slab grids for training and direct-grid fitting are separate
|
|
29
|
-
pass their local path as `grid_root`.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
### Development checkout (macOS, Linux, Windows)
|
|
34
|
-
|
|
35
|
-
From the repository root, use a native Python 3.10 or 3.11 interpreter to
|
|
36
|
-
create a virtual environment. For FITS input and the example notebooks:
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
python3.11 -m venv .venv
|
|
40
|
-
.venv/bin/python -m pip install -e ".[io,notebooks]"
|
|
41
|
-
.venv/bin/python -c "import diskmelts; print(diskmelts.__name__)"
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
Use `python3.10` if that is the native Python available on your machine.
|
|
45
|
-
For core fitting and CSV/array inputs only, replace the install command with
|
|
46
|
-
`.venv/bin/python -m pip install -e .`. See the
|
|
47
|
-
[installation guide](https://diskmelts.readthedocs.io/en/latest/installation.html) for Windows commands.
|
|
48
|
-
|
|
49
|
-
### Conda or Mamba
|
|
50
|
-
|
|
51
|
-
The YAML files use Conda only for Python and pip; pip installs the package and
|
|
52
|
-
its declared dependencies. Choose one from the repository root:
|
|
53
|
-
|
|
54
|
-
| File | Contents |
|
|
55
|
-
| --- | --- |
|
|
56
|
-
| `environment.yaml` | Core package |
|
|
57
|
-
| `environment-notebooks.yaml` | Core package, FITS support, JupyterLab |
|
|
58
|
-
| `environment-dev.yaml` | Notebook environment, tests, documentation tools |
|
|
59
|
-
|
|
60
|
-
For the notebook setup, run `mamba env create --file environment-notebooks.yaml`
|
|
61
|
-
then `conda activate diskmelts-notebooks`. `conda env create --file` works with
|
|
62
|
-
the same files when using a current Conda release. On Apple Silicon, use a
|
|
63
|
-
native `osx-arm64` installation such as Miniforge; an older Intel Conda can
|
|
64
|
-
still spend a long time solving even these smaller files.
|
|
32
|
+
The pip package includes the production checkpoints and continuum reference
|
|
33
|
+
tables. Full slab grids for training and direct-grid fitting are separate
|
|
34
|
+
downloads; pass their local path as `grid_root`.
|
|
35
|
+
Example notebooks and spectra can be downloaded from the repository when
|
|
36
|
+
needed; they are not installed by pip.
|
|
65
37
|
|
|
66
38
|
## Runtime dependencies
|
|
67
39
|
|
|
@@ -119,34 +91,44 @@ special regions, FITS input, saving CSVs, and uncertainty diagnostics.
|
|
|
119
91
|
|
|
120
92
|
## Quick fitting example
|
|
121
93
|
|
|
94
|
+
Use a continuum-subtracted CSV with a header and `wave,flux` as its first two
|
|
95
|
+
columns, with wavelength in µm and flux in Jy. For a runnable example without
|
|
96
|
+
cloning the repository, download the
|
|
97
|
+
[J16120505 spectrum](https://github.com/wddlx/DiskMELTS/blob/main/Realobs_data/Consub_data/j16120505_v9.0_contsub_RVcorr.csv)
|
|
98
|
+
as `j16120505_contsub.csv`, or run:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
curl -L -o j16120505_contsub.csv https://raw.githubusercontent.com/wddlx/DiskMELTS/main/Realobs_data/Consub_data/j16120505_v9.0_contsub_RVcorr.csv
|
|
102
|
+
```
|
|
103
|
+
|
|
122
104
|
```python
|
|
123
|
-
from diskmelts import load_fitting_models, load_observed_spectrum
|
|
105
|
+
from diskmelts import fit_stage, load_fitting_models, load_observed_spectrum
|
|
124
106
|
|
|
125
|
-
|
|
107
|
+
models = load_fitting_models('C2H2')
|
|
126
108
|
|
|
127
109
|
obs_wav, obs_flux = load_observed_spectrum(
|
|
128
|
-
'
|
|
110
|
+
'j16120505_contsub.csv'
|
|
129
111
|
)
|
|
130
112
|
|
|
131
113
|
fit = fit_stage(
|
|
132
114
|
obs_wav,
|
|
133
115
|
obs_flux,
|
|
134
|
-
molecule='
|
|
135
|
-
wavelength_range=(
|
|
136
|
-
pretrained=
|
|
137
|
-
fit_ranges=
|
|
116
|
+
molecule='C2H2',
|
|
117
|
+
wavelength_range=(13.0, 15.0),
|
|
118
|
+
pretrained=models,
|
|
119
|
+
fit_ranges=(13.5, 14.1),
|
|
138
120
|
distance_pc=122.5,
|
|
139
|
-
n_samples=
|
|
140
|
-
n_refine=
|
|
141
|
-
n_top=
|
|
142
|
-
sigma=0.001,
|
|
121
|
+
n_samples=1024,
|
|
122
|
+
n_refine=4,
|
|
123
|
+
n_top=4,
|
|
143
124
|
)
|
|
144
125
|
|
|
145
|
-
print(fit['params'])
|
|
126
|
+
print(fit['params']['C2H2'])
|
|
146
127
|
```
|
|
147
128
|
|
|
148
129
|
You can also read spectra with your own code. DiskMELTS only requires
|
|
149
|
-
one-dimensional `obs_wav` and `obs_flux` arrays.
|
|
130
|
+
one-dimensional `obs_wav` and `obs_flux` arrays. Replace the sample CSV with
|
|
131
|
+
your own file to fit your source; update `distance_pc` and fit intervals.
|
|
150
132
|
|
|
151
133
|
For a complete staged fit-and-subtract workflow from a checkout, edit and run:
|
|
152
134
|
|
|
@@ -176,9 +158,9 @@ plotting.
|
|
|
176
158
|
|
|
177
159
|
## Training and validation data
|
|
178
160
|
|
|
179
|
-
`Model_grids/` and `Pretrain_grid/` are intentionally
|
|
180
|
-
they contain the full local training data.
|
|
181
|
-
under the top-level `Trained_model/` are also optional; the package bundles
|
|
161
|
+
Generated data under `Model_grids/` and `Pretrain_grid/` are intentionally
|
|
162
|
+
ignored by Git because they contain the full local training data. Generated
|
|
163
|
+
checkpoint directories under the top-level `Trained_model/` are also optional; the package bundles
|
|
182
164
|
only the production checkpoints needed for v2 fitting. To run
|
|
183
165
|
`examples/dev_v2_pt_validation.py` or
|
|
184
166
|
`notebooks/Example_Training_Validation.ipynb`, place the complete model grids
|
|
@@ -189,7 +171,8 @@ The maintained v2 workflow uses a hybrid design after restricting the expanded
|
|
|
189
171
|
IRIS grids to the intended physical domain. H2O uses five overlapping
|
|
190
172
|
wavelength checkpoints covering 4.9–25.0 µm, all sharing `T=100–1400 K` and
|
|
191
173
|
`logN=13–19`. Primary carbon-bearing and rarer molecules use one checkpoint
|
|
192
|
-
each
|
|
174
|
+
each and `logN=13–19.5`; C6H6 is limited to `T=100–675 K`, while the others
|
|
175
|
+
use `T=100–1400 K`.
|
|
193
176
|
The new C2HD checkpoint spans 11.5–20.5 µm to include its 19 µm band;
|
|
194
177
|
CO17O and CO18O span 13–18 µm. The updated 13C12CH2 checkpoint keeps
|
|
195
178
|
11.5–17 µm. To retrain these four grids, run:
|
|
@@ -198,6 +181,13 @@ CO17O and CO18O span 13–18 µm. The updated 13C12CH2 checkpoint keeps
|
|
|
198
181
|
DISKMELTS_MOLECULES=13C12CH2,C2HD,CO17O,CO18O python examples/dev_v2_pt_validation.py
|
|
199
182
|
```
|
|
200
183
|
|
|
184
|
+
C6H6 and C3H4 also have bundled fitting checkpoints. The C6H6 checkpoint
|
|
185
|
+
covers 13–17 µm and 100–675 K; C3H4 covers 15–18 µm and 100–1400 K. Load
|
|
186
|
+
either by name with `load_fitting_models`. Direct grid fitting
|
|
187
|
+
uses the same names with local `Model_grids/C6H6/` and `Model_grids/C3H4/`
|
|
188
|
+
files. See the [training guide](https://diskmelts.readthedocs.io/en/latest/training.html)
|
|
189
|
+
for peak audits and retraining commands.
|
|
190
|
+
|
|
201
191
|
Five to ten percent of complete `(T, logN)` grid spectra are excluded before
|
|
202
192
|
PCA or neural-network training. They are used to select the PCA dimension and
|
|
203
193
|
to validate spectral reconstruction and full parameter fitting. The
|
|
@@ -519,6 +519,9 @@ def _build_components(molecules, h2o_components=1, component_names=None):
|
|
|
519
519
|
raise ValueError('component_names must match the number of fitted components')
|
|
520
520
|
for comp, label in zip(components, component_names):
|
|
521
521
|
comp['label'] = label
|
|
522
|
+
labels = [comp['label'] for comp in components]
|
|
523
|
+
if len(labels) != len(set(labels)):
|
|
524
|
+
raise ValueError('component labels must be unique; name repeated molecules with component_names')
|
|
522
525
|
return components
|
|
523
526
|
|
|
524
527
|
|
|
@@ -697,8 +700,9 @@ def fit_molecules(
|
|
|
697
700
|
molecule names or component labels.
|
|
698
701
|
logN_bounds (tuple or dict or None): default (14, 19). A dict can use
|
|
699
702
|
molecule names or component labels.
|
|
700
|
-
loga_bounds (tuple or None): bounds on log10(A)
|
|
701
|
-
|
|
703
|
+
loga_bounds (tuple, dict, or None): bounds on log10(A), optionally
|
|
704
|
+
keyed by component label or molecule. None means A >= 0 with no
|
|
705
|
+
upper bound. Shared-area groups use the intersection of bounds.
|
|
702
706
|
shared_area_groups (list of sequences or None): component labels whose
|
|
703
707
|
emitting areas must be equal, e.g. [('C2H2', '13C12CH2')]. Each
|
|
704
708
|
component may appear in at most one group. Unlisted components
|
|
@@ -914,10 +918,22 @@ def fit_molecules(
|
|
|
914
918
|
)
|
|
915
919
|
return physical
|
|
916
920
|
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
+
component_area_bounds = []
|
|
922
|
+
for comp in components:
|
|
923
|
+
pair = _bounds_for(comp, loga_bounds, None)
|
|
924
|
+
if pair is None:
|
|
925
|
+
component_area_bounds.append((0.0, np.inf))
|
|
926
|
+
continue
|
|
927
|
+
if (len(pair) != 2 or not np.all(np.isfinite(pair)) or
|
|
928
|
+
pair[0] >= pair[1] or not 0 < 10.0 ** pair[0] < 10.0 ** pair[1]):
|
|
929
|
+
raise ValueError(f'{comp["label"]} needs finite increasing loga_bounds')
|
|
930
|
+
component_area_bounds.append((10.0 ** pair[0], 10.0 ** pair[1]))
|
|
931
|
+
area_lower = np.array([max(component_area_bounds[i][0] for i in members)
|
|
932
|
+
for members in area_group_members])
|
|
933
|
+
area_upper = np.array([min(component_area_bounds[i][1] for i in members)
|
|
934
|
+
for members in area_group_members])
|
|
935
|
+
if np.any(area_lower >= area_upper):
|
|
936
|
+
raise ValueError('shared area group has no overlap in loga_bounds')
|
|
921
937
|
|
|
922
938
|
def _matrix_for(params):
|
|
923
939
|
cols = []
|
|
@@ -939,12 +955,11 @@ def fit_molecules(
|
|
|
939
955
|
flux_scale = max(float(np.max(np.abs(obs_fit))),
|
|
940
956
|
float(np.max(np.abs(M_group))), np.finfo(float).tiny)
|
|
941
957
|
M_scaled, obs_scaled = M_group / flux_scale, obs_fit / flux_scale
|
|
942
|
-
if np.isfinite(
|
|
958
|
+
if np.any(area_lower > 0) or np.any(np.isfinite(area_upper)):
|
|
943
959
|
res = scipy.optimize.lsq_linear(
|
|
944
960
|
M_scaled,
|
|
945
961
|
obs_scaled,
|
|
946
|
-
bounds=(
|
|
947
|
-
np.full(len(area_group_members), A_bounds[1])),
|
|
962
|
+
bounds=(area_lower, area_upper),
|
|
948
963
|
)
|
|
949
964
|
A_group = np.asarray(res.x, dtype=np.float64)
|
|
950
965
|
else:
|
|
@@ -1332,14 +1347,14 @@ def save_fitted_comparison(csv_path, source_name, all_fits):
|
|
|
1332
1347
|
|
|
1333
1348
|
def _v(comp, key):
|
|
1334
1349
|
if comp not in all_params:
|
|
1335
|
-
return
|
|
1350
|
+
return np.nan
|
|
1336
1351
|
return round(all_params[comp][key], 4)
|
|
1337
1352
|
|
|
1338
1353
|
def _e(comp, key, which):
|
|
1339
1354
|
if comp not in all_unc:
|
|
1340
|
-
return
|
|
1355
|
+
return np.nan
|
|
1341
1356
|
v = all_unc[comp].get(key, {}).get(which, float('nan'))
|
|
1342
|
-
return round(v, 4) if np.isfinite(v) else
|
|
1357
|
+
return round(v, 4) if np.isfinite(v) else np.nan
|
|
1343
1358
|
|
|
1344
1359
|
row = {
|
|
1345
1360
|
'Source': source_name,
|
|
Binary file
|
|
Binary file
|
|
@@ -43,6 +43,8 @@ _MOL_LABEL = {
|
|
|
43
43
|
'C2HD': r'C$_2$HD',
|
|
44
44
|
'CO17O': r'C$^{16}$O$^{17}$O',
|
|
45
45
|
'CO18O': r'C$^{16}$O$^{18}$O',
|
|
46
|
+
'C6H6': r'C$_6$H$_6$',
|
|
47
|
+
'C3H4': r'C$_3$H$_4$',
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
_MOL_COLOR = {
|
|
@@ -64,6 +66,8 @@ _MOL_COLOR = {
|
|
|
64
66
|
'C2HD': 'teal',
|
|
65
67
|
'CO17O': 'slateblue',
|
|
66
68
|
'CO18O': 'goldenrod',
|
|
69
|
+
'C6H6': 'darkorange',
|
|
70
|
+
'C3H4': 'purple',
|
|
67
71
|
}
|
|
68
72
|
|
|
69
73
|
# ---------------------------------------------------------------------------
|
|
@@ -270,7 +274,8 @@ def plot_fit(
|
|
|
270
274
|
ax_bot.text(0.99, 0.92, rf'$\chi^2_{{\rm red}} = {chi2_red:.2f}$',
|
|
271
275
|
transform=ax_bot.transAxes, ha='right', va='top', fontsize=9)
|
|
272
276
|
|
|
273
|
-
|
|
277
|
+
fig.subplots_adjust(left=0.11, right=0.98, bottom=0.10, top=0.92,
|
|
278
|
+
hspace=0.08)
|
|
274
279
|
if show:
|
|
275
280
|
plt.show()
|
|
276
281
|
if save_path is not None:
|
|
@@ -34,7 +34,8 @@ CARBON_RANGES = {
|
|
|
34
34
|
'HC3N': (13.0, 18.0), 'C2H6': (9.0, 15.0),
|
|
35
35
|
'C2H4': (8.0, 14.0), 'CH4': (5.0, 9.0),
|
|
36
36
|
'C2HD': (11.5, 20.5), 'CO17O': (13.0, 18.0),
|
|
37
|
-
'CO18O': (13.0, 18.0),
|
|
37
|
+
'CO18O': (13.0, 18.0), 'C6H6': (13.0, 17.0),
|
|
38
|
+
'C3H4': (15.0, 18.0),
|
|
38
39
|
}
|
|
39
40
|
MODEL_SPECS = {
|
|
40
41
|
'H2O': {
|
|
@@ -49,9 +50,9 @@ MODEL_SPECS = {
|
|
|
49
50
|
mol: {
|
|
50
51
|
'path': f'Trained_model/{mol}_single_v2/net_{mol}_forward.pt',
|
|
51
52
|
'wavelength_ranges': (wav_range,),
|
|
52
|
-
'T_bounds': (100.0, 1400.0),
|
|
53
|
+
'T_bounds': (100.0, 675.0) if mol == 'C6H6' else (100.0, 1400.0),
|
|
53
54
|
'logN_bounds': (13.0, 19.5),
|
|
54
|
-
'n_pca': 30,
|
|
55
|
+
'n_pca': 75 if mol == 'C3H4' else 30,
|
|
55
56
|
'hidden': (64, 128, 64),
|
|
56
57
|
}
|
|
57
58
|
for mol, wav_range in CARBON_RANGES.items()
|
|
@@ -58,8 +58,8 @@ def _stage_ranges(fit_ranges, components):
|
|
|
58
58
|
|
|
59
59
|
def _components(molecule, h2o_components, component_names):
|
|
60
60
|
molecules = [molecule] if isinstance(molecule, str) else list(molecule)
|
|
61
|
-
if not molecules
|
|
62
|
-
raise ValueError('molecule must contain
|
|
61
|
+
if not molecules:
|
|
62
|
+
raise ValueError('molecule must contain at least one molecular name')
|
|
63
63
|
if h2o_components not in (1, 2):
|
|
64
64
|
raise ValueError('h2o_components must be 1 or 2')
|
|
65
65
|
parts = []
|
|
@@ -281,10 +281,6 @@ def fit_grid_stage(obs_wav, obs_flux, molecule, wavelength_range, fit_ranges, *,
|
|
|
281
281
|
noise_scale = float(sigma) * to_reference if sigma is not None else max(
|
|
282
282
|
float(np.std(target)), np.finfo(float).tiny,
|
|
283
283
|
)
|
|
284
|
-
lo_A, hi_A = 10.0 ** float(loga_bounds[0]), 10.0 ** float(loga_bounds[1])
|
|
285
|
-
if not 0 < lo_A < hi_A:
|
|
286
|
-
raise ValueError('loga_bounds must be increasing and finite')
|
|
287
|
-
|
|
288
284
|
if n_refine < 1:
|
|
289
285
|
raise ValueError('n_refine must be positive')
|
|
290
286
|
|
|
@@ -301,6 +297,14 @@ def fit_grid_stage(obs_wav, obs_flux, molecule, wavelength_range, fit_ranges, *,
|
|
|
301
297
|
bounds = [(bound_for(T_bounds, part, (100.0, 1400.0)),
|
|
302
298
|
bound_for(logN_bounds, part, default_logN(part)))
|
|
303
299
|
for part in parts]
|
|
300
|
+
area_bounds = [bound_for(loga_bounds, part, (-2.0, 2.0))
|
|
301
|
+
for part in parts]
|
|
302
|
+
if any(len(pair) != 2 or not np.all(np.isfinite(pair)) or
|
|
303
|
+
pair[0] >= pair[1] or not 0 < 10.0 ** pair[0] < 10.0 ** pair[1]
|
|
304
|
+
for pair in area_bounds):
|
|
305
|
+
raise ValueError('loga_bounds must be increasing and finite')
|
|
306
|
+
area_lower = np.array([10.0 ** pair[0] for pair in area_bounds])
|
|
307
|
+
area_upper = np.array([10.0 ** pair[1] for pair in area_bounds])
|
|
304
308
|
molecules = list(dict.fromkeys(part['model_mol'] for part in parts))
|
|
305
309
|
libraries = {}
|
|
306
310
|
for mol in molecules:
|
|
@@ -330,7 +334,7 @@ def fit_grid_stage(obs_wav, obs_flux, molecule, wavelength_range, fit_ranges, *,
|
|
|
330
334
|
def profile_amplitudes(nonlin):
|
|
331
335
|
if (ordered_water and
|
|
332
336
|
nonlin[2 * water_indices[0]] > nonlin[2 * water_indices[1]]):
|
|
333
|
-
return np.inf,
|
|
337
|
+
return np.inf, area_lower.copy()
|
|
334
338
|
matrix = templates(nonlin)
|
|
335
339
|
scale = max(float(np.max(np.abs(target))),
|
|
336
340
|
float(np.max(np.abs(matrix))), np.finfo(float).tiny)
|
|
@@ -338,12 +342,12 @@ def fit_grid_stage(obs_wav, obs_flux, molecule, wavelength_range, fit_ranges, *,
|
|
|
338
342
|
column = matrix[:, 0] / scale
|
|
339
343
|
denom = float(np.dot(column, column))
|
|
340
344
|
amplitude = (float(np.clip(np.dot(column, target / scale) / denom,
|
|
341
|
-
|
|
345
|
+
area_lower[0], area_upper[0]))
|
|
346
|
+
if denom > 0 else area_lower[0])
|
|
342
347
|
amplitudes = np.array([amplitude])
|
|
343
348
|
else:
|
|
344
349
|
solution = lsq_linear(matrix / scale, target / scale,
|
|
345
|
-
bounds=(
|
|
346
|
-
np.full(n_parts, hi_A)))
|
|
350
|
+
bounds=(area_lower, area_upper))
|
|
347
351
|
amplitudes = solution.x
|
|
348
352
|
residual = matrix @ amplitudes - target
|
|
349
353
|
return float(np.dot(residual, residual)), amplitudes
|
|
@@ -358,8 +362,8 @@ def fit_grid_stage(obs_wav, obs_flux, molecule, wavelength_range, fit_ranges, *,
|
|
|
358
362
|
key=lambda x: profile_amplitudes(x)[0])
|
|
359
363
|
if not candidates:
|
|
360
364
|
raise RuntimeError('grid search found no feasible component ordering')
|
|
361
|
-
solution_bounds = [entry for pair in bounds
|
|
362
|
-
for entry in (pair[0], pair[1],
|
|
365
|
+
solution_bounds = [entry for k, pair in enumerate(bounds)
|
|
366
|
+
for entry in (pair[0], pair[1], area_bounds[k])]
|
|
363
367
|
lower = np.array([item[0] for item in solution_bounds], dtype=float)
|
|
364
368
|
upper = np.array([item[1] for item in solution_bounds], dtype=float)
|
|
365
369
|
scales = np.array([
|
|
@@ -445,8 +449,8 @@ def fit_grid_stage(obs_wav, obs_flux, molecule, wavelength_range, fit_ranges, *,
|
|
|
445
449
|
np.isclose(T, bounds[k][0][1], rtol=0, atol=1e-5)),
|
|
446
450
|
'logN_at_bound': bool(np.isclose(logN, bounds[k][1][0], rtol=0, atol=1e-6) or
|
|
447
451
|
np.isclose(logN, bounds[k][1][1], rtol=0, atol=1e-6)),
|
|
448
|
-
'log10A_at_bound': bool(np.isclose(logA,
|
|
449
|
-
|
|
452
|
+
'log10A_at_bound': bool(np.isclose(logA, area_bounds[k][0], rtol=0, atol=1e-6) or
|
|
453
|
+
np.isclose(logA, area_bounds[k][1], rtol=0, atol=1e-6)),
|
|
450
454
|
}
|
|
451
455
|
print(f' Grid fit: {len(parts)} components, weighted SSE={best_loss:.4g}')
|
|
452
456
|
return {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: diskmelts
|
|
3
|
-
Version: 2.1
|
|
3
|
+
Version: 2.1.2
|
|
4
4
|
Summary: Machine-learning Enabled Line fitting Tool for Spectra of protoplanetary disks
|
|
5
5
|
Author: Chengyan Xie, Dingshan Deng
|
|
6
6
|
License-Expression: MIT
|
|
@@ -49,58 +49,30 @@ density (`logN`), and emitting area scaling (`A`) from observed spectra.
|
|
|
49
49
|
|
|
50
50
|
## Installation
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
DiskMELTS is available on [PyPI](https://pypi.org/project/diskmelts/).
|
|
53
|
+
The C6H6 and C3H4 checkpoints are included starting with version 2.1.2.
|
|
54
|
+
With Python 3.9 or newer, install it from any directory. These commands use
|
|
55
|
+
`python` in an activated environment; the
|
|
56
|
+
[installation guide](https://diskmelts.readthedocs.io/en/latest/installation.html)
|
|
57
|
+
shows how to create one on macOS, Linux, Windows, or Conda:
|
|
54
58
|
|
|
55
59
|
```bash
|
|
56
60
|
python -m pip install diskmelts
|
|
57
|
-
|
|
61
|
+
python -c "import diskmelts; print('DiskMELTS is ready')"
|
|
58
62
|
```
|
|
59
63
|
|
|
60
|
-
|
|
64
|
+
Optional features can be installed in the same way:
|
|
61
65
|
|
|
62
66
|
```bash
|
|
63
|
-
python -m pip install "diskmelts[io]
|
|
67
|
+
python -m pip install "diskmelts[io]" # FITS input
|
|
68
|
+
python -m pip install "diskmelts[io,notebooks]" # FITS input and JupyterLab
|
|
64
69
|
```
|
|
65
70
|
|
|
66
|
-
The package includes the production checkpoints and continuum reference
|
|
67
|
-
Full slab grids for training and direct-grid fitting are separate
|
|
68
|
-
pass their local path as `grid_root`.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
### Development checkout (macOS, Linux, Windows)
|
|
73
|
-
|
|
74
|
-
From the repository root, use a native Python 3.10 or 3.11 interpreter to
|
|
75
|
-
create a virtual environment. For FITS input and the example notebooks:
|
|
76
|
-
|
|
77
|
-
```bash
|
|
78
|
-
python3.11 -m venv .venv
|
|
79
|
-
.venv/bin/python -m pip install -e ".[io,notebooks]"
|
|
80
|
-
.venv/bin/python -c "import diskmelts; print(diskmelts.__name__)"
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
Use `python3.10` if that is the native Python available on your machine.
|
|
84
|
-
For core fitting and CSV/array inputs only, replace the install command with
|
|
85
|
-
`.venv/bin/python -m pip install -e .`. See the
|
|
86
|
-
[installation guide](https://diskmelts.readthedocs.io/en/latest/installation.html) for Windows commands.
|
|
87
|
-
|
|
88
|
-
### Conda or Mamba
|
|
89
|
-
|
|
90
|
-
The YAML files use Conda only for Python and pip; pip installs the package and
|
|
91
|
-
its declared dependencies. Choose one from the repository root:
|
|
92
|
-
|
|
93
|
-
| File | Contents |
|
|
94
|
-
| --- | --- |
|
|
95
|
-
| `environment.yaml` | Core package |
|
|
96
|
-
| `environment-notebooks.yaml` | Core package, FITS support, JupyterLab |
|
|
97
|
-
| `environment-dev.yaml` | Notebook environment, tests, documentation tools |
|
|
98
|
-
|
|
99
|
-
For the notebook setup, run `mamba env create --file environment-notebooks.yaml`
|
|
100
|
-
then `conda activate diskmelts-notebooks`. `conda env create --file` works with
|
|
101
|
-
the same files when using a current Conda release. On Apple Silicon, use a
|
|
102
|
-
native `osx-arm64` installation such as Miniforge; an older Intel Conda can
|
|
103
|
-
still spend a long time solving even these smaller files.
|
|
71
|
+
The pip package includes the production checkpoints and continuum reference
|
|
72
|
+
tables. Full slab grids for training and direct-grid fitting are separate
|
|
73
|
+
downloads; pass their local path as `grid_root`.
|
|
74
|
+
Example notebooks and spectra can be downloaded from the repository when
|
|
75
|
+
needed; they are not installed by pip.
|
|
104
76
|
|
|
105
77
|
## Runtime dependencies
|
|
106
78
|
|
|
@@ -158,34 +130,44 @@ special regions, FITS input, saving CSVs, and uncertainty diagnostics.
|
|
|
158
130
|
|
|
159
131
|
## Quick fitting example
|
|
160
132
|
|
|
133
|
+
Use a continuum-subtracted CSV with a header and `wave,flux` as its first two
|
|
134
|
+
columns, with wavelength in µm and flux in Jy. For a runnable example without
|
|
135
|
+
cloning the repository, download the
|
|
136
|
+
[J16120505 spectrum](https://github.com/wddlx/DiskMELTS/blob/main/Realobs_data/Consub_data/j16120505_v9.0_contsub_RVcorr.csv)
|
|
137
|
+
as `j16120505_contsub.csv`, or run:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
curl -L -o j16120505_contsub.csv https://raw.githubusercontent.com/wddlx/DiskMELTS/main/Realobs_data/Consub_data/j16120505_v9.0_contsub_RVcorr.csv
|
|
141
|
+
```
|
|
142
|
+
|
|
161
143
|
```python
|
|
162
|
-
from diskmelts import load_fitting_models, load_observed_spectrum
|
|
144
|
+
from diskmelts import fit_stage, load_fitting_models, load_observed_spectrum
|
|
163
145
|
|
|
164
|
-
|
|
146
|
+
models = load_fitting_models('C2H2')
|
|
165
147
|
|
|
166
148
|
obs_wav, obs_flux = load_observed_spectrum(
|
|
167
|
-
'
|
|
149
|
+
'j16120505_contsub.csv'
|
|
168
150
|
)
|
|
169
151
|
|
|
170
152
|
fit = fit_stage(
|
|
171
153
|
obs_wav,
|
|
172
154
|
obs_flux,
|
|
173
|
-
molecule='
|
|
174
|
-
wavelength_range=(
|
|
175
|
-
pretrained=
|
|
176
|
-
fit_ranges=
|
|
155
|
+
molecule='C2H2',
|
|
156
|
+
wavelength_range=(13.0, 15.0),
|
|
157
|
+
pretrained=models,
|
|
158
|
+
fit_ranges=(13.5, 14.1),
|
|
177
159
|
distance_pc=122.5,
|
|
178
|
-
n_samples=
|
|
179
|
-
n_refine=
|
|
180
|
-
n_top=
|
|
181
|
-
sigma=0.001,
|
|
160
|
+
n_samples=1024,
|
|
161
|
+
n_refine=4,
|
|
162
|
+
n_top=4,
|
|
182
163
|
)
|
|
183
164
|
|
|
184
|
-
print(fit['params'])
|
|
165
|
+
print(fit['params']['C2H2'])
|
|
185
166
|
```
|
|
186
167
|
|
|
187
168
|
You can also read spectra with your own code. DiskMELTS only requires
|
|
188
|
-
one-dimensional `obs_wav` and `obs_flux` arrays.
|
|
169
|
+
one-dimensional `obs_wav` and `obs_flux` arrays. Replace the sample CSV with
|
|
170
|
+
your own file to fit your source; update `distance_pc` and fit intervals.
|
|
189
171
|
|
|
190
172
|
For a complete staged fit-and-subtract workflow from a checkout, edit and run:
|
|
191
173
|
|
|
@@ -215,9 +197,9 @@ plotting.
|
|
|
215
197
|
|
|
216
198
|
## Training and validation data
|
|
217
199
|
|
|
218
|
-
`Model_grids/` and `Pretrain_grid/` are intentionally
|
|
219
|
-
they contain the full local training data.
|
|
220
|
-
under the top-level `Trained_model/` are also optional; the package bundles
|
|
200
|
+
Generated data under `Model_grids/` and `Pretrain_grid/` are intentionally
|
|
201
|
+
ignored by Git because they contain the full local training data. Generated
|
|
202
|
+
checkpoint directories under the top-level `Trained_model/` are also optional; the package bundles
|
|
221
203
|
only the production checkpoints needed for v2 fitting. To run
|
|
222
204
|
`examples/dev_v2_pt_validation.py` or
|
|
223
205
|
`notebooks/Example_Training_Validation.ipynb`, place the complete model grids
|
|
@@ -228,7 +210,8 @@ The maintained v2 workflow uses a hybrid design after restricting the expanded
|
|
|
228
210
|
IRIS grids to the intended physical domain. H2O uses five overlapping
|
|
229
211
|
wavelength checkpoints covering 4.9–25.0 µm, all sharing `T=100–1400 K` and
|
|
230
212
|
`logN=13–19`. Primary carbon-bearing and rarer molecules use one checkpoint
|
|
231
|
-
each
|
|
213
|
+
each and `logN=13–19.5`; C6H6 is limited to `T=100–675 K`, while the others
|
|
214
|
+
use `T=100–1400 K`.
|
|
232
215
|
The new C2HD checkpoint spans 11.5–20.5 µm to include its 19 µm band;
|
|
233
216
|
CO17O and CO18O span 13–18 µm. The updated 13C12CH2 checkpoint keeps
|
|
234
217
|
11.5–17 µm. To retrain these four grids, run:
|
|
@@ -237,6 +220,13 @@ CO17O and CO18O span 13–18 µm. The updated 13C12CH2 checkpoint keeps
|
|
|
237
220
|
DISKMELTS_MOLECULES=13C12CH2,C2HD,CO17O,CO18O python examples/dev_v2_pt_validation.py
|
|
238
221
|
```
|
|
239
222
|
|
|
223
|
+
C6H6 and C3H4 also have bundled fitting checkpoints. The C6H6 checkpoint
|
|
224
|
+
covers 13–17 µm and 100–675 K; C3H4 covers 15–18 µm and 100–1400 K. Load
|
|
225
|
+
either by name with `load_fitting_models`. Direct grid fitting
|
|
226
|
+
uses the same names with local `Model_grids/C6H6/` and `Model_grids/C3H4/`
|
|
227
|
+
files. See the [training guide](https://diskmelts.readthedocs.io/en/latest/training.html)
|
|
228
|
+
for peak audits and retraining commands.
|
|
229
|
+
|
|
240
230
|
Five to ten percent of complete `(T, logN)` grid spectra are excluded before
|
|
241
231
|
PCA or neural-network training. They are used to select the PCA dimension and
|
|
242
232
|
to validate spectral reconstruction and full parameter fitting. The
|
|
@@ -34,7 +34,9 @@ src/diskmelts/models/Trained_model/C2H2_single_v2/net_C2H2_forward.pt
|
|
|
34
34
|
src/diskmelts/models/Trained_model/C2H4_single_v2/net_C2H4_forward.pt
|
|
35
35
|
src/diskmelts/models/Trained_model/C2H6_single_v2/net_C2H6_forward.pt
|
|
36
36
|
src/diskmelts/models/Trained_model/C2HD_single_v2/net_C2HD_forward.pt
|
|
37
|
+
src/diskmelts/models/Trained_model/C3H4_single_v2/net_C3H4_forward.pt
|
|
37
38
|
src/diskmelts/models/Trained_model/C4H2_single_v2/net_C4H2_forward.pt
|
|
39
|
+
src/diskmelts/models/Trained_model/C6H6_single_v2/net_C6H6_forward.pt
|
|
38
40
|
src/diskmelts/models/Trained_model/CH4_single_v2/net_CH4_forward.pt
|
|
39
41
|
src/diskmelts/models/Trained_model/CO17O_single_v2/net_CO17O_forward.pt
|
|
40
42
|
src/diskmelts/models/Trained_model/CO18O_single_v2/net_CO18O_forward.pt
|
|
@@ -14,12 +14,13 @@ from diskmelts.v2_grid_fitting import (
|
|
|
14
14
|
)
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
def _small_grid(tmp_path):
|
|
18
|
-
grid_dir = tmp_path / 'grids' /
|
|
17
|
+
def _small_grid(tmp_path, molecule='C2H2', wavelength_range=(11.0, 13.0)):
|
|
18
|
+
grid_dir = tmp_path / 'grids' / molecule
|
|
19
19
|
grid_dir.mkdir(parents=True)
|
|
20
|
-
|
|
20
|
+
lo, hi = wavelength_range
|
|
21
|
+
wav = np.linspace(lo, hi, 60)
|
|
21
22
|
basis = np.stack([np.exp(-((wav - center) / 0.09) ** 2)
|
|
22
|
-
for center in (
|
|
23
|
+
for center in (lo + 0.3, (lo + hi) / 2, hi - 0.3)])
|
|
23
24
|
|
|
24
25
|
def spectrum(T, logN):
|
|
25
26
|
return 0.01 * (basis[0] + (1 + (T - 100) / 25) * basis[1]
|
|
@@ -33,6 +34,25 @@ def _small_grid(tmp_path):
|
|
|
33
34
|
return wav, spectrum
|
|
34
35
|
|
|
35
36
|
|
|
37
|
+
@pytest.mark.parametrize('molecule,wavelength_range', [
|
|
38
|
+
('C6H6', (13.0, 17.0)),
|
|
39
|
+
('C3H4', (15.0, 18.0)),
|
|
40
|
+
])
|
|
41
|
+
def test_new_molecules_fit_from_direct_grids(tmp_path, molecule,
|
|
42
|
+
wavelength_range):
|
|
43
|
+
wav, spectrum = _small_grid(tmp_path, molecule, wavelength_range)
|
|
44
|
+
observed = spectrum(113.0, 13.07)
|
|
45
|
+
fit = fit_grid_stage(
|
|
46
|
+
wav, observed, molecule, wavelength_range, wavelength_range,
|
|
47
|
+
grid_root=tmp_path / 'grids', T_bounds=(100, 150),
|
|
48
|
+
logN_bounds=(13, 13.25), sigma=1e-4,
|
|
49
|
+
maxiter=20, popsize=5, n_refine=2,
|
|
50
|
+
)
|
|
51
|
+
assert molecule in fit['params']
|
|
52
|
+
assert np.isfinite(fit['model_flux']).all()
|
|
53
|
+
assert np.linalg.norm(fit['residual']) < np.linalg.norm(observed)
|
|
54
|
+
|
|
55
|
+
|
|
36
56
|
def test_grid_fit_and_saved_errors(tmp_path):
|
|
37
57
|
wav, spectrum = _small_grid(tmp_path)
|
|
38
58
|
distance_pc = 177.0
|
|
@@ -114,3 +134,42 @@ def test_grid_stage_rejects_unapplied_isotope_constraints(tmp_path):
|
|
|
114
134
|
output_dir=tmp_path / 'results', detection_screening=False,
|
|
115
135
|
)
|
|
116
136
|
assert not (tmp_path / 'results').exists()
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def test_repeated_molecule_has_independent_component_bounds(tmp_path):
|
|
140
|
+
wav, spectrum = _small_grid(tmp_path)
|
|
141
|
+
observed = 0.7 * spectrum(110, 13.04) + 1.4 * spectrum(140, 13.20)
|
|
142
|
+
stage = {
|
|
143
|
+
'name': 'acetylene', 'mol': ['C2H2', 'C2H2'],
|
|
144
|
+
'component_names': ['C2H2_thin', 'C2H2_thick'],
|
|
145
|
+
'wavelength_range': (11, 13), 'fit_ranges': (11, 13),
|
|
146
|
+
'T_bounds': (100, 150),
|
|
147
|
+
'logN_bounds': {'C2H2_thin': (13.0, 13.1),
|
|
148
|
+
'C2H2_thick': (13.15, 13.25)},
|
|
149
|
+
'loga_bounds': {'C2H2_thin': (-1.0, 0.0),
|
|
150
|
+
'C2H2_thick': (0.0, 1.0)},
|
|
151
|
+
}
|
|
152
|
+
input_path = tmp_path / 'observation.csv'
|
|
153
|
+
pd.DataFrame({'wave': wav, 'flux': observed}).to_csv(input_path, index=False)
|
|
154
|
+
result = fit_observation_grids(
|
|
155
|
+
input_path, [stage], grid_root=tmp_path / 'grids',
|
|
156
|
+
output_dir=tmp_path / 'results', sigma_noise=1e-4,
|
|
157
|
+
detection_screening=False, maxiter=12, popsize=5, n_refine=2,
|
|
158
|
+
)
|
|
159
|
+
params = result['fits']['acetylene']['params']
|
|
160
|
+
assert set(params) == {'C2H2_thin', 'C2H2_thick'}
|
|
161
|
+
assert 13.0 <= params['C2H2_thin']['logN'] <= 13.1
|
|
162
|
+
assert 13.15 <= params['C2H2_thick']['logN'] <= 13.25
|
|
163
|
+
assert 0.1 <= params['C2H2_thin']['A'] <= 1.0
|
|
164
|
+
assert 1.0 <= params['C2H2_thick']['A'] <= 10.0
|
|
165
|
+
spectrum_csv = pd.read_csv(result['products']['acetylene']['spectrum'])
|
|
166
|
+
assert {'C2H2_thin_model', 'C2H2_thick_model'} <= set(spectrum_csv.columns)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def test_repeated_grid_molecule_requires_unique_labels(tmp_path):
|
|
170
|
+
wav, spectrum = _small_grid(tmp_path)
|
|
171
|
+
with pytest.raises(ValueError, match='component labels must be unique'):
|
|
172
|
+
fit_grid_stage(
|
|
173
|
+
wav, spectrum(125, 13.125), ['C2H2', 'C2H2'],
|
|
174
|
+
(11, 13), (11, 13), grid_root=tmp_path / 'grids',
|
|
175
|
+
)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import warnings
|
|
4
|
+
|
|
3
5
|
import numpy as np
|
|
4
6
|
import pandas as pd
|
|
5
7
|
import pytest
|
|
@@ -53,3 +55,26 @@ def test_save_running_spectrum(tmp_path):
|
|
|
53
55
|
assert list(df.columns) == ["wave", "residual", "cumulative_model"]
|
|
54
56
|
assert len(df) == 50
|
|
55
57
|
assert df["wave"].iloc[0] == pytest.approx(11.0)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_save_fitted_comparison_updates_missing_numeric_fields(tmp_path):
|
|
61
|
+
pytest.importorskip("torch")
|
|
62
|
+
from diskmelts import save_fitted_comparison
|
|
63
|
+
|
|
64
|
+
path = tmp_path / "comparison.csv"
|
|
65
|
+
water = {"water": {"params": {
|
|
66
|
+
"H2O_warm": {"logN": 17.0, "T": 400.0, "log10A": 1.0},
|
|
67
|
+
}}}
|
|
68
|
+
carbon = {"carbon": {"params": {
|
|
69
|
+
"C2H2": {"logN": 18.0, "T": 600.0, "log10A": 2.0},
|
|
70
|
+
}}}
|
|
71
|
+
save_fitted_comparison(path, "source", water)
|
|
72
|
+
with warnings.catch_warnings():
|
|
73
|
+
warnings.simplefilter("error", FutureWarning)
|
|
74
|
+
save_fitted_comparison(path, "source", carbon)
|
|
75
|
+
|
|
76
|
+
df = pd.read_csv(path)
|
|
77
|
+
assert len(df) == 1
|
|
78
|
+
assert pd.isna(df.loc[0, "H2O_N_warm"])
|
|
79
|
+
assert pd.isna(df.loc[0, "C2H2_N_err_low"])
|
|
80
|
+
assert df.loc[0, "C2H2_N"] == pytest.approx(18.0)
|
|
@@ -8,6 +8,44 @@ pytest.importorskip('torch')
|
|
|
8
8
|
from diskmelts import fitting
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
def test_repeated_model_molecule_uses_component_bounds(monkeypatch):
|
|
12
|
+
wave = np.linspace(13.0, 14.0, 41)
|
|
13
|
+
bases = (np.exp(-((wave - 13.3) / 0.1) ** 2),
|
|
14
|
+
np.exp(-((wave - 13.7) / 0.1) ** 2))
|
|
15
|
+
|
|
16
|
+
def fake_flux(model, T, logN, A, obs_wav):
|
|
17
|
+
shape = bases[0] + (logN - 14.0) * bases[1]
|
|
18
|
+
return A * np.interp(obs_wav, wave, shape)
|
|
19
|
+
|
|
20
|
+
monkeypatch.setattr(fitting, '_mol_flux_on_wav', fake_flux)
|
|
21
|
+
observed = fake_flux(None, 300, 14.5, 0.8, wave) + fake_flux(None, 500, 16.5, 1.5, wave)
|
|
22
|
+
fit = fitting.fit_molecules(
|
|
23
|
+
wave, observed, ['C2H2', 'C2H2'], {'C2H2': {'mol': 'C2H2'}},
|
|
24
|
+
(13.0, 14.0), component_names=['C2H2_thin', 'C2H2_thick'],
|
|
25
|
+
T_bounds=(200, 600),
|
|
26
|
+
logN_bounds={'C2H2_thin': (14.0, 15.0),
|
|
27
|
+
'C2H2_thick': (16.0, 17.0)},
|
|
28
|
+
loga_bounds={'C2H2_thin': (-1.0, 0.0),
|
|
29
|
+
'C2H2_thick': (0.0, 1.0)},
|
|
30
|
+
n_samples=16, n_refine=2, n_top=2, seed=7, verbose=False,
|
|
31
|
+
)
|
|
32
|
+
params = fit['params']
|
|
33
|
+
assert set(params) == {'C2H2_thin', 'C2H2_thick'}
|
|
34
|
+
assert 14.0 <= params['C2H2_thin']['logN'] <= 15.0
|
|
35
|
+
assert 16.0 <= params['C2H2_thick']['logN'] <= 17.0
|
|
36
|
+
assert 0.1 <= params['C2H2_thin']['A'] <= 1.0
|
|
37
|
+
assert 1.0 <= params['C2H2_thick']['A'] <= 10.0
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_repeated_model_molecule_requires_unique_labels():
|
|
41
|
+
with pytest.raises(ValueError, match='component labels must be unique'):
|
|
42
|
+
fitting.fit_molecules(
|
|
43
|
+
np.array([13.0, 14.0]), np.array([1.0, 1.0]),
|
|
44
|
+
['C2H2', 'C2H2'], {'C2H2': {}}, (13.0, 14.0),
|
|
45
|
+
verbose=False,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
11
49
|
def test_shared_area_groups_use_one_amplitude_in_joint_fit(monkeypatch):
|
|
12
50
|
wave = np.linspace(13.0, 16.0, 80)
|
|
13
51
|
profiles = {
|
|
@@ -23,3 +23,22 @@ def test_bundled_model_fit_without_grids(tmp_path, monkeypatch):
|
|
|
23
23
|
assert fit['params']['C2H2']['logN'] == pytest.approx(16, abs=0.02)
|
|
24
24
|
with pytest.raises(ValueError, match='grid_root is required'):
|
|
25
25
|
fit_grid_stage(wave, flux, 'C2H2', (13.5, 14.1), (13.5, 14.1))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@pytest.mark.parametrize('molecule,window', [
|
|
29
|
+
('C6H6', (14.5, 15.2)),
|
|
30
|
+
('C3H4', (15.68, 15.85)),
|
|
31
|
+
])
|
|
32
|
+
def test_new_bundled_molecules_fit_without_grids(tmp_path, monkeypatch,
|
|
33
|
+
molecule, window):
|
|
34
|
+
monkeypatch.chdir(tmp_path)
|
|
35
|
+
models = load_fitting_models(molecule)
|
|
36
|
+
wave = np.linspace(*window, 100)
|
|
37
|
+
flux = generate_spectrum(500, 16, 1.0, models[molecule], obs_wav=wave)
|
|
38
|
+
fit = fit_stage(
|
|
39
|
+
wave, flux, molecule, window, window, models,
|
|
40
|
+
n_samples=64, n_refine=2, n_top=2, seed=4,
|
|
41
|
+
)
|
|
42
|
+
assert molecule in fit['params']
|
|
43
|
+
assert np.isfinite(fit['model_flux']).all()
|
|
44
|
+
assert np.linalg.norm(fit['residual']) < np.linalg.norm(flux)
|
|
@@ -30,6 +30,14 @@ def test_notebook_code_cells_compile(path):
|
|
|
30
30
|
compile("".join(cell["source"]), f"{path.name}:cell-{index}", "exec")
|
|
31
31
|
|
|
32
32
|
|
|
33
|
+
@pytest.mark.parametrize("path", [FITTING_NOTEBOOK, TRAINING_NOTEBOOK])
|
|
34
|
+
def test_notebook_rejects_incompatible_sklearn(path, monkeypatch):
|
|
35
|
+
sklearn = pytest.importorskip("sklearn")
|
|
36
|
+
monkeypatch.setattr(sklearn, "__version__", "0.0")
|
|
37
|
+
with pytest.raises(RuntimeError, match="require scikit-learn 1.8.0"):
|
|
38
|
+
exec(_code_cell(_notebook(path), 1), {})
|
|
39
|
+
|
|
40
|
+
|
|
33
41
|
@pytest.mark.parametrize("start_dir", [ROOT, ROOT / "notebooks"])
|
|
34
42
|
def test_consub_notebook_reads_public_usco_csv(monkeypatch, start_dir):
|
|
35
43
|
raw_dir = ROOT / "Realobs_data" / "Raw_data"
|
|
@@ -46,6 +54,9 @@ def test_consub_notebook_reads_public_usco_csv(monkeypatch, start_dir):
|
|
|
46
54
|
@pytest.mark.parametrize("start_dir", [ROOT, ROOT / "notebooks"])
|
|
47
55
|
def test_fitting_notebook_resolves_committed_assets(monkeypatch, start_dir):
|
|
48
56
|
pytest.importorskip("torch")
|
|
57
|
+
sklearn = pytest.importorskip("sklearn")
|
|
58
|
+
# This test checks paths and stage settings; the version guard is tested above.
|
|
59
|
+
monkeypatch.setattr(sklearn, "__version__", "1.8.0")
|
|
49
60
|
notebook = _notebook(FITTING_NOTEBOOK)
|
|
50
61
|
namespace = {}
|
|
51
62
|
|
|
@@ -65,6 +76,8 @@ def test_fitting_notebook_resolves_committed_assets(monkeypatch, start_dir):
|
|
|
65
76
|
@pytest.mark.parametrize("start_dir", [ROOT, ROOT / "notebooks"])
|
|
66
77
|
def test_training_notebook_resolves_local_data_locations(monkeypatch, start_dir):
|
|
67
78
|
pytest.importorskip("torch")
|
|
79
|
+
sklearn = pytest.importorskip("sklearn")
|
|
80
|
+
monkeypatch.setattr(sklearn, "__version__", "1.8.0")
|
|
68
81
|
notebook = _notebook(TRAINING_NOTEBOOK)
|
|
69
82
|
namespace = {}
|
|
70
83
|
|
|
@@ -83,11 +96,11 @@ def test_production_checkpoint_files_are_bundled():
|
|
|
83
96
|
from diskmelts import MODEL_SPECS
|
|
84
97
|
from diskmelts.v2_fitting import MODEL_ROOT
|
|
85
98
|
|
|
86
|
-
assert len(MODEL_SPECS) ==
|
|
99
|
+
assert len(MODEL_SPECS) == 16
|
|
87
100
|
for molecule, spec in MODEL_SPECS.items():
|
|
88
101
|
path = MODEL_ROOT / spec['path']
|
|
89
102
|
assert path.is_file(), f'missing bundled checkpoint for {molecule}: {path}'
|
|
90
|
-
assert len(list(MODEL_ROOT.rglob('*.pt'))) ==
|
|
103
|
+
assert len(list(MODEL_ROOT.rglob('*.pt'))) == 20
|
|
91
104
|
|
|
92
105
|
|
|
93
106
|
def test_new_grid_checkpoints_load_and_generate_finite_spectra():
|
|
@@ -95,7 +108,7 @@ def test_new_grid_checkpoints_load_and_generate_finite_spectra():
|
|
|
95
108
|
from diskmelts import load_fitting_models
|
|
96
109
|
from diskmelts.fitting import generate_spectrum
|
|
97
110
|
|
|
98
|
-
molecules = ('13C12CH2', 'C2HD', 'CO17O', 'CO18O')
|
|
111
|
+
molecules = ('13C12CH2', 'C2HD', 'CO17O', 'CO18O', 'C6H6', 'C3H4')
|
|
99
112
|
models = load_fitting_models(molecules)
|
|
100
113
|
for molecule in molecules:
|
|
101
114
|
flux = generate_spectrum(400., 16., 1., models[molecule])
|
|
@@ -111,7 +124,7 @@ def test_gitignore_separates_fitting_assets_from_training_data():
|
|
|
111
124
|
if line.strip() and not line.lstrip().startswith("#")
|
|
112
125
|
}
|
|
113
126
|
|
|
114
|
-
for pattern in ('/Model_grids
|
|
127
|
+
for pattern in ('/Model_grids/*', '/Pretrain_grid/', '/Trained_model/',
|
|
115
128
|
'/0-Consub/',
|
|
116
129
|
'/docs/_build/', '/realobs_results/', '/figures/*'):
|
|
117
130
|
assert pattern in patterns
|
|
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
|
|
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
|
|
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
|