asteroid_spinprops 1.0.1__py3-none-any.whl → 1.1.2__py3-none-any.whl
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/ssolib/modelfit.py +105 -82
- asteroid_spinprops/ssolib/periodest.py +5 -5
- {asteroid_spinprops-1.0.1.dist-info → asteroid_spinprops-1.1.2.dist-info}/METADATA +1 -1
- {asteroid_spinprops-1.0.1.dist-info → asteroid_spinprops-1.1.2.dist-info}/RECORD +5 -5
- {asteroid_spinprops-1.0.1.dist-info → asteroid_spinprops-1.1.2.dist-info}/WHEEL +0 -0
|
@@ -7,16 +7,18 @@ from fink_utils.sso.spins import (
|
|
|
7
7
|
estimate_sso_params,
|
|
8
8
|
func_hg1g2_with_spin,
|
|
9
9
|
)
|
|
10
|
-
from asteroid_spinprops.ssolib.periodest import
|
|
10
|
+
from asteroid_spinprops.ssolib.periodest import (
|
|
11
|
+
get_multiterm_period_estimate,
|
|
12
|
+
)
|
|
11
13
|
|
|
12
14
|
|
|
13
15
|
def get_fit_params(
|
|
14
16
|
data,
|
|
15
17
|
flavor,
|
|
16
18
|
shg1g2_constrained=True,
|
|
17
|
-
|
|
19
|
+
period_blind=True,
|
|
20
|
+
pole_blind=True,
|
|
18
21
|
p0=None,
|
|
19
|
-
survey_filter=None,
|
|
20
22
|
alt_spin=False,
|
|
21
23
|
period_in=None,
|
|
22
24
|
terminator=False,
|
|
@@ -30,28 +32,28 @@ def get_fit_params(
|
|
|
30
32
|
|
|
31
33
|
Parameters
|
|
32
34
|
----------
|
|
33
|
-
data : pandas.DataFrame
|
|
35
|
+
data : pandas.DataFrame single-row
|
|
34
36
|
Input dataset containing photometry and geometry with columns:
|
|
35
37
|
- 'cmred': reduced magnitudes
|
|
36
38
|
- 'csigmapsf': uncertainties
|
|
37
39
|
- 'Phase': solar phase angles (deg)
|
|
38
40
|
- 'cfid': filter IDs
|
|
39
41
|
- 'ra', 'dec': coordinates (deg)
|
|
40
|
-
- 'cjd': observation times
|
|
42
|
+
- 'cjd': observation times (light-time corrected)
|
|
41
43
|
Optional (for terminator fits):
|
|
42
44
|
- 'ra_s', 'dec_s': sub-solar point coordinates (deg)
|
|
43
45
|
flavor : str
|
|
44
|
-
Model type to fit. Must be 'SHG1G2' or '
|
|
46
|
+
Model type to fit. Must be 'SHG1G2' or 'SOCCA'.
|
|
45
47
|
shg1g2_constrained : bool, optional
|
|
46
|
-
Whether to constrain the
|
|
47
|
-
|
|
48
|
-
If True, perform a small grid search over initial
|
|
48
|
+
Whether to constrain the SOCCA fit using a prior SHG1G2 solution. Default True.
|
|
49
|
+
period_blind : bool, optional
|
|
50
|
+
If True, perform a small grid search over initial periods. Default True.
|
|
51
|
+
pole_blind : bool, optional
|
|
52
|
+
If True, perform a grid search over initial poles. Default True.
|
|
49
53
|
p0 : list, optional
|
|
50
54
|
Initial guess parameters for the fit. Required if `shg1g2_constrained=False`.
|
|
51
|
-
survey_filter : str or None, optional
|
|
52
|
-
If 'ZTF' or 'ATLAS', only data from that survey are used. Default None uses all data.
|
|
53
55
|
alt_spin : bool, optional
|
|
54
|
-
For
|
|
56
|
+
For SOCCA constrained fits, use the antipodal spin solution. Default False.
|
|
55
57
|
period_in : float, optional
|
|
56
58
|
Input synodic period (days) to override automatic estimation. Default None.
|
|
57
59
|
terminator : bool, optional
|
|
@@ -63,7 +65,7 @@ def get_fit_params(
|
|
|
63
65
|
If `flavor='SHG1G2'`:
|
|
64
66
|
dict
|
|
65
67
|
Best-fit SHG1G2 parameters.
|
|
66
|
-
If `flavor='
|
|
68
|
+
If `flavor='SOCCA'`:
|
|
67
69
|
dict
|
|
68
70
|
Best-fit SOCCA parameters.
|
|
69
71
|
|
|
@@ -77,59 +79,72 @@ def get_fit_params(
|
|
|
77
79
|
Raises
|
|
78
80
|
------
|
|
79
81
|
ValueError
|
|
80
|
-
If `flavor` is not 'SHG1G2' or '
|
|
82
|
+
If `flavor` is not 'SHG1G2' or 'SOCCA'.
|
|
81
83
|
"""
|
|
82
84
|
|
|
83
|
-
if survey_filter is None:
|
|
84
|
-
filter_mask = np.array(data["cfid"].values[0]) >= 0
|
|
85
|
-
if survey_filter == "ZTF":
|
|
86
|
-
filter_mask = (np.array(data["cfid"].values[0]) == 1) | (
|
|
87
|
-
np.array(data["cfid"].values[0]) == 2
|
|
88
|
-
)
|
|
89
|
-
if survey_filter == "ATLAS":
|
|
90
|
-
filter_mask = (np.array(data["cfid"].values[0]) == 3) | (
|
|
91
|
-
np.array(data["cfid"].values[0]) == 4
|
|
92
|
-
)
|
|
93
85
|
if flavor == "SHG1G2":
|
|
94
86
|
if p0 is None:
|
|
95
87
|
Afit = estimate_sso_params(
|
|
96
|
-
magpsf_red=data["cmred"].values[0]
|
|
97
|
-
sigmapsf=data["csigmapsf"].values[0]
|
|
98
|
-
phase=np.radians(data["Phase"].values[0]
|
|
99
|
-
filters=data["cfid"].values[0]
|
|
100
|
-
ra=np.radians(data["ra"].values[0]
|
|
101
|
-
dec=np.radians(data["dec"].values[0]
|
|
88
|
+
magpsf_red=data["cmred"].values[0],
|
|
89
|
+
sigmapsf=data["csigmapsf"].values[0],
|
|
90
|
+
phase=np.radians(data["Phase"].values[0]),
|
|
91
|
+
filters=data["cfid"].values[0],
|
|
92
|
+
ra=np.radians(data["ra"].values[0]),
|
|
93
|
+
dec=np.radians(data["dec"].values[0]),
|
|
102
94
|
model="SHG1G2",
|
|
103
95
|
)
|
|
104
96
|
|
|
105
97
|
if p0 is not None:
|
|
106
98
|
Afit = estimate_sso_params(
|
|
107
|
-
magpsf_red=data["cmred"].values[0]
|
|
108
|
-
sigmapsf=data["csigmapsf"].values[0]
|
|
109
|
-
phase=np.radians(data["Phase"].values[0]
|
|
110
|
-
filters=data["cfid"].values[0]
|
|
111
|
-
ra=np.radians(data["ra"].values[0]
|
|
112
|
-
dec=np.radians(data["dec"].values[0]
|
|
99
|
+
magpsf_red=data["cmred"].values[0],
|
|
100
|
+
sigmapsf=data["csigmapsf"].values[0],
|
|
101
|
+
phase=np.radians(data["Phase"].values[0]),
|
|
102
|
+
filters=data["cfid"].values[0],
|
|
103
|
+
ra=np.radians(data["ra"].values[0]),
|
|
104
|
+
dec=np.radians(data["dec"].values[0]),
|
|
113
105
|
model="SHG1G2",
|
|
114
106
|
p0=p0,
|
|
115
107
|
)
|
|
116
108
|
|
|
117
109
|
return Afit
|
|
118
|
-
if flavor == "
|
|
110
|
+
if flavor == "SOCCA":
|
|
119
111
|
if shg1g2_constrained is True:
|
|
120
112
|
shg1g2_params = get_fit_params(
|
|
121
|
-
data=data, flavor="SHG1G2"
|
|
122
|
-
)
|
|
123
|
-
residuals_dataframe = make_residuals_df(
|
|
124
|
-
data, model_parameters=shg1g2_params
|
|
113
|
+
data=data, flavor="SHG1G2"
|
|
125
114
|
)
|
|
115
|
+
try:
|
|
116
|
+
residuals_dataframe = make_residuals_df(
|
|
117
|
+
data, model_parameters=shg1g2_params
|
|
118
|
+
)
|
|
119
|
+
except Exception:
|
|
120
|
+
SOCCA_opt = {"Failed at period search preliminary steps": 3}
|
|
121
|
+
return SOCCA_opt
|
|
126
122
|
if period_in is None:
|
|
127
|
-
|
|
128
|
-
|
|
123
|
+
# Period search boundaries (in days)
|
|
124
|
+
pmin, pmax = 5e-2, 1e4
|
|
125
|
+
try:
|
|
126
|
+
p_in, k_val, p_rms, signal_peaks, window_peaks = (
|
|
127
|
+
get_multiterm_period_estimate(
|
|
128
|
+
residuals_dataframe, p_min=pmin, p_max=pmax, k_free=True
|
|
129
|
+
)
|
|
130
|
+
)
|
|
131
|
+
except KeyError:
|
|
132
|
+
# If more than 10 terms are required switch to fast rotator:
|
|
133
|
+
pmin, pmax = 5e-3, 5e-2
|
|
134
|
+
try:
|
|
135
|
+
p_in, k_val, p_rms, signal_peaks, window_peaks = (
|
|
136
|
+
get_multiterm_period_estimate(
|
|
137
|
+
residuals_dataframe, p_min=pmin, p_max=pmax, k_free=True
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
except Exception:
|
|
141
|
+
SOCCA_opt = {"Failed at period search after": 4}
|
|
142
|
+
return SOCCA_opt
|
|
143
|
+
period_sy = p_in
|
|
129
144
|
else:
|
|
130
145
|
period_sy = period_in
|
|
131
146
|
|
|
132
|
-
if
|
|
147
|
+
if period_blind is True:
|
|
133
148
|
rms = []
|
|
134
149
|
model = []
|
|
135
150
|
|
|
@@ -138,10 +153,16 @@ def get_fit_params(
|
|
|
138
153
|
)
|
|
139
154
|
|
|
140
155
|
ra0, dec0 = shg1g2_params["alpha0"], shg1g2_params["delta0"]
|
|
156
|
+
|
|
157
|
+
if pole_blind is True:
|
|
158
|
+
ra_init, dec_init = utils.generate_initial_points(
|
|
159
|
+
ra0, dec0, dec_shift=45
|
|
160
|
+
)
|
|
141
161
|
|
|
142
|
-
|
|
143
|
-
ra0, dec0
|
|
144
|
-
|
|
162
|
+
else:
|
|
163
|
+
ra0_antipodal, dec0_antipodal = utils.flip_spin(ra0, dec0)
|
|
164
|
+
ra_init = [ra0, ra0_antipodal]
|
|
165
|
+
dec_init = [dec0, dec0_antipodal]
|
|
145
166
|
|
|
146
167
|
H_key = next(
|
|
147
168
|
(f"H_{i}" for i in range(1, 7) if f"H_{i}" in shg1g2_params),
|
|
@@ -162,22 +183,24 @@ def get_fit_params(
|
|
|
162
183
|
0.1,
|
|
163
184
|
] # phi 0
|
|
164
185
|
|
|
165
|
-
|
|
186
|
+
SOCCA = get_fit_params(
|
|
166
187
|
data,
|
|
167
|
-
"
|
|
188
|
+
"SOCCA",
|
|
168
189
|
shg1g2_constrained=False,
|
|
169
190
|
p0=p_in,
|
|
170
191
|
terminator=terminator,
|
|
171
192
|
)
|
|
172
193
|
try:
|
|
173
|
-
rms.append(
|
|
174
|
-
model.append(
|
|
194
|
+
rms.append(SOCCA["rms"])
|
|
195
|
+
model.append(SOCCA)
|
|
175
196
|
except Exception:
|
|
176
197
|
continue
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
198
|
+
try:
|
|
199
|
+
rms = np.array(rms)
|
|
200
|
+
SOCCA_opt = model[rms.argmin()]
|
|
201
|
+
except Exception:
|
|
202
|
+
SOCCA_opt = {"Failed at SOCCA inversion": 5}
|
|
203
|
+
return SOCCA_opt
|
|
181
204
|
else:
|
|
182
205
|
period_si_t, alt_period_si_t, _ = utils.estimate_sidereal_period(
|
|
183
206
|
data=data, model_parameters=shg1g2_params, synodic_period=period_sy
|
|
@@ -238,53 +261,53 @@ def get_fit_params(
|
|
|
238
261
|
|
|
239
262
|
# Constrained Fit
|
|
240
263
|
Afit = estimate_sso_params(
|
|
241
|
-
data["cmred"].values[0]
|
|
242
|
-
data["csigmapsf"].values[0]
|
|
243
|
-
np.radians(data["Phase"].values[0]
|
|
244
|
-
data["cfid"].values[0]
|
|
245
|
-
ra=np.radians(data["ra"].values[0]
|
|
246
|
-
dec=np.radians(data["dec"].values[0]
|
|
247
|
-
jd=data["cjd"].values[0]
|
|
248
|
-
model="SSHG1G2",
|
|
264
|
+
data["cmred"].values[0],
|
|
265
|
+
data["csigmapsf"].values[0],
|
|
266
|
+
np.radians(data["Phase"].values[0]),
|
|
267
|
+
data["cfid"].values[0],
|
|
268
|
+
ra=np.radians(data["ra"].values[0]),
|
|
269
|
+
dec=np.radians(data["dec"].values[0]),
|
|
270
|
+
jd=data["cjd"].values[0],
|
|
271
|
+
model="SSHG1G2", # We should call this SOCCA
|
|
249
272
|
p0=p0,
|
|
250
273
|
)
|
|
251
274
|
return Afit
|
|
252
275
|
|
|
253
276
|
if shg1g2_constrained is False:
|
|
254
277
|
if p0 is None:
|
|
255
|
-
print("Initialize
|
|
278
|
+
print("Initialize SOCCA first!")
|
|
256
279
|
if p0 is not None:
|
|
257
280
|
if terminator:
|
|
258
281
|
Afit = estimate_sso_params(
|
|
259
|
-
data["cmred"].values[0]
|
|
260
|
-
data["csigmapsf"].values[0]
|
|
261
|
-
np.radians(data["Phase"].values[0]
|
|
262
|
-
data["cfid"].values[0]
|
|
263
|
-
ra=np.radians(data["ra"].values[0]
|
|
264
|
-
dec=np.radians(data["dec"].values[0]
|
|
265
|
-
jd=data["cjd"].values[0]
|
|
282
|
+
data["cmred"].values[0],
|
|
283
|
+
data["csigmapsf"].values[0],
|
|
284
|
+
np.radians(data["Phase"].values[0]),
|
|
285
|
+
data["cfid"].values[0],
|
|
286
|
+
ra=np.radians(data["ra"].values[0]),
|
|
287
|
+
dec=np.radians(data["dec"].values[0]),
|
|
288
|
+
jd=data["cjd"].values[0],
|
|
266
289
|
model="SSHG1G2",
|
|
267
290
|
p0=p0,
|
|
268
291
|
terminator=terminator,
|
|
269
|
-
ra_s=np.radians(data["ra_s"].values[0]
|
|
270
|
-
dec_s=np.radians(data["dec_s"].values[0]
|
|
292
|
+
ra_s=np.radians(data["ra_s"].values[0]),
|
|
293
|
+
dec_s=np.radians(data["dec_s"].values[0]),
|
|
271
294
|
)
|
|
272
295
|
else:
|
|
273
296
|
Afit = estimate_sso_params(
|
|
274
|
-
data["cmred"].values[0]
|
|
275
|
-
data["csigmapsf"].values[0]
|
|
276
|
-
np.radians(data["Phase"].values[0]
|
|
277
|
-
data["cfid"].values[0]
|
|
278
|
-
ra=np.radians(data["ra"].values[0]
|
|
279
|
-
dec=np.radians(data["dec"].values[0]
|
|
280
|
-
jd=data["cjd"].values[0]
|
|
297
|
+
data["cmred"].values[0],
|
|
298
|
+
data["csigmapsf"].values[0],
|
|
299
|
+
np.radians(data["Phase"].values[0]),
|
|
300
|
+
data["cfid"].values[0],
|
|
301
|
+
ra=np.radians(data["ra"].values[0]),
|
|
302
|
+
dec=np.radians(data["dec"].values[0]),
|
|
303
|
+
jd=data["cjd"].values[0],
|
|
281
304
|
model="SSHG1G2",
|
|
282
305
|
p0=p0,
|
|
283
306
|
terminator=terminator,
|
|
284
307
|
)
|
|
285
308
|
return Afit
|
|
286
|
-
if flavor not in ["SHG1G2", "
|
|
287
|
-
print("Model must either be SHG1G2 or
|
|
309
|
+
if flavor not in ["SHG1G2", "SOCCA"]:
|
|
310
|
+
print("Model must either be SHG1G2 or SOCCA, not {}".format(flavor))
|
|
288
311
|
|
|
289
312
|
|
|
290
313
|
def get_model_points(data, params):
|
|
@@ -122,7 +122,7 @@ def get_period_estimate(residuals_dataframe, p_min=0.03, p_max=2):
|
|
|
122
122
|
)
|
|
123
123
|
|
|
124
124
|
|
|
125
|
-
def
|
|
125
|
+
def get_multiterm_period_estimate(
|
|
126
126
|
residuals_dataframe, p_min=0.03, p_max=2, k_free=True, k_val=None
|
|
127
127
|
):
|
|
128
128
|
"""
|
|
@@ -337,7 +337,7 @@ def perform_residual_resampling(resid_df, p_min, p_max, k=1):
|
|
|
337
337
|
----------
|
|
338
338
|
resid_df : pandas.DataFrame
|
|
339
339
|
DataFrame of residuals containing columns required for `get_period_estimate`
|
|
340
|
-
or `
|
|
340
|
+
or `get_multiterm_period_estimate`.
|
|
341
341
|
p_min : float
|
|
342
342
|
Minimum period to search (days).
|
|
343
343
|
p_max : float
|
|
@@ -356,7 +356,7 @@ def perform_residual_resampling(resid_df, p_min, p_max, k=1):
|
|
|
356
356
|
Notes
|
|
357
357
|
-----
|
|
358
358
|
- Performs 25 bootstrap resamples by default.
|
|
359
|
-
- For k=1, uses `get_period_estimate`; for k>1, uses `
|
|
359
|
+
- For k=1, uses `get_period_estimate`; for k>1, uses `get_multiterm_period_estimate`.
|
|
360
360
|
"""
|
|
361
361
|
|
|
362
362
|
if k == 1:
|
|
@@ -373,13 +373,13 @@ def perform_residual_resampling(resid_df, p_min, p_max, k=1):
|
|
|
373
373
|
cond = np.abs(Pog - Pbs) / Pog < 1e-2
|
|
374
374
|
Nbs = np.sum(np.ones(25)[cond])
|
|
375
375
|
if k > 1:
|
|
376
|
-
Pog, _, _ = 24 /
|
|
376
|
+
Pog, _, _ = 24 / get_multiterm_period_estimate(
|
|
377
377
|
resid_df, p_min=p_min, p_max=p_max, k_free=False, k_val=k
|
|
378
378
|
)
|
|
379
379
|
Pbs = np.zeros(25)
|
|
380
380
|
for n in range(25):
|
|
381
381
|
BS_df = resid_df.sample(n=len(resid_df), replace=True)
|
|
382
|
-
Pbs[n], _, _ = 24 /
|
|
382
|
+
Pbs[n], _, _ = 24 / get_multiterm_period_estimate(
|
|
383
383
|
BS_df, p_min=p_min, p_max=p_max, k_free=False, k_val=k
|
|
384
384
|
)
|
|
385
385
|
cond = np.abs(Pog - Pbs) / Pog < 1e-2
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
asteroid_spinprops/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
asteroid_spinprops/ssolib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
asteroid_spinprops/ssolib/dataprep.py,sha256=7PfkVNpLjPERkhr8dZQfN8haFCFmoeXB3fWuTSBLVuc,7848
|
|
4
|
-
asteroid_spinprops/ssolib/modelfit.py,sha256=
|
|
5
|
-
asteroid_spinprops/ssolib/periodest.py,sha256=
|
|
4
|
+
asteroid_spinprops/ssolib/modelfit.py,sha256=CM2fc_OKPrajK3Dadiny4JEkY1KuwCXqoarTx8SnYpM,16473
|
|
5
|
+
asteroid_spinprops/ssolib/periodest.py,sha256=kDWEB0fPRd5paqxNjJmigsocrAd4rydYLwxNh5sMV2U,13216
|
|
6
6
|
asteroid_spinprops/ssolib/ssptools.py,sha256=DlSgYtXenztRAtEV9d4itzp5OZMjkbXkW2yZ_Qumu4U,4490
|
|
7
7
|
asteroid_spinprops/ssolib/utils.py,sha256=BUeIP0DZ45tg5qAQML8LBM8Gbj1vn2d3PGzvgQvfq_I,11094
|
|
8
|
-
asteroid_spinprops-1.
|
|
9
|
-
asteroid_spinprops-1.
|
|
10
|
-
asteroid_spinprops-1.
|
|
8
|
+
asteroid_spinprops-1.1.2.dist-info/METADATA,sha256=Ea_ijdxK1WerLh0BSULWUQp3sn054ghbk35Chg_Ggz4,5635
|
|
9
|
+
asteroid_spinprops-1.1.2.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
10
|
+
asteroid_spinprops-1.1.2.dist-info/RECORD,,
|
|
File without changes
|