@@ -102,12 +102,12 @@ def limits(t, m, sigma, band):
102
102
t_amplitude = np .ptp (t )
103
103
m_amplitude = np .ptp (m )
104
104
105
- mean_dt = np . median ( t [ 1 :] - t [: - 1 ] )
105
+ _ , dt = t0_and_weighted_centroid_sigma ( t , m , sigma )
106
106
107
107
limits = {}
108
108
limits ["reference_time" ] = (np .min (t ) - 10 * t_amplitude , np .max (t ) + 10 * t_amplitude )
109
109
limits ["amplitude" ] = (0.0 , 20 * m_amplitude )
110
- limits ["rise_time" ] = (0.1 * mean_dt , 10 * t_amplitude )
110
+ limits ["rise_time" ] = (dt / 100 , 10 * t_amplitude )
111
111
112
112
return limits
113
113
@@ -147,24 +147,13 @@ def value(t, t0, amplitude, rise_time, fall_time):
147
147
148
148
@staticmethod
149
149
def initial_guesses (t , m , sigma , band ):
150
- A = np .ptp (m )
151
-
152
- mc = m - np .min (m ) # To avoid crashing on all-negative data
150
+ A = 1.5 * max (np .max (m ), np .ptp (m ))
153
151
154
- # Naive peak position from the highest point
155
- t0 = t [np .argmax (m )]
156
- # Peak position as weighted centroid of everything above median
157
- idx = m > np .median (m )
158
- # t0 = np.sum(t[idx] * m[idx] / sigma[idx]) / np.sum(m[idx] / sigma[idx])
159
- # Weighted centroid sigma
160
- dt = np .sqrt (np .sum ((t [idx ] - t0 ) ** 2 * (mc [idx ]) / sigma [idx ]) / np .sum (mc [idx ] / sigma [idx ]))
152
+ t0 , dt = t0_and_weighted_centroid_sigma (t , m , sigma )
161
153
162
154
# Empirical conversion of sigma to rise/fall times
163
- rise_time = dt / 2
164
- fall_time = dt / 2
165
-
166
- # Compensate for the difference between reference_time and peak position
167
- t0 -= np .log (fall_time / rise_time ) * rise_time * fall_time / (rise_time + fall_time )
155
+ rise_time = dt
156
+ fall_time = dt
168
157
169
158
initial = {}
170
159
initial ["reference_time" ] = t0
@@ -178,14 +167,13 @@ def initial_guesses(t, m, sigma, band):
178
167
def limits (t , m , sigma , band ):
179
168
t_amplitude = np .ptp (t )
180
169
m_amplitude = np .ptp (m )
181
-
182
- mean_dt = np .median (t [1 :] - t [:- 1 ])
170
+ _ , dt = t0_and_weighted_centroid_sigma (t , m , sigma )
183
171
184
172
limits = {}
185
173
limits ["reference_time" ] = (np .min (t ) - 10 * t_amplitude , np .max (t ) + 10 * t_amplitude )
186
174
limits ["amplitude" ] = (0.0 , 20 * m_amplitude )
187
- limits ["rise_time" ] = (0.1 * mean_dt , 10 * t_amplitude )
188
- limits ["fall_time" ] = (0.1 * mean_dt , 10 * t_amplitude )
175
+ limits ["rise_time" ] = (dt / 100 , 10 * t_amplitude )
176
+ limits ["fall_time" ] = (dt / 100 , 10 * t_amplitude )
189
177
190
178
return limits
191
179
@@ -198,7 +186,7 @@ def peak_time(t0, amplitude, rise_time, fall_time):
198
186
class LinexpBolometricTerm (BaseBolometricTerm ):
199
187
"""Linexp function, symmetric form. Generated using a prototype version of Multi-view
200
188
Symbolic Regression (Russeil et al. 2024, https://arxiv.org/abs/2402.04298) on
201
- a SLSN ZTF light curve (https://ztf.snad.space/dr17/view/821207100004043)"""
189
+ a SLSN ZTF light curve (https://ztf.snad.space/dr17/view/821207100004043). Careful not very stable guesses/limits """
202
190
203
191
@staticmethod
204
192
def parameter_names ():
@@ -226,6 +214,7 @@ def value(t, t0, amplitude, rise_time):
226
214
def initial_guesses (t , m , sigma , band ):
227
215
A = np .ptp (m )
228
216
med_dt = median_dt (t , band )
217
+ t0 , dt = t0_and_weighted_centroid_sigma (t , m , sigma )
229
218
230
219
# Compute points after or before maximum
231
220
peak_time = t [np .argmax (m )]
@@ -276,7 +265,6 @@ def parameter_scalings():
276
265
@staticmethod
277
266
def value (t , t0 , amplitude , time1 , time2 , p ):
278
267
dt = t - t0
279
-
280
268
result = np .zeros_like (dt )
281
269
282
270
# To avoid numerical overflows
@@ -290,37 +278,34 @@ def value(t, t0, amplitude, time1, time2, p):
290
278
291
279
@staticmethod
292
280
def initial_guesses (t , m , sigma , band ):
293
- A = np .ptp (m )
294
- med_dt = median_dt (t , band )
281
+ A = max ( np .max ( m ), np . ptp (m ) )
282
+ t0 , dt = t0_and_weighted_centroid_sigma (t , m , sigma )
295
283
296
- # Naive peak position from the highest point
297
- t0 = t [np .argmax (m )]
298
-
299
- # Empirical conversion of sigma to rise/fall times
300
- time1 = 50 * med_dt
301
- time2 = 50 * med_dt
284
+ # Empirical conversion of sigma to times
285
+ time1 = 2 * dt
286
+ time2 = 2 * dt
302
287
303
288
initial = {}
304
289
initial ["reference_time" ] = t0
305
290
initial ["amplitude" ] = A
306
291
initial ["time1" ] = time1
307
292
initial ["time2" ] = time2
308
- initial ["p" ] = 0. 1
293
+ initial ["p" ] = 1
309
294
310
295
return initial
311
296
312
297
@staticmethod
313
298
def limits (t , m , sigma , band ):
314
299
t_amplitude = np .ptp (t )
315
300
m_amplitude = np .ptp (m )
316
- med_dt = median_dt (t , band )
301
+ _ , dt = t0_and_weighted_centroid_sigma (t , m , sigma )
317
302
318
303
limits = {}
319
304
limits ["reference_time" ] = (np .min (t ) - 10 * t_amplitude , np .max (t ) + 10 * t_amplitude )
320
305
limits ["amplitude" ] = (0.0 , 10 * m_amplitude )
321
- limits ["time1" ] = (med_dt , 2 * t_amplitude )
322
- limits ["time2" ] = (med_dt , 2 * t_amplitude )
323
- limits ["p" ] = (1e-4 , 10 )
306
+ limits ["time1" ] = (dt / 10 , 2 * t_amplitude )
307
+ limits ["time2" ] = (dt / 10 , 2 * t_amplitude )
308
+ limits ["p" ] = (1e-2 , 100 )
324
309
325
310
return limits
326
311
@@ -336,13 +321,27 @@ def peak_time(t0, p):
336
321
337
322
def median_dt (t , band ):
338
323
# Compute the median distance between points in each band
324
+ # Caution when using this method as it might be strongly biaised because of ZTF high cadence a given day.
339
325
dt = []
340
326
for b in np .unique (band ):
341
327
dt += list (t [band == b ][1 :] - t [band == b ][:- 1 ])
342
328
med_dt = np .median (dt )
343
329
return med_dt
344
330
345
331
332
+ def t0_and_weighted_centroid_sigma (t , m , sigma ):
333
+ # To avoid crashing on all-negative data
334
+ mc = m - np .min (m )
335
+
336
+ # Peak position as weighted centroid of everything above median
337
+ idx = m > np .median (m )
338
+ t0 = np .sum (t [idx ] * m [idx ] / sigma [idx ]) / np .sum (m [idx ] / sigma [idx ])
339
+
340
+ # Weighted centroid sigma
341
+ dt = np .sqrt (np .sum ((t [idx ] - t0 ) ** 2 * (mc [idx ]) / sigma [idx ]) / np .sum (mc [idx ] / sigma [idx ]))
342
+ return t0 , dt
343
+
344
+
346
345
bolometric_terms = {
347
346
"sigmoid" : SigmoidBolometricTerm ,
348
347
"bazin" : BazinBolometricTerm ,
0 commit comments