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.
- {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/PKG-INFO +1 -1
- {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/asteroid_spinprops/__init__.py +0 -0
- {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/asteroid_spinprops/ssolib/modelfit.py +60 -26
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/pipetools.py +167 -0
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/atlas_x_ztf_testing/test_pqfile_1.parquet +0 -0
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/atlas_x_ztf_testing/test_pqfile_2.parquet +0 -0
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/2000 WL152 +1702 -0
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/2001 PC +94 -0
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/2001 SG276 +111 -0
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/2008 GX32 +93 -0
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/2009 BE185 +130 -0
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/2011 EY17 +101 -0
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/2134 T-1 +352 -0
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/Bellmore +2657 -0
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/Dermott +2971 -0
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/Duke +2026 -0
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/Izenberg +2440 -0
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/Lermontov +2760 -0
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/Poullain +1272 -0
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/ephemeris_testing/Sonneberga +2756 -0
- asteroid_spinprops-1.3.9/asteroid_spinprops/ssolib/testing/testing_ssoname_keys.pkl +0 -0
- {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/asteroid_spinprops/ssolib/utils.py +1 -1
- {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/pyproject.toml +1 -1
- {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/README.md +0 -0
- {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/asteroid_spinprops/ssolib/__init__.py +0 -0
- {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/asteroid_spinprops/ssolib/dataprep.py +0 -0
- {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/asteroid_spinprops/ssolib/periodest.py +0 -0
- {asteroid_spinprops-1.3.8 → asteroid_spinprops-1.3.9}/asteroid_spinprops/ssolib/ssptools.py +0 -0
|
File without changes
|
|
@@ -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
|
|
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
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
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
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
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
|