diskmelts 2.1.2__tar.gz → 2.2.1__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 (98) hide show
  1. diskmelts-2.2.1/MANIFEST.in +2 -0
  2. {diskmelts-2.1.2/src/diskmelts.egg-info → diskmelts-2.2.1}/PKG-INFO +109 -26
  3. {diskmelts-2.1.2 → diskmelts-2.2.1}/README.md +105 -22
  4. {diskmelts-2.1.2 → diskmelts-2.2.1}/pyproject.toml +8 -5
  5. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/__init__.py +4 -0
  6. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/consub/_core.py +24 -7
  7. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/fitting.py +189 -120
  8. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0/C2H2_wavelength_bank_v2/C2H2_model_bank.json +26 -0
  9. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0/C2H2_wavelength_bank_v2/net_C2H2_w6to9.pt +0 -0
  10. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0/CH3_single_v2/net_CH3_forward.pt +0 -0
  11. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/H2O_wavelength_bank_v2_fixed/H2O_model_bank.json +1 -0
  12. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0/OH_single_v2/net_OH_forward.pt +0 -0
  13. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/13C12CH2_single_v2/net_13C12CH2_forward.pt +0 -0
  14. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/13CO2_single_v2/net_13CO2_forward.pt +0 -0
  15. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/C2H2_wavelength_bank_v2/C2H2_model_bank.json +26 -0
  16. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/C2H2_wavelength_bank_v2/net_C2H2_w11p5to17.pt +0 -0
  17. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/C2H2_wavelength_bank_v2/net_C2H2_w6to9.pt +0 -0
  18. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/C2H4_single_v2/net_C2H4_forward.pt +0 -0
  19. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/C2H6_single_v2/net_C2H6_forward.pt +0 -0
  20. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/C2HD_single_v2/net_C2HD_forward.pt +0 -0
  21. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/C3H4_single_v2/net_C3H4_forward.pt +0 -0
  22. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/C4H2_single_v2/net_C4H2_forward.pt +0 -0
  23. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/C6H6_single_v2/net_C6H6_forward.pt +0 -0
  24. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/CH3_single_v2/net_CH3_forward.pt +0 -0
  25. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/CH4_single_v2/net_CH4_forward.pt +0 -0
  26. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/CO17O_single_v2/net_CO17O_forward.pt +0 -0
  27. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/CO18O_single_v2/net_CO18O_forward.pt +0 -0
  28. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/CO2_single_v2/net_CO2_forward.pt +0 -0
  29. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/H2O_wavelength_bank_v2_fixed/H2O_model_bank.json +132 -0
  30. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/H2O_wavelength_bank_v2_fixed/net_H2O_w13p5to19p2_n13to19_t100to1400.pt +0 -0
  31. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/H2O_wavelength_bank_v2_fixed/net_H2O_w19to25_n13to19_t100to1400.pt +0 -0
  32. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/H2O_wavelength_bank_v2_fixed/net_H2O_w4p9to7p4_n13to19_t100to1400.pt +0 -0
  33. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/H2O_wavelength_bank_v2_fixed/net_H2O_w7p2to11p2_n13to19_t100to1400.pt +0 -0
  34. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/H2O_wavelength_bank_v2_fixed/net_H2O_w9p9to15p1_n13to19_t100to1400.pt +0 -0
  35. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/HC3N_single_v2/net_HC3N_forward.pt +0 -0
  36. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/HCN_single_v2/net_HCN_forward.pt +0 -0
  37. diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma2/OH_single_v2/net_OH_forward.pt +0 -0
  38. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/plotting.py +3 -1
  39. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/trainmodel.py +27 -10
  40. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/v2_fitting.py +233 -35
  41. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/v2_grid_fitting.py +119 -57
  42. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/validation.py +23 -7
  43. {diskmelts-2.1.2 → diskmelts-2.2.1/src/diskmelts.egg-info}/PKG-INFO +109 -26
  44. diskmelts-2.2.1/src/diskmelts.egg-info/SOURCES.txt +81 -0
  45. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts.egg-info/requires.txt +2 -2
  46. diskmelts-2.1.2/src/diskmelts.egg-info/SOURCES.txt +0 -65
  47. diskmelts-2.1.2/tests/test_consub_package.py +0 -99
  48. diskmelts-2.1.2/tests/test_detection.py +0 -133
  49. diskmelts-2.1.2/tests/test_dev_v2_fitting_distance.py +0 -41
  50. diskmelts-2.1.2/tests/test_dev_v2_fitting_grids.py +0 -175
  51. diskmelts-2.1.2/tests/test_dev_v2_read_plot.py +0 -95
  52. diskmelts-2.1.2/tests/test_imports.py +0 -60
  53. diskmelts-2.1.2/tests/test_io.py +0 -80
  54. diskmelts-2.1.2/tests/test_mlp.py +0 -43
  55. diskmelts-2.1.2/tests/test_model_bank.py +0 -228
  56. diskmelts-2.1.2/tests/test_shared_area_fitting.py +0 -190
  57. diskmelts-2.1.2/tests/test_smoke.py +0 -48
  58. diskmelts-2.1.2/tests/test_v2_package_assets.py +0 -44
  59. diskmelts-2.1.2/tests/test_water_training.py +0 -126
  60. diskmelts-2.1.2/tests/test_workflows.py +0 -240
  61. {diskmelts-2.1.2 → diskmelts-2.2.1}/LICENSE +0 -0
  62. {diskmelts-2.1.2 → diskmelts-2.2.1}/setup.cfg +0 -0
  63. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/consub/__init__.py +0 -0
  64. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/consub/_api.py +0 -0
  65. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/consub/cont_ranges.csv +0 -0
  66. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/consub/cont_ranges_PPan.csv +0 -0
  67. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/consub/regions/carbon_extended.csv +0 -0
  68. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/consub/regions/carbon_extended.json +0 -0
  69. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/consub/regions/carbon_rich.csv +0 -0
  70. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/consub/regions/carbon_rich.json +0 -0
  71. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/consub/regions/ttauri.csv +0 -0
  72. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/consub/regions/ttauri.json +0 -0
  73. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/consub/regions/water.csv +0 -0
  74. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/consub/regions/water.json +0 -0
  75. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/13C12CH2_single_v2/net_13C12CH2_forward.pt +0 -0
  76. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/13CO2_single_v2/net_13CO2_forward.pt +0 -0
  77. /diskmelts-2.1.2/src/diskmelts/models/Trained_model/C2H2_single_v2/net_C2H2_forward.pt → /diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0/C2H2_wavelength_bank_v2/net_C2H2_w11p5to17.pt +0 -0
  78. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/C2H4_single_v2/net_C2H4_forward.pt +0 -0
  79. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/C2H6_single_v2/net_C2H6_forward.pt +0 -0
  80. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/C2HD_single_v2/net_C2HD_forward.pt +0 -0
  81. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/C3H4_single_v2/net_C3H4_forward.pt +0 -0
  82. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/C4H2_single_v2/net_C4H2_forward.pt +0 -0
  83. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/C6H6_single_v2/net_C6H6_forward.pt +0 -0
  84. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/CH4_single_v2/net_CH4_forward.pt +0 -0
  85. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/CO17O_single_v2/net_CO17O_forward.pt +0 -0
  86. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/CO18O_single_v2/net_CO18O_forward.pt +0 -0
  87. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/CO2_single_v2/net_CO2_forward.pt +0 -0
  88. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/H2O_wavelength_bank_v2_fixed/net_H2O_w13p5to19p2_n13to19_t100to1400.pt +0 -0
  89. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/H2O_wavelength_bank_v2_fixed/net_H2O_w19to25_n13to19_t100to1400.pt +0 -0
  90. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/H2O_wavelength_bank_v2_fixed/net_H2O_w4p9to7p4_n13to19_t100to1400.pt +0 -0
  91. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/H2O_wavelength_bank_v2_fixed/net_H2O_w7p2to11p2_n13to19_t100to1400.pt +0 -0
  92. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/H2O_wavelength_bank_v2_fixed/net_H2O_w9p9to15p1_n13to19_t100to1400.pt +0 -0
  93. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/HC3N_single_v2/net_HC3N_forward.pt +0 -0
  94. {diskmelts-2.1.2/src/diskmelts/models/Trained_model → diskmelts-2.2.1/src/diskmelts/models/Trained_model/sigma0}/HCN_single_v2/net_HCN_forward.pt +0 -0
  95. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/v2_paper_comparison.py +0 -0
  96. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts/v2_read_plot.py +0 -0
  97. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts.egg-info/dependency_links.txt +0 -0
  98. {diskmelts-2.1.2 → diskmelts-2.2.1}/src/diskmelts.egg-info/top_level.txt +0 -0
@@ -0,0 +1,2 @@
1
+ # Tests need the repository checkout (fixtures, Realobs_data); keep them out of the sdist.
2
+ prune tests
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: diskmelts
3
- Version: 2.1.2
3
+ Version: 2.2.1
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
@@ -12,15 +12,15 @@ Keywords: astronomy,protoplanetary disks,JWST,spectral fitting,machine learning
12
12
  Classifier: Programming Language :: Python :: 3
13
13
  Classifier: Operating System :: OS Independent
14
14
  Classifier: Topic :: Scientific/Engineering :: Astronomy
15
- Requires-Python: >=3.9
15
+ Requires-Python: >=3.11
16
16
  Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
- Requires-Dist: torch
18
+ Requires-Dist: torch>=1.13
19
19
  Requires-Dist: numpy<2,>=1.26; sys_platform == "darwin" and platform_machine == "x86_64"
20
20
  Requires-Dist: numpy; sys_platform != "darwin" or platform_machine != "x86_64"
21
21
  Requires-Dist: pandas
22
22
  Requires-Dist: scipy
23
- Requires-Dist: scikit-learn
23
+ Requires-Dist: scikit-learn<1.9,>=1.8
24
24
  Requires-Dist: matplotlib
25
25
  Provides-Extra: io
26
26
  Requires-Dist: astropy; extra == "io"
@@ -49,9 +49,11 @@ density (`logN`), and emitting area scaling (`A`) from observed spectra.
49
49
 
50
50
  ## Installation
51
51
 
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
52
+ DiskMELTS is available on [PyPI](https://pypi.org/project/diskmelts/) and
53
+ requires Python 3.11 or newer. It bundles 46 production checkpoints, 23 each
54
+ for the sigma=0 and sigma=2 grids, covering the same 18 species (see
55
+ [Available molecules](#available-molecules)).
56
+ Install it from any directory. These commands use
55
57
  `python` in an activated environment; the
56
58
  [installation guide](https://diskmelts.readthedocs.io/en/latest/installation.html)
57
59
  shows how to create one on macOS, Linux, Windows, or Conda:
@@ -74,6 +76,48 @@ downloads; pass their local path as `grid_root`.
74
76
  Example notebooks and spectra can be downloaded from the repository when
75
77
  needed; they are not installed by pip.
76
78
 
79
+ To install from a checkout with Conda or Mamba, run:
80
+
81
+ ```bash
82
+ git clone https://github.com/wddlx/DiskMELTS.git
83
+ cd DiskMELTS
84
+ conda env create -f environment.yaml
85
+ conda activate diskmelts
86
+ ```
87
+
88
+ Use `environment-notebooks.yaml` or `environment-dev.yaml` for the corresponding
89
+ notebook or contributor dependencies.
90
+
91
+ ## Minimal workflow
92
+
93
+ Subtract the continuum, fit one molecule, and print the result:
94
+
95
+ ```python
96
+ from diskmelts import consub, fit_stage, load_fitting_models
97
+
98
+ # 1. Raw spectrum: CSV with wave (µm), flux (Jy), and optional err columns.
99
+ raw_wave, raw_flux, raw_err = consub.read_spectrum("my_raw_spectrum.csv")
100
+ wave, flux, err, cont, cont_unshifted = consub.calculate(
101
+ raw_wave, raw_flux, raw_err, preset="ttauri",
102
+ )
103
+
104
+ # 2. Fit C2H2 near 13.7 µm with the bundled surrogate model.
105
+ models = load_fitting_models("C2H2")
106
+ fit = fit_stage(
107
+ wave, flux, molecule="C2H2", pretrained=models,
108
+ wavelength_range=(13.0, 15.0), fit_ranges=(13.5, 14.1),
109
+ distance_pc=140.0, n_samples=1024, n_refine=4, n_top=4,
110
+ )
111
+
112
+ # 3. Best-fit T (K), logN (cm^-2), A (au^2), and the spread of top solutions.
113
+ print(fit["params"]["C2H2"])
114
+ print(fit["uncertainty"]["C2H2"])
115
+ ```
116
+
117
+ The sections below explain each step, and the
118
+ [first-spectrum guide](https://diskmelts.readthedocs.io/en/latest/quickstart.html)
119
+ covers multi-stage fits, saved outputs, and plots.
120
+
77
121
  ## Runtime dependencies
78
122
 
79
123
  | Package | Purpose |
@@ -117,12 +161,6 @@ With `preset=None, linefreefile=None` (or `""`), fitting uses all nonexcluded
117
161
  pixels and skips the line-free correction, so `cont` equals `contOrig`.
118
162
  Reference tables are bundled; normal continuum subtraction needs no model grids.
119
163
 
120
- The private `0-Consub/` experiment directory is excluded from Git and is not
121
- required by the installed package. Its runtime code and reference tables are
122
- maintained under `src/diskmelts/consub/`.
123
- The distributed tests in `tests/` exercise the installed continuum API and
124
- bundled references without that private directory.
125
-
126
164
  Returned `err` represents measurement/noise error, not correlated continuum
127
165
  uncertainty. Broad excluded intervals require inspection. See the
128
166
  [continuum guide](https://diskmelts.readthedocs.io/en/latest/continuum.html) for presets, regional box sizes,
@@ -169,31 +207,71 @@ You can also read spectra with your own code. DiskMELTS only requires
169
207
  one-dimensional `obs_wav` and `obs_flux` arrays. Replace the sample CSV with
170
208
  your own file to fit your source; update `distance_pc` and fit intervals.
171
209
 
172
- For a complete staged fit-and-subtract workflow from a checkout, edit and run:
210
+ For a complete staged fit-and-subtract workflow from a clone of the
211
+ repository, run:
173
212
 
174
213
  ```bash
175
214
  python examples/dev_v2_realobs.py
215
+ python examples/dev_v2_realobs.py --input /path/to/my_spectrum.csv --name my_source --distance-pc 140 --sigma 2
176
216
  ```
177
217
 
218
+ Adjust that script's stage windows for your spectrum.
219
+ `python examples/synthetic_array_fit.py` generates an HCN spectrum and fits it
220
+ from in-memory arrays, without an observation file.
221
+
178
222
  The v2 fitting API is `load_fitting_models`, `fit_stage`, `fit_observation`, and
179
- `plot_saved_observation`. The production checkpoints are packaged under
180
- `src/diskmelts/models/` and included in the wheel. Model fitting requires no
181
- `Model_grids/` or `Pretrain_grid/` directory. The model metadata, including
182
- PCA counts and network layers, are in `diskmelts.MODEL_SPECS` and checked when
183
- loading. The checkpoint flux convention is 1 au² at 140 pc; `distance_pc`
184
- sets the source distance and makes the returned emitting area physical.
185
- The [fitting notebook](https://github.com/wddlx/DiskMELTS/blob/main/notebooks/Example_Fitting.ipynb) requires 13C12CH2 to
186
- be no hotter than C2H2 and gives them the same emitting area. It ties 13CO2
187
- to CO2 in both temperature and area. Set
223
+ `plot_saved_observation`. The production checkpoints are included in the
224
+ wheel, so model fitting needs no local model grids. The checkpoint flux
225
+ convention is 1 au² at 140 pc; `distance_pc` sets the source distance and
226
+ makes the returned emitting area physical. `fit_observation` accepts either a
227
+ CSV path or in-memory `obs_wav`, `obs_flux`, and optional `obs_err` arrays
228
+ (new in 2.2.1).
229
+
230
+ For a synthetic spectrum, `wave, flux = diskmelts.synthesize_spectrum('HCN',
231
+ T=300, logN=18, A=1)` returns the native wavelength axis and model flux (new
232
+ in 2.2.1). See the
233
+ [generation guide](https://diskmelts.readthedocs.io/en/latest/generate_spectra.html).
234
+
235
+ The [fitting notebook](https://github.com/wddlx/DiskMELTS/blob/main/notebooks/Example_Fitting.ipynb)
236
+ requires 13C12CH2 to be no hotter than C2H2 and gives them the same emitting
237
+ area; it ties 13CO2 to CO2 in both temperature and area. Point its input at
238
+ your own continuum-subtracted CSV, or pass arrays. Set
188
239
  `isotopologue_groups`, `Tshare` (`free`, `equal`, or `less`), and `Ashare` in a
189
240
  joint stage to choose those constraints. See the
190
241
  [fitting guide](https://diskmelts.readthedocs.io/en/latest/quickstart.html) for examples.
191
242
 
192
243
  For an optional fit directly from slab grids, use `fit_grid_stage` or
193
- `fit_observation_grids` and supply `grid_root='Model_grids'` explicitly. This
244
+ `fit_observation_grids` and supply `grid_root='Model_grids/sigma0'` explicitly. This
194
245
  separate method does require the full local grids. See the
195
246
  [quick start](https://diskmelts.readthedocs.io/en/latest/quickstart.html) for both workflows and saved-result
196
247
  plotting.
248
+ For complete sigma=2 grids, pass `grid_root='Model_grids/sigma2'`.
249
+
250
+ ## Available molecules
251
+
252
+ Each molecule is available for two slab-model grids: sigma=0 (default) assumes
253
+ no turbulent broadening, so lines are only thermally broadened, and sigma=2
254
+ assumes 2 km/s turbulent broadening. Select sigma=2 with `load_fitting_models(..., sigma=2)` or
255
+ `fit_observation(..., sigma=2)`. Fit windows must lie inside a model's band.
256
+
257
+ | Molecule | Band (µm) | T (K) | logN (cm⁻²) |
258
+ |---|---|---|---|
259
+ | H2O | 4.9–25.0 (five overlapping tiles) | 100–1400 | 13–19 |
260
+ | C2H2 | 6–9 and 11.5–17 | 100–1400 | 13–19.5 |
261
+ | HCN, CO2, 13C12CH2, 13CO2 | 11.5–17 | 100–1400 | 13–19.5 |
262
+ | HC3N, CO17O, CO18O | 13–18 | 100–1400 | 13–19.5 |
263
+ | C4H2 | 14–18 | 100–1400 | 13–19.5 |
264
+ | C3H4, CH3 | 15–18 | 100–1400 | 13–19.5 |
265
+ | C6H6 | 13–17 | 100–675 | 13–19.5 |
266
+ | C2H6 | 9–15 | 100–1400 | 13–19.5 |
267
+ | C2H4 | 8–14 | 100–1400 | 13–19.5 |
268
+ | CH4 | 5–9 | 100–1400 | 13–19.5 |
269
+ | C2HD | 11.5–20.5 | 100–1400 | 13–19.5 |
270
+ | OH | 15–26 | 100–1400 | 13–19.5 |
271
+
272
+ `diskmelts.MODEL_SPECS` records the exact domains, PCA sizes, and network
273
+ layers. Version 2.2.0 lacks the sigma=0 OH and 6–9 µm C2H2 checkpoints;
274
+ upgrade with `python -m pip install -U diskmelts`.
197
275
 
198
276
  ## Training and validation data
199
277
 
@@ -203,7 +281,7 @@ checkpoint directories under the top-level `Trained_model/` are also optional; t
203
281
  only the production checkpoints needed for v2 fitting. To run
204
282
  `examples/dev_v2_pt_validation.py` or
205
283
  `notebooks/Example_Training_Validation.ipynb`, place the complete model grids
206
- under `Model_grids/<molecule>/`. The workflows create or reuse the corresponding
284
+ under `Model_grids/sigma0/<molecule>/`. The workflows create or reuse the corresponding
207
285
  pretraining CSV under `Pretrain_grid/`.
208
286
 
209
287
  The maintained v2 workflow uses a hybrid design after restricting the expanded
@@ -223,10 +301,15 @@ DISKMELTS_MOLECULES=13C12CH2,C2HD,CO17O,CO18O python examples/dev_v2_pt_validati
223
301
  C6H6 and C3H4 also have bundled fitting checkpoints. The C6H6 checkpoint
224
302
  covers 13–17 µm and 100–675 K; C3H4 covers 15–18 µm and 100–1400 K. Load
225
303
  either by name with `load_fitting_models`. Direct grid fitting
226
- uses the same names with local `Model_grids/C6H6/` and `Model_grids/C3H4/`
304
+ uses the same names with local `Model_grids/sigma0/C6H6/` and `Model_grids/sigma0/C3H4/`
227
305
  files. See the [training guide](https://diskmelts.readthedocs.io/en/latest/training.html)
228
306
  for peak audits and retraining commands.
229
307
 
308
+ The package also includes a CH3 checkpoint for 15–18 µm,
309
+ `T=100–1400 K`, and `logN=13–19.5`. Its strongest grid feature in this window
310
+ is near 16.4–16.6 µm. Use `load_fitting_models('CH3')` after installing this
311
+ package; direct-grid fitting uses local `Model_grids/sigma0/CH3/` files.
312
+
230
313
  Five to ten percent of complete `(T, logN)` grid spectra are excluded before
231
314
  PCA or neural-network training. They are used to select the PCA dimension and
232
315
  to validate spectral reconstruction and full parameter fitting. The
@@ -10,9 +10,11 @@ density (`logN`), and emitting area scaling (`A`) from observed spectra.
10
10
 
11
11
  ## Installation
12
12
 
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
13
+ DiskMELTS is available on [PyPI](https://pypi.org/project/diskmelts/) and
14
+ requires Python 3.11 or newer. It bundles 46 production checkpoints, 23 each
15
+ for the sigma=0 and sigma=2 grids, covering the same 18 species (see
16
+ [Available molecules](#available-molecules)).
17
+ Install it from any directory. These commands use
16
18
  `python` in an activated environment; the
17
19
  [installation guide](https://diskmelts.readthedocs.io/en/latest/installation.html)
18
20
  shows how to create one on macOS, Linux, Windows, or Conda:
@@ -35,6 +37,48 @@ downloads; pass their local path as `grid_root`.
35
37
  Example notebooks and spectra can be downloaded from the repository when
36
38
  needed; they are not installed by pip.
37
39
 
40
+ To install from a checkout with Conda or Mamba, run:
41
+
42
+ ```bash
43
+ git clone https://github.com/wddlx/DiskMELTS.git
44
+ cd DiskMELTS
45
+ conda env create -f environment.yaml
46
+ conda activate diskmelts
47
+ ```
48
+
49
+ Use `environment-notebooks.yaml` or `environment-dev.yaml` for the corresponding
50
+ notebook or contributor dependencies.
51
+
52
+ ## Minimal workflow
53
+
54
+ Subtract the continuum, fit one molecule, and print the result:
55
+
56
+ ```python
57
+ from diskmelts import consub, fit_stage, load_fitting_models
58
+
59
+ # 1. Raw spectrum: CSV with wave (µm), flux (Jy), and optional err columns.
60
+ raw_wave, raw_flux, raw_err = consub.read_spectrum("my_raw_spectrum.csv")
61
+ wave, flux, err, cont, cont_unshifted = consub.calculate(
62
+ raw_wave, raw_flux, raw_err, preset="ttauri",
63
+ )
64
+
65
+ # 2. Fit C2H2 near 13.7 µm with the bundled surrogate model.
66
+ models = load_fitting_models("C2H2")
67
+ fit = fit_stage(
68
+ wave, flux, molecule="C2H2", pretrained=models,
69
+ wavelength_range=(13.0, 15.0), fit_ranges=(13.5, 14.1),
70
+ distance_pc=140.0, n_samples=1024, n_refine=4, n_top=4,
71
+ )
72
+
73
+ # 3. Best-fit T (K), logN (cm^-2), A (au^2), and the spread of top solutions.
74
+ print(fit["params"]["C2H2"])
75
+ print(fit["uncertainty"]["C2H2"])
76
+ ```
77
+
78
+ The sections below explain each step, and the
79
+ [first-spectrum guide](https://diskmelts.readthedocs.io/en/latest/quickstart.html)
80
+ covers multi-stage fits, saved outputs, and plots.
81
+
38
82
  ## Runtime dependencies
39
83
 
40
84
  | Package | Purpose |
@@ -78,12 +122,6 @@ With `preset=None, linefreefile=None` (or `""`), fitting uses all nonexcluded
78
122
  pixels and skips the line-free correction, so `cont` equals `contOrig`.
79
123
  Reference tables are bundled; normal continuum subtraction needs no model grids.
80
124
 
81
- The private `0-Consub/` experiment directory is excluded from Git and is not
82
- required by the installed package. Its runtime code and reference tables are
83
- maintained under `src/diskmelts/consub/`.
84
- The distributed tests in `tests/` exercise the installed continuum API and
85
- bundled references without that private directory.
86
-
87
125
  Returned `err` represents measurement/noise error, not correlated continuum
88
126
  uncertainty. Broad excluded intervals require inspection. See the
89
127
  [continuum guide](https://diskmelts.readthedocs.io/en/latest/continuum.html) for presets, regional box sizes,
@@ -130,31 +168,71 @@ You can also read spectra with your own code. DiskMELTS only requires
130
168
  one-dimensional `obs_wav` and `obs_flux` arrays. Replace the sample CSV with
131
169
  your own file to fit your source; update `distance_pc` and fit intervals.
132
170
 
133
- For a complete staged fit-and-subtract workflow from a checkout, edit and run:
171
+ For a complete staged fit-and-subtract workflow from a clone of the
172
+ repository, run:
134
173
 
135
174
  ```bash
136
175
  python examples/dev_v2_realobs.py
176
+ python examples/dev_v2_realobs.py --input /path/to/my_spectrum.csv --name my_source --distance-pc 140 --sigma 2
137
177
  ```
138
178
 
179
+ Adjust that script's stage windows for your spectrum.
180
+ `python examples/synthetic_array_fit.py` generates an HCN spectrum and fits it
181
+ from in-memory arrays, without an observation file.
182
+
139
183
  The v2 fitting API is `load_fitting_models`, `fit_stage`, `fit_observation`, and
140
- `plot_saved_observation`. The production checkpoints are packaged under
141
- `src/diskmelts/models/` and included in the wheel. Model fitting requires no
142
- `Model_grids/` or `Pretrain_grid/` directory. The model metadata, including
143
- PCA counts and network layers, are in `diskmelts.MODEL_SPECS` and checked when
144
- loading. The checkpoint flux convention is 1 au² at 140 pc; `distance_pc`
145
- sets the source distance and makes the returned emitting area physical.
146
- The [fitting notebook](https://github.com/wddlx/DiskMELTS/blob/main/notebooks/Example_Fitting.ipynb) requires 13C12CH2 to
147
- be no hotter than C2H2 and gives them the same emitting area. It ties 13CO2
148
- to CO2 in both temperature and area. Set
184
+ `plot_saved_observation`. The production checkpoints are included in the
185
+ wheel, so model fitting needs no local model grids. The checkpoint flux
186
+ convention is 1 au² at 140 pc; `distance_pc` sets the source distance and
187
+ makes the returned emitting area physical. `fit_observation` accepts either a
188
+ CSV path or in-memory `obs_wav`, `obs_flux`, and optional `obs_err` arrays
189
+ (new in 2.2.1).
190
+
191
+ For a synthetic spectrum, `wave, flux = diskmelts.synthesize_spectrum('HCN',
192
+ T=300, logN=18, A=1)` returns the native wavelength axis and model flux (new
193
+ in 2.2.1). See the
194
+ [generation guide](https://diskmelts.readthedocs.io/en/latest/generate_spectra.html).
195
+
196
+ The [fitting notebook](https://github.com/wddlx/DiskMELTS/blob/main/notebooks/Example_Fitting.ipynb)
197
+ requires 13C12CH2 to be no hotter than C2H2 and gives them the same emitting
198
+ area; it ties 13CO2 to CO2 in both temperature and area. Point its input at
199
+ your own continuum-subtracted CSV, or pass arrays. Set
149
200
  `isotopologue_groups`, `Tshare` (`free`, `equal`, or `less`), and `Ashare` in a
150
201
  joint stage to choose those constraints. See the
151
202
  [fitting guide](https://diskmelts.readthedocs.io/en/latest/quickstart.html) for examples.
152
203
 
153
204
  For an optional fit directly from slab grids, use `fit_grid_stage` or
154
- `fit_observation_grids` and supply `grid_root='Model_grids'` explicitly. This
205
+ `fit_observation_grids` and supply `grid_root='Model_grids/sigma0'` explicitly. This
155
206
  separate method does require the full local grids. See the
156
207
  [quick start](https://diskmelts.readthedocs.io/en/latest/quickstart.html) for both workflows and saved-result
157
208
  plotting.
209
+ For complete sigma=2 grids, pass `grid_root='Model_grids/sigma2'`.
210
+
211
+ ## Available molecules
212
+
213
+ Each molecule is available for two slab-model grids: sigma=0 (default) assumes
214
+ no turbulent broadening, so lines are only thermally broadened, and sigma=2
215
+ assumes 2 km/s turbulent broadening. Select sigma=2 with `load_fitting_models(..., sigma=2)` or
216
+ `fit_observation(..., sigma=2)`. Fit windows must lie inside a model's band.
217
+
218
+ | Molecule | Band (µm) | T (K) | logN (cm⁻²) |
219
+ |---|---|---|---|
220
+ | H2O | 4.9–25.0 (five overlapping tiles) | 100–1400 | 13–19 |
221
+ | C2H2 | 6–9 and 11.5–17 | 100–1400 | 13–19.5 |
222
+ | HCN, CO2, 13C12CH2, 13CO2 | 11.5–17 | 100–1400 | 13–19.5 |
223
+ | HC3N, CO17O, CO18O | 13–18 | 100–1400 | 13–19.5 |
224
+ | C4H2 | 14–18 | 100–1400 | 13–19.5 |
225
+ | C3H4, CH3 | 15–18 | 100–1400 | 13–19.5 |
226
+ | C6H6 | 13–17 | 100–675 | 13–19.5 |
227
+ | C2H6 | 9–15 | 100–1400 | 13–19.5 |
228
+ | C2H4 | 8–14 | 100–1400 | 13–19.5 |
229
+ | CH4 | 5–9 | 100–1400 | 13–19.5 |
230
+ | C2HD | 11.5–20.5 | 100–1400 | 13–19.5 |
231
+ | OH | 15–26 | 100–1400 | 13–19.5 |
232
+
233
+ `diskmelts.MODEL_SPECS` records the exact domains, PCA sizes, and network
234
+ layers. Version 2.2.0 lacks the sigma=0 OH and 6–9 µm C2H2 checkpoints;
235
+ upgrade with `python -m pip install -U diskmelts`.
158
236
 
159
237
  ## Training and validation data
160
238
 
@@ -164,7 +242,7 @@ checkpoint directories under the top-level `Trained_model/` are also optional; t
164
242
  only the production checkpoints needed for v2 fitting. To run
165
243
  `examples/dev_v2_pt_validation.py` or
166
244
  `notebooks/Example_Training_Validation.ipynb`, place the complete model grids
167
- under `Model_grids/<molecule>/`. The workflows create or reuse the corresponding
245
+ under `Model_grids/sigma0/<molecule>/`. The workflows create or reuse the corresponding
168
246
  pretraining CSV under `Pretrain_grid/`.
169
247
 
170
248
  The maintained v2 workflow uses a hybrid design after restricting the expanded
@@ -184,10 +262,15 @@ DISKMELTS_MOLECULES=13C12CH2,C2HD,CO17O,CO18O python examples/dev_v2_pt_validati
184
262
  C6H6 and C3H4 also have bundled fitting checkpoints. The C6H6 checkpoint
185
263
  covers 13–17 µm and 100–675 K; C3H4 covers 15–18 µm and 100–1400 K. Load
186
264
  either by name with `load_fitting_models`. Direct grid fitting
187
- uses the same names with local `Model_grids/C6H6/` and `Model_grids/C3H4/`
265
+ uses the same names with local `Model_grids/sigma0/C6H6/` and `Model_grids/sigma0/C3H4/`
188
266
  files. See the [training guide](https://diskmelts.readthedocs.io/en/latest/training.html)
189
267
  for peak audits and retraining commands.
190
268
 
269
+ The package also includes a CH3 checkpoint for 15–18 µm,
270
+ `T=100–1400 K`, and `logN=13–19.5`. Its strongest grid feature in this window
271
+ is near 16.4–16.6 µm. Use `load_fitting_models('CH3')` after installing this
272
+ package; direct-grid fitting uses local `Model_grids/sigma0/CH3/` files.
273
+
191
274
  Five to ten percent of complete `(T, logN)` grid spectra are excluded before
192
275
  PCA or neural-network training. They are used to select the PCA dimension and
193
276
  to validate spectral reconstruction and full parameter fitting. The
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "diskmelts"
7
- version = "2.1.2"
7
+ version = "2.2.1"
8
8
  description = "Machine-learning Enabled Line fitting Tool for Spectra of protoplanetary disks"
9
9
  readme = "README.md"
10
- requires-python = ">=3.9"
10
+ requires-python = ">=3.11"
11
11
  license = "MIT"
12
12
  license-files = ["LICENSE"]
13
13
  authors = [
@@ -21,13 +21,16 @@ classifiers = [
21
21
  "Topic :: Scientific/Engineering :: Astronomy",
22
22
  ]
23
23
  dependencies = [
24
- "torch",
24
+ # Checkpoints load with torch.load(weights_only=False), added in 1.13.
25
+ "torch>=1.13",
25
26
  # Intel macOS wheels stop at PyTorch 2.2, whose NumPy bridge needs NumPy 1.x.
26
27
  "numpy>=1.26,<2; sys_platform == 'darwin' and platform_machine == 'x86_64'",
27
28
  "numpy; sys_platform != 'darwin' or platform_machine != 'x86_64'",
28
29
  "pandas",
29
30
  "scipy",
30
- "scikit-learn",
31
+ # Bundled checkpoints pickle scikit-learn 1.8 PCA/scaler objects; keep the
32
+ # same minor version so they unpickle without a cross-version warning.
33
+ "scikit-learn>=1.8,<1.9",
31
34
  "matplotlib",
32
35
  ]
33
36
 
@@ -47,7 +50,7 @@ notebooks = ["jupyterlab", "ipykernel"]
47
50
  where = ["src"]
48
51
 
49
52
  [tool.setuptools.package-data]
50
- diskmelts = ["models/Trained_model/*/*.pt", "models/Trained_model/*/*.json",
53
+ diskmelts = ["models/Trained_model/sigma*/*/*.pt", "models/Trained_model/sigma*/*/*.json",
51
54
  "consub/*.csv", "consub/regions/*.csv", "consub/regions/*.json"]
52
55
 
53
56
  [tool.pytest.ini_options]
@@ -39,7 +39,9 @@ from diskmelts.plotting import (
39
39
  )
40
40
  from diskmelts.v2_fitting import (
41
41
  MODEL_SPECS,
42
+ SIGMA2_MODEL_SPECS,
42
43
  load_fitting_models,
44
+ synthesize_spectrum,
43
45
  fit_stage,
44
46
  fit_observation,
45
47
  )
@@ -58,7 +60,9 @@ from diskmelts import consub
58
60
  __all__ = [
59
61
  "consub",
60
62
  "MODEL_SPECS",
63
+ "SIGMA2_MODEL_SPECS",
61
64
  "load_fitting_models",
65
+ "synthesize_spectrum",
62
66
  "fit_stage",
63
67
  "fit_observation",
64
68
  "fit_grid_stage",
@@ -41,6 +41,8 @@ def _regions(regions):
41
41
  a = np.asarray(regions, dtype=float)
42
42
  if a.size == 0:
43
43
  return np.empty((0, 2))
44
+ if a.shape == (2,):
45
+ a = a[np.newaxis]
44
46
  if a.ndim != 2 or a.shape[1] != 2 or not np.all(np.isfinite(a)) or np.any(a[:, 1] <= a[:, 0]):
45
47
  raise ValueError("Regions must be finite (xmin, xmax) pairs with xmin < xmax")
46
48
  return a
@@ -128,11 +130,21 @@ def _mad(a):
128
130
  return 1.4826 * np.median(np.abs(a - np.median(a)))
129
131
 
130
132
 
131
- def _interp(x, xp, yp):
133
+ def _interp(x, xp, yp, linear_ends=False):
132
134
  if len(xp) == 1:
133
135
  return np.full(len(x), yp[0])
134
136
  # Constant end corrections avoid unstable polynomial extrapolation.
135
- return PchipInterpolator(xp, yp)(np.clip(x, xp[0], xp[-1]))
137
+ out = PchipInterpolator(xp, yp)(np.clip(x, xp[0], xp[-1]))
138
+ if linear_ends:
139
+ # A sloped continuum beyond the last knot needs a slope, not a constant;
140
+ # fit it over about 1 um of knots so one noisy knot cannot set it.
141
+ xp, yp = np.asarray(xp), np.asarray(yp)
142
+ for outside, end, near in ((x < xp[0], 0, xp <= xp[0] + 1.0),
143
+ (x > xp[-1], -1, xp >= xp[-1] - 1.0)):
144
+ if outside.any() and near.sum() >= 2:
145
+ slope = np.polyfit(xp[near], yp[near], 1)[0]
146
+ out[outside] = yp[end] + slope * (x[outside] - xp[end])
147
+ return out
136
148
 
137
149
 
138
150
  def _widths(x, good, boxsizes):
@@ -143,7 +155,7 @@ def _widths(x, good, boxsizes):
143
155
  n = np.convolve(good.astype(float), np.ones(min(101, len(x))), "same")
144
156
  fraction = np.maximum(n / min(101, len(x)), 0.05)
145
157
  return np.clip(31 * dx / fraction, 0.25, 1.0)
146
- if np.isscalar(boxsizes):
158
+ if np.ndim(boxsizes) == 0:
147
159
  if not np.isfinite(boxsizes) or boxsizes < 5:
148
160
  raise ValueError("boxsizes must be at least 5 pixels")
149
161
  return dx * float(boxsizes)
@@ -188,7 +200,7 @@ def _local_baseline(x, y, noise, good, widths):
188
200
  if len(positions) < 3:
189
201
  raise ValueError("Too few continuum windows; widen boxsizes or revise masks")
190
202
  knots = pd.DataFrame({"x": positions, "y": values}).groupby("x", sort=True).median()
191
- return _interp(x, knots.index.to_numpy(), knots.y.to_numpy())
203
+ return _interp(x, knots.index.to_numpy(), knots.y.to_numpy(), linear_ends=True)
192
204
 
193
205
 
194
206
  def _arpls(x, y, noise, good, widths):
@@ -203,10 +215,12 @@ def _arpls(x, y, noise, good, widths):
203
215
  weights = base.copy()
204
216
  converged = False
205
217
  for _ in range(40):
206
- z = spsolve(diags(weights) + penalty, weights*y)
218
+ z = spsolve((diags(weights) + penalty).tocsc(), weights*y)
207
219
  residual = y-z
208
220
  negative = residual[good & (residual < 0)]
209
221
  if len(negative) < 3:
222
+ # Nothing left below the baseline to down-weight: a fixed point.
223
+ converged = True
210
224
  break
211
225
  scale = max(np.std(negative), np.median(noise[good])*0.1)
212
226
  new = base * expit(-2*(residual - (2*scale-np.mean(negative)))/scale)
@@ -354,8 +368,11 @@ def subtract_continuum(wav, flux, *, error=None, exclude=None, boxsizes=None,
354
368
  unsupported |= (x < x[reference][0]) | (x > x[reference][-1])
355
369
  cont_error[unsupported] = np.nan
356
370
  if unsupported.any():
357
- warnings.warn("Continuum crosses regions with weak support; inspect the plot or "
358
- "subtract_continuum() diagnostics before using those regions", stacklevel=2)
371
+ edges = np.flatnonzero(np.diff(np.r_[0, unsupported.astype(int), 0]))
372
+ spans = ", ".join(f"{x[a]:.2f}-{x[b-1]:.2f}" for a, b in zip(edges[::2], edges[1::2]))
373
+ warnings.warn(f"Continuum is interpolated or extrapolated without nearby reference "
374
+ f"pixels at {spans} um (weak_support column); inspect the plot before "
375
+ "using those regions", stacklevel=2)
359
376
  result = pd.DataFrame({"wave": x, "flux": original-continuum,
360
377
  "err": measurement, "cont": continuum,
361
378
  "cont_unshifted": baseline, "raw_flux": original,