asteroid_spinprops 1.3.8__tar.gz → 1.3.9__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 (28) hide show
  1. {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/PKG-INFO +1 -1
  2. {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/asteroid_spinprops/__init__.py +0 -0
  3. {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/asteroid_spinprops/ssolib/modelfit.py +60 -26
  4. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/pipetools.py +167 -0
  5. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/atlas_x_ztf_testing/test_pqfile_1.parquet +0 -0
  6. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/atlas_x_ztf_testing/test_pqfile_2.parquet +0 -0
  7. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/2000 WL152 +1702 -0
  8. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/2001 PC +94 -0
  9. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/2001 SG276 +111 -0
  10. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/2008 GX32 +93 -0
  11. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/2009 BE185 +130 -0
  12. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/2011 EY17 +101 -0
  13. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/2134 T-1 +352 -0
  14. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/Bellmore +2657 -0
  15. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/Dermott +2971 -0
  16. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/Duke +2026 -0
  17. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/Izenberg +2440 -0
  18. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/Lermontov +2760 -0
  19. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/Poullain +1272 -0
  20. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/Sonneberga +2756 -0
  21. asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/testing_ssoname_keys.pkl +0 -0
  22. {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/asteroid_spinprops/ssolib/utils.py +1 -1
  23. {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/pyproject.toml +1 -1
  24. {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/README.md +0 -0
  25. {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/asteroid_spinprops/ssolib/__init__.py +0 -0
  26. {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/asteroid_spinprops/ssolib/dataprep.py +0 -0
  27. {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/asteroid_spinprops/ssolib/periodest.py +0 -0
  28. {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/asteroid_spinprops/ssolib/ssptools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: asteroid_spinprops
3
- Version: 1.3.8
3
+ Version: 1.3.9
4
4
  Summary: Collection of tools used for fitting sHG1G2 and SOCCA photometric models to sparse asteroid photometry
5
5
  License: MIT
6
6
  Author: Odysseas
@@ -4,10 +4,7 @@ import pandas as pd
4
4
  import asteroid_spinprops.ssolib.utils as utils
5
5
  import asteroid_spinprops.ssolib.periodest as periodest
6
6
 
7
- from fink_utils.sso.spins import (
8
- estimate_sso_params,
9
- func_shg1g2,
10
- )
7
+ from fink_utils.sso.spins import estimate_sso_params, func_shg1g2, parameter_remapping
11
8
  from asteroid_spinprops.ssolib.periodest import (
12
9
  get_multiterm_period_estimate,
13
10
  )
@@ -25,6 +22,8 @@ def get_fit_params(
25
22
  period_in=None,
26
23
  period_quality_flag=False,
27
24
  terminator=False,
25
+ remap=False,
26
+ remap_kwargs=None,
28
27
  time_me=True,
29
28
  ):
30
29
  """
@@ -278,7 +277,7 @@ def get_fit_params(
278
277
  H_key = next(
279
278
  (
280
279
  f"H_{i}" for i in range(1, 7) if f"H_{i}" in shg1g2_params
281
- ), # FIXME: Harcoded N of bands, won't throw error if N>6, but to be recosnidered
280
+ ), # FIXME: Harcoded N of bands, won't throw error if N>6, but to be reconsidered
282
281
  None,
283
282
  )
284
283
 
@@ -314,13 +313,24 @@ def get_fit_params(
314
313
  a_c,
315
314
  0.1,
316
315
  ] # phi 0
317
- SOCCA = get_fit_params(
318
- data,
319
- "SOCCA",
320
- shg1g2_constrained=False,
321
- p0=p_in,
322
- terminator=terminator,
323
- )
316
+ if remap:
317
+ SOCCA = get_fit_params(
318
+ data,
319
+ "SOCCA",
320
+ shg1g2_constrained=False,
321
+ p0=p_in,
322
+ terminator=terminator,
323
+ remap=remap,
324
+ remap_kwargs=remap_kwargs,
325
+ )
326
+ else:
327
+ SOCCA = get_fit_params(
328
+ data,
329
+ "SOCCA",
330
+ shg1g2_constrained=False,
331
+ p0=p_in,
332
+ terminator=terminator,
333
+ )
324
334
  try:
325
335
  rms.append(SOCCA["rms"])
326
336
  model.append(SOCCA)
@@ -435,20 +445,44 @@ def get_fit_params(
435
445
  print("Initialize SOCCA first!")
436
446
  if p0 is not None:
437
447
  if terminator:
438
- Afit = estimate_sso_params(
439
- data["cmred"].values[0],
440
- data["csigmapsf"].values[0],
441
- np.radians(data["Phase"].values[0]),
442
- data["cfid"].values[0],
443
- ra=np.radians(data["ra"].values[0]),
444
- dec=np.radians(data["dec"].values[0]),
445
- jd=data["cjd"].values[0],
446
- model="SOCCA",
447
- p0=p0,
448
- terminator=terminator,
449
- ra_s=np.radians(data["ra_s"].values[0]),
450
- dec_s=np.radians(data["dec_s"].values[0]),
451
- )
448
+ if remap:
449
+ p0in = np.concatenate((p0[3:], p0[:3]))
450
+ p0_latent = parameter_remapping(
451
+ p0in, physical_to_latent=True, **remap_kwargs
452
+ )
453
+ p0_latent = np.concatenate((p0_latent[-3:], p0_latent[:-3]))
454
+ Afit = estimate_sso_params(
455
+ data["cmred"].values[0],
456
+ data["csigmapsf"].values[0],
457
+ np.radians(data["Phase"].values[0]),
458
+ data["cfid"].values[0],
459
+ ra=np.radians(data["ra"].values[0]),
460
+ dec=np.radians(data["dec"].values[0]),
461
+ jd=data["cjd"].values[0],
462
+ model="SOCCA",
463
+ p0=p0_latent,
464
+ terminator=terminator,
465
+ ra_s=np.radians(data["ra_s"].values[0]),
466
+ dec_s=np.radians(data["dec_s"].values[0]),
467
+ bounds=None,
468
+ remap=remap,
469
+ remap_kwargs=remap_kwargs,
470
+ )
471
+ else:
472
+ Afit = estimate_sso_params(
473
+ data["cmred"].values[0],
474
+ data["csigmapsf"].values[0],
475
+ np.radians(data["Phase"].values[0]),
476
+ data["cfid"].values[0],
477
+ ra=np.radians(data["ra"].values[0]),
478
+ dec=np.radians(data["dec"].values[0]),
479
+ jd=data["cjd"].values[0],
480
+ model="SOCCA",
481
+ p0=p0,
482
+ terminator=terminator,
483
+ ra_s=np.radians(data["ra_s"].values[0]),
484
+ dec_s=np.radians(data["dec_s"].values[0]),
485
+ )
452
486
  else:
453
487
  Afit = estimate_sso_params(
454
488
  data["cmred"].values[0],
@@ -0,0 +1,167 @@
1
+ import pandas as pd
2
+ from tqdm import tqdm
3
+ import rocks
4
+ import numpy as np
5
+
6
+ from asteroid_spinprops.ssolib.dataprep import filter_sso_data
7
+ from asteroid_spinprops.ssolib.modelfit import get_fit_params, make_residuals_df
8
+ from asteroid_spinprops.ssolib.periodest import (
9
+ get_period_estimate,
10
+ perform_residual_resampling,
11
+ )
12
+ from asteroid_spinprops.ssolib.utils import read_clean_data
13
+
14
+
15
+ def process_single_sso(name: str, path_args: list, filtering=True) -> tuple | None:
16
+ """
17
+ Process a single Solar System Object to extract period estimation metrics.
18
+
19
+ Parameters
20
+ ----------
21
+ name : str
22
+ Name of the SSO to be processed.
23
+ path_args : list
24
+ Arguments required to locate and load SSO data,
25
+ paths to parquet files and ephemeris cache.
26
+
27
+ Returns
28
+ -------
29
+ tuple or None
30
+ A tuple containing:
31
+ - signal (tuple): Periodogram signal information (power, frequency and the 5 highest peaks).
32
+ - window (tuple): Window function data (power, frequency and the 5 highest peaks).
33
+ - noise (float): Signal noise level.
34
+ - name (str): SSO name.
35
+ - Nbs (int): Bootstrap score.
36
+ - npts (int): Number of data points.
37
+ Returns None if processing fails.
38
+ """
39
+ try:
40
+ if filtering is True:
41
+ data, _ = filter_sso_data(name, *path_args)
42
+ else:
43
+ data = read_clean_data(name, *path_args, return_rejects=False)
44
+ mparams = get_fit_params(data=data, flavor="SHG1G2")
45
+ resid_df = make_residuals_df(data, mparams)
46
+ signal, window, noise = get_period_estimate(resid_df)
47
+ _, Nbs = perform_residual_resampling(resid_df=resid_df)
48
+ npts = len(data["Phase"].values[0])
49
+ return signal, window, noise, name, Nbs, npts
50
+ except Exception:
51
+ return None
52
+
53
+
54
+ def load_light_curve_data(file_path: str) -> pd.DataFrame:
55
+ """
56
+ Load a LCDB CSV file and return a dataframe containing objects periods.
57
+
58
+ Parameters
59
+ ----------
60
+ file_path : str
61
+ Path to the CSV file containing light curve details.
62
+
63
+ Returns
64
+ -------
65
+ pd.DataFrame
66
+ A DataFrame containing cleaned and filtered light curve data,
67
+ with the 'Period' column converted to float and initial metadata rows skipped.
68
+ """
69
+ lc = pd.read_csv(file_path, skiprows=range(16))
70
+ lc = lc[5:]
71
+ lc["Period"] = lc["Period"].astype(float)
72
+ return lc
73
+
74
+
75
+ def fill_missing_periods_and_powers(periods, powers):
76
+ """
77
+ Replace incomplete period or power arrays with NaN-filled placeholders.
78
+
79
+ Parameters
80
+ ----------
81
+ periods : list of array-like
82
+ List of period arrays estimated for each SSO.
83
+ powers : list of array-like
84
+ List of power arrays associated with each estimated period.
85
+
86
+ Returns
87
+ -------
88
+ None
89
+ The input lists are modified in place.
90
+ """
91
+ filler = np.full(5, np.nan)
92
+ for i in range(len(periods)):
93
+ if len(periods[i]) < 5:
94
+ periods[i] = filler
95
+ if len(powers[i]) < 5:
96
+ powers[i] = filler
97
+
98
+
99
+ def collect_rocks_periods(names: list[str]) -> list[np.ndarray]:
100
+ """
101
+ Retrieve known periods from the SsODNet service for a list of SSOs.
102
+
103
+ Parameters
104
+ ----------
105
+ names : list of str
106
+ List of SSO names to query.
107
+
108
+ Returns
109
+ -------
110
+ list of np.ndarray
111
+ Each element is an array of known periods for the corresponding SSO & method.
112
+ If no valid periods are found, returns two arrays with a single NaN.
113
+ """
114
+ periods = []
115
+ methods = []
116
+ for sso in tqdm(names, desc="Querying rocks"):
117
+ r = rocks.Rock(sso, datacloud="spins")
118
+ try:
119
+ values = r.spins["period"].values.astype(np.float64)
120
+ method = r.spins["method"].values
121
+
122
+ if (values == [None] * len(values)).all():
123
+ periods.append(np.array([np.nan]))
124
+ methods.append(np.array([np.nan]))
125
+ else:
126
+ periods.append(values[~np.isnan(values)])
127
+ methods.append(method[~np.isnan(values)])
128
+ except Exception:
129
+ periods.append(np.array([np.nan]))
130
+ methods.append(np.array([np.nan]))
131
+ return periods, methods
132
+
133
+
134
+ def match_true_period(Ps, Procks, Pmethods):
135
+ """
136
+ Match the closest known period from SsODNet to each estimated period.
137
+
138
+ Parameters
139
+ ----------
140
+ Ps : array-like
141
+ Array of estimated periods
142
+ Procks : list of np.ndarray
143
+ List of known periods from Rocks for each SSO.
144
+
145
+ Returns
146
+ -------
147
+ list
148
+ The closest known period from Rocks for each estimate & method.
149
+ Returns NaN if no valid match exists.
150
+ """
151
+ matched = []
152
+ method = []
153
+ for p_est, p_true, m_true in zip(Ps, Procks, Pmethods):
154
+ if isinstance(p_true, float) or len(p_true) == 0 or np.isnan(p_true).all():
155
+ matched.append(np.nan)
156
+ method.append(np.nan)
157
+ else:
158
+ diffs = np.abs(p_est - p_true[:, None]) / p_true[:, None]
159
+ min_idx = np.argmin(diffs, axis=0)
160
+ matched.append(p_true[min_idx[0]])
161
+ method.append(m_true[min_idx[0]])
162
+ return matched, method
163
+
164
+
165
+ def filter_sso_name(name, path_args):
166
+ clean_data, rejects = filter_sso_data(name, *path_args, lc_filtering=False)
167
+ return name, clean_data, rejects