microlens-submit 0.16.5__tar.gz → 0.17.0__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 (49) hide show
  1. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/CHANGELOG.md +28 -0
  2. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/CITATION.cff +2 -2
  3. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/PKG-INFO +4 -4
  4. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/README.md +3 -3
  5. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/__init__.py +1 -1
  6. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/cli/commands/solutions.py +29 -1
  7. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/cli/commands/validation.py +8 -3
  8. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/models/solution.py +17 -0
  9. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/models/submission.py +4 -2
  10. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/tier_validation.py +6 -9
  11. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/validate_parameters.py +522 -190
  12. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit.egg-info/PKG-INFO +4 -4
  13. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit.egg-info/SOURCES.txt +2 -0
  14. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/pyproject.toml +1 -1
  15. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/setup.py +1 -1
  16. microlens_submit-0.17.0/tests/test_bic_calculation.py +235 -0
  17. microlens_submit-0.17.0/tests/test_physical_validation.py +55 -0
  18. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/tests/test_tier_validation.py +2 -2
  19. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/LICENSE +0 -0
  20. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/MANIFEST.in +0 -0
  21. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/assets/github-desktop_logo.png +0 -0
  22. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/assets/rges-pit_logo.png +0 -0
  23. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/cli/__init__.py +0 -0
  24. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/cli/__main__.py +0 -0
  25. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/cli/commands/__init__.py +0 -0
  26. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/cli/commands/dossier.py +0 -0
  27. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/cli/commands/export.py +0 -0
  28. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/cli/commands/init.py +0 -0
  29. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/cli/main.py +0 -0
  30. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/dossier/__init__.py +0 -0
  31. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/dossier/dashboard.py +0 -0
  32. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/dossier/event_page.py +0 -0
  33. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/dossier/full_report.py +0 -0
  34. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/dossier/solution_page.py +0 -0
  35. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/dossier/utils.py +0 -0
  36. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/error_messages.py +0 -0
  37. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/models/__init__.py +0 -0
  38. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/models/event.py +0 -0
  39. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/text_symbols.py +0 -0
  40. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit/utils.py +0 -0
  41. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit.egg-info/dependency_links.txt +0 -0
  42. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit.egg-info/entry_points.txt +0 -0
  43. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit.egg-info/requires.txt +0 -0
  44. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/microlens_submit.egg-info/top_level.txt +0 -0
  45. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/setup.cfg +0 -0
  46. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/tests/test_api.py +0 -0
  47. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/tests/test_cli.py +0 -0
  48. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/tests/test_dossier_generation.py +0 -0
  49. {microlens_submit-0.16.5 → microlens_submit-0.17.0}/tests/test_dossier_pages.py +0 -0
@@ -5,6 +5,34 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.17.0] - 2026-02-04
9
+
10
+ ### Added
11
+ - **Physical Parameters**: Added 24 physical parameters (Mtot, M1-M4, D_L, D_S, thetaE, piE components, mu_rel components, phi) to parameter spec
12
+ - **Physical Parameter Validation**: Comprehensive validation including mass consistency checks, vector magnitude verification, distance constraints, and unit confusion warnings
13
+ - **Uncertainty Metadata**: Added three new Solution fields:
14
+ - `uncertainty_method`: Method used to derive uncertainties (mcmc_posterior, fisher_matrix, bootstrap, propagation, inference, literature, other)
15
+ - `confidence_level`: Confidence level for uncertainties (default: 0.68 for 1-sigma)
16
+ - `physical_parameter_uncertainties`: Uncertainties for physical parameters (symmetric or asymmetric)
17
+ - **CLI Options**: Added `--physical-param-uncertainty`, `--uncertainty-method`, and `--confidence-level` options to `add-solution` command
18
+ - **Tests**: Added 3 new comprehensive BIC calculation tests verifying parameter counting
19
+ - **Version Management**: Enhanced `bump_version.py` to update and validate `parameter_spec.yaml` (includes drift check)
20
+
21
+ ### Fixed
22
+ - **BIC Calculation Bug**: Fixed critical bug where BIC calculation counted ALL parameters including metadata (t_ref, limb_darkening_coeffs) and physical parameters (Mtot, D_L, etc.) as "free parameters". Now correctly counts only fitted model parameters using new `count_model_parameters()` function. This affects relative probability calculations during export and solution comparison.
23
+
24
+ ### Changed
25
+ - Physical parameters now validated with `validate_physical_parameters()` automatically when present
26
+ - Solution metadata validation now includes uncertainty metadata checks
27
+ - BIC calculation in `submission.py` and `validation.py` now uses `count_model_parameters()` instead of `len(s.parameters)`
28
+
29
+ ### Documentation
30
+ - Added comprehensive examples of physical parameters and uncertainty metadata to tutorial and usage examples
31
+ - Tutorial emphasizes uncertainties are **optional but strongly recommended** for evaluation readiness
32
+ - Created `PHYSICAL_PARAMS_SUMMARY.md` with complete implementation guide
33
+
34
+ ## [Unreleased]
35
+
8
36
  ## [0.16.5] - 2026-02-04
9
37
 
10
38
  ### Fixed
@@ -1,9 +1,9 @@
1
1
  cff-version: 1.2.0
2
2
  message: "If you use microlens-submit, please cite it as below."
3
3
  title: "microlens-submit"
4
- version: "0.16.5"
4
+ version: "0.17.0"
5
5
  authors:
6
6
  - family-names: Malpas
7
7
  given-names: Amber
8
8
  url: "https://github.com/AmberLee2427/microlens-submit"
9
- doi: "10.5281/zenodo.18246117"
9
+ doi: "10.5281/zenodo.18488304"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: microlens-submit
3
- Version: 0.16.5
3
+ Version: 0.17.0
4
4
  Summary: A tool for managing and submitting microlensing solutions
5
5
  Home-page: https://github.com/AmberLee2427/microlens-submit
6
6
  Author: Amber Malpas
@@ -210,15 +210,15 @@ import this file directly.
210
210
 
211
211
  Bibtex:
212
212
  ```
213
- @software{malpas_2025_18246117,
213
+ @software{malpas_2025_18488304,
214
214
  author = {Malpas, Amber},
215
215
  title = {microlens-submit},
216
216
  month = oct,
217
217
  year = 2025,
218
218
  publisher = {Zenodo},
219
219
  version = {v0.16.3},
220
- doi = {10.5281/zenodo.18246117},
221
- url = {https://doi.org/10.5281/zenodo.18246117},
220
+ doi = {10.5281/zenodo.18488304},
221
+ url = {https://doi.org/10.5281/zenodo.18488304},
222
222
  }
223
223
  ```
224
224
 
@@ -160,15 +160,15 @@ import this file directly.
160
160
 
161
161
  Bibtex:
162
162
  ```
163
- @software{malpas_2025_18246117,
163
+ @software{malpas_2025_18488304,
164
164
  author = {Malpas, Amber},
165
165
  title = {microlens-submit},
166
166
  month = oct,
167
167
  year = 2025,
168
168
  publisher = {Zenodo},
169
169
  version = {v0.16.3},
170
- doi = {10.5281/zenodo.18246117},
171
- url = {https://doi.org/10.5281/zenodo.18246117},
170
+ doi = {10.5281/zenodo.18488304},
171
+ url = {https://doi.org/10.5281/zenodo.18488304},
172
172
  }
173
173
  ```
174
174
 
@@ -5,7 +5,7 @@ validate, and export a challenge submission using either the Python API or
5
5
  the command line interface.
6
6
  """
7
7
 
8
- __version__ = "0.16.5"
8
+ __version__ = "0.17.0"
9
9
 
10
10
  from .models import Event, Solution, Submission
11
11
  from .utils import load
@@ -187,7 +187,31 @@ def add_solution(
187
187
  physical_param: Optional[List[str]] = typer.Option(
188
188
  None,
189
189
  "--physical-param",
190
- help=("Physical parameters (M_L, D_L, M_planet, a, etc.) " "derived from model parameters [ADVANCED]"),
190
+ help=("Physical parameters (Mtot, D_L, thetaE, etc.) " "derived from model parameters [ADVANCED]"),
191
+ ),
192
+ physical_param_uncertainty: Optional[List[str]] = typer.Option(
193
+ None,
194
+ "--physical-param-uncertainty",
195
+ help=(
196
+ "Physical parameter uncertainties as key=value. "
197
+ "Can be single value (symmetric) or [lower,upper] (asymmetric) [ADVANCED]"
198
+ ),
199
+ ),
200
+ uncertainty_method: Optional[str] = typer.Option(
201
+ None,
202
+ "--uncertainty-method",
203
+ help=(
204
+ "Method used to derive uncertainties [ADVANCED]. "
205
+ "Options: mcmc_posterior, fisher_matrix, bootstrap, propagation, inference, literature, other"
206
+ ),
207
+ ),
208
+ confidence_level: Optional[float] = typer.Option(
209
+ None,
210
+ "--confidence-level",
211
+ help=(
212
+ "Confidence level for uncertainties (default: 0.68 = 1σ) [ADVANCED]. "
213
+ "Standard values: 0.68 (1σ), 0.95 (2σ), 0.997 (3σ)"
214
+ ),
191
215
  ),
192
216
  relative_probability: Optional[float] = typer.Option(
193
217
  None,
@@ -281,6 +305,10 @@ def add_solution(
281
305
  sol.limb_darkening_coeffs = _parse_pairs(limb_darkening_coeff)
282
306
  sol.parameter_uncertainties = _parse_pairs(parameter_uncertainty) or uncertainties
283
307
  sol.physical_parameters = _parse_pairs(physical_param)
308
+ sol.physical_parameter_uncertainties = _parse_pairs(physical_param_uncertainty)
309
+ sol.uncertainty_method = uncertainty_method
310
+ if confidence_level is not None:
311
+ sol.confidence_level = confidence_level
284
312
  sol.log_likelihood = log_likelihood
285
313
  sol.relative_probability = relative_probability
286
314
  sol.n_data_points = n_data_points
@@ -12,6 +12,7 @@ from rich.table import Table
12
12
  from microlens_submit.error_messages import enhance_validation_messages
13
13
  from microlens_submit.text_symbols import symbol
14
14
  from microlens_submit.utils import load
15
+ from microlens_submit.validate_parameters import count_model_parameters
15
16
 
16
17
  console = Console()
17
18
 
@@ -196,13 +197,17 @@ def compare_solutions(
196
197
  need_calc = [s for s in solutions if s.relative_probability is None]
197
198
  if need_calc:
198
199
  can_calc = all(
199
- s.log_likelihood is not None and s.n_data_points and s.n_data_points > 0 and len(s.parameters) > 0
200
+ s.log_likelihood is not None
201
+ and s.n_data_points
202
+ and s.n_data_points > 0
203
+ and count_model_parameters(s.parameters) > 0
200
204
  for s in need_calc
201
205
  )
202
206
  remaining = max(1.0 - provided_sum, 0.0)
203
207
  if can_calc:
204
208
  bic_vals = {
205
- s.solution_id: len(s.parameters) * math.log(s.n_data_points) - 2 * s.log_likelihood
209
+ s.solution_id: count_model_parameters(s.parameters) * math.log(s.n_data_points)
210
+ - 2 * s.log_likelihood
206
211
  for s in need_calc
207
212
  }
208
213
  bic_min = min(bic_vals.values())
@@ -219,7 +224,7 @@ def compare_solutions(
219
224
 
220
225
  rows = []
221
226
  for sol in solutions:
222
- k = len(sol.parameters)
227
+ k = count_model_parameters(sol.parameters)
223
228
  bic = k * math.log(sol.n_data_points) - 2 * sol.log_likelihood
224
229
  rp = sol.relative_probability if sol.relative_probability is not None else rel_prob_map.get(sol.solution_id)
225
230
  rows.append(
@@ -134,7 +134,10 @@ class Solution(BaseModel):
134
134
  limb_darkening_model: Optional[str] = None
135
135
  limb_darkening_coeffs: Optional[dict] = None
136
136
  parameter_uncertainties: Optional[dict] = None
137
+ uncertainty_method: Optional[str] = None
138
+ confidence_level: Optional[float] = 0.68
137
139
  physical_parameters: Optional[dict] = None
140
+ physical_parameter_uncertainties: Optional[dict] = None
138
141
  log_likelihood: Optional[float] = None
139
142
  relative_probability: Optional[float] = None
140
143
  n_data_points: Optional[int] = None
@@ -155,6 +158,7 @@ class Solution(BaseModel):
155
158
  higher_order_effects = values.get("higher_order_effects", [])
156
159
  bands = values.get("bands", [])
157
160
  t_ref = values.get("t_ref")
161
+ limb_darkening_coeffs = values.get("limb_darkening_coeffs")
158
162
 
159
163
  # Only check for totally broken objects (e.g., wrong types)
160
164
  basic_errors = []
@@ -176,6 +180,7 @@ class Solution(BaseModel):
176
180
  higher_order_effects=higher_order_effects,
177
181
  bands=bands,
178
182
  t_ref=t_ref,
183
+ limb_darkening_coeffs=limb_darkening_coeffs,
179
184
  )
180
185
  if validation_warnings:
181
186
  warnings.warn(f"Solution created with potential issues: {'; '.join(validation_warnings)}", UserWarning)
@@ -388,6 +393,18 @@ class Solution(BaseModel):
388
393
  )
389
394
  messages.extend(consistency_messages)
390
395
 
396
+ # Check solution metadata (uncertainties, etc.)
397
+ from ..validate_parameters import validate_solution_metadata
398
+
399
+ metadata_messages = validate_solution_metadata(
400
+ parameter_uncertainties=self.parameter_uncertainties,
401
+ physical_parameters=self.physical_parameters,
402
+ physical_parameter_uncertainties=self.physical_parameter_uncertainties,
403
+ uncertainty_method=self.uncertainty_method,
404
+ confidence_level=self.confidence_level,
405
+ )
406
+ messages.extend(metadata_messages)
407
+
391
408
  return messages
392
409
 
393
410
  def _save(self, event_path: Path) -> None:
@@ -18,6 +18,7 @@ import psutil
18
18
  from pydantic import BaseModel, Field
19
19
 
20
20
  from ..text_symbols import symbol
21
+ from ..validate_parameters import count_model_parameters
21
22
  from .event import Event
22
23
  from .solution import Solution
23
24
 
@@ -500,14 +501,15 @@ class Submission(BaseModel):
500
501
  s.log_likelihood is None
501
502
  or s.n_data_points is None
502
503
  or s.n_data_points <= 0
503
- or len(s.parameters) == 0
504
+ or count_model_parameters(s.parameters) == 0
504
505
  ):
505
506
  can_calc = False
506
507
  break
507
508
  remaining = max(1.0 - provided_sum, 0.0)
508
509
  if can_calc:
509
510
  bic_vals = {
510
- s.solution_id: len(s.parameters) * math.log(s.n_data_points) - 2 * s.log_likelihood
511
+ s.solution_id: count_model_parameters(s.parameters) * math.log(s.n_data_points)
512
+ - 2 * s.log_likelihood
511
513
  for s in need_calc
512
514
  }
513
515
  bic_min = min(bic_vals.values())
@@ -38,21 +38,21 @@ Note:
38
38
  from typing import Dict, List, Optional, Set
39
39
 
40
40
  # Tier definitions with their associated event lists
41
+ # --- BEGIN AUTO-GENERATED: TIER_DEFINITIONS ---
41
42
  TIER_DEFINITIONS = {
42
43
  "beginner": {
43
44
  "description": "Beginner challenge tier with limited event set",
44
45
  "event_prefix": "rmdc26_",
45
- "event_range": [0, 200],
46
+ "event_range": [0, 253],
46
47
  },
47
48
  "experienced": {
48
49
  "description": "Experienced challenge tier with full event set",
49
50
  "event_prefix": "rmdc26_",
50
- "event_range": [0, 2000],
51
+ "event_range": [0, 3000],
51
52
  },
52
53
  "test": {
53
54
  "description": "Testing tier for development",
54
55
  "event_list": [
55
- # Add test events here
56
56
  "evt",
57
57
  "test-event",
58
58
  "EVENT001",
@@ -68,17 +68,14 @@ TIER_DEFINITIONS = {
68
68
  "description": "2018 test events tier",
69
69
  "event_prefix": "ulwdc1_",
70
70
  "event_range": [0, 293],
71
- "event_list": [
72
- # Add 2018 test events here
73
- "2018-EVENT-001",
74
- "2018-EVENT-002",
75
- ],
71
+ "event_list": ["2018-EVENT-001", "2018-EVENT-002"],
76
72
  },
77
73
  "None": {
78
74
  "description": "No validation tier (skips event validation)",
79
- "event_list": [], # Empty list means no validation
75
+ "event_list": [],
80
76
  },
81
77
  }
78
+ # --- END AUTO-GENERATED: TIER_DEFINITIONS ---
82
79
 
83
80
  # Cache for event lists to avoid repeated list creation
84
81
  _EVENT_LIST_CACHE: Dict[str, Set[str]] = {}