@@ -34,6 +34,7 @@ def f_two_timescales(k, tau1, A1, tau2, A2):
34
34
# keep in mind to pick the tau with the bigger amplitude. see `tau_from_popt()`
35
35
return np .abs (A1 ) * np .exp (- k / tau1 ) + np .abs (A2 ) * np .exp (- k / tau2 )
36
36
37
+
37
38
def f_complex (k , tau , A , O , tauosc , B , gamma , nu , taugs , C ):
38
39
(
39
40
""":math:`|A| e^{-k/\\ tau} + B e^{-(k/\\ tau_{osc})^\\ gamma} """
@@ -50,18 +51,18 @@ def f_complex(k, tau, A, O, tauosc, B, gamma, nu, taugs, C):
50
51
51
52
def tau_from_popt (fitfunc , popt ):
52
53
"""
53
- Get the 'selected' tau from the fit parameters. This is necessary in particular
54
- for the two-timescale fit, where the chosen tau is not always the
55
- first element in popt.
56
-
57
- Parameters
58
- ----------
59
- fitfunc : callable, The fit function
60
- popt : ~numpy.ndarray, The fit parameters
61
-
62
- Returns
63
- -------
64
- tau : float
54
+ Get the 'selected' tau from the fit parameters. This is necessary in particular
55
+ for the two-timescale fit, where the chosen tau is not always the
56
+ first element in popt.
57
+
58
+ Parameters
59
+ ----------
60
+ fitfunc : callable, The fit function
61
+ popt : ~numpy.ndarray, The fit parameters
62
+
63
+ Returns
64
+ -------
65
+ tau : float
65
66
"""
66
67
67
68
if fitfunc == f_linear :
@@ -118,16 +119,19 @@ def default_fitpars(fitfunc):
118
119
elif fitfunc == f_exponential_offset :
119
120
return np .array ([(20 , 1 , 0 ), (200 , 1 , 0 ), (- 20 , 1 , 0 ), (- 50 , 1 , 0 ), (- 1 , 1 , 0 )])
120
121
elif fitfunc == f_two_timescales :
121
- res = np .array ([
122
- # tau1 A1 tau2 A2
123
- (0.1 , 0.01 , 10 , 0.01 ),
124
- (0.1 , 0.1 , 10 , 0.01 ),
125
- (0.5 , 0.01 , 10 , 0.001 ),
126
- (0.5 , 0.1 , 10 , 0.01 ),
127
- (0.1 , 0.01 , 10 , 0 ),
128
- (0.1 , 0.1 , 10 , 0 ),
129
- (0.5 , 0.01 , 10 , 0 ),
130
- (0.5 , 0.1 , 10 , 0 )])
122
+ res = np .array (
123
+ [
124
+ # tau1 A1 tau2 A2
125
+ (0.1 , 0.01 , 10 , 0.01 ),
126
+ (0.1 , 0.1 , 10 , 0.01 ),
127
+ (0.5 , 0.01 , 10 , 0.001 ),
128
+ (0.5 , 0.1 , 10 , 0.01 ),
129
+ (0.1 , 0.01 , 10 , 0 ),
130
+ (0.1 , 0.1 , 10 , 0 ),
131
+ (0.5 , 0.01 , 10 , 0 ),
132
+ (0.5 , 0.1 , 10 , 0 ),
133
+ ]
134
+ )
131
135
return res
132
136
elif fitfunc == f_complex :
133
137
res = np .array (
@@ -233,23 +237,37 @@ def fitpars_check(pars, fitfunc):
233
237
234
238
235
239
def fitfunc_check (f ):
236
- if f is f_linear or \
237
- str (f ).lower () in ['f_linear' , 'linear' , 'lin' , 'l' ]:
238
- return f_linear
239
- elif f is f_exponential or \
240
- str (f ).lower () in ['f_exponential' , 'exponential' , 'exp' , 'e' ]:
241
- return f_exponential
242
- elif f is f_exponential_offset or \
243
- str (f ).lower () in ['f_exponential_offset' , 'exponentialoffset' ,
244
- 'exponential_offset' ,'offset' , 'exp_off' , 'exp_offset' , 'exp_offs' , 'eo' ]:
245
- return f_exponential_offset
246
- elif f is f_two_timescales or \
247
- str (f ).lower () in ['f_two_timescales' , 'two_ts' , 'two_timescales' , 'f_two_ts' , 'double_exp' ]:
248
- return f_two_timescales
249
- elif f is f_complex or \
250
- str (f ).lower () in ['f_complex' , 'complex' , 'cplx' , 'c' ]:
251
- return f_complex
252
- elif callable (f ) or hasattr (f , '__call__' ) :
240
+ if f is f_linear or str (f ).lower () in ["f_linear" , "linear" , "lin" , "l" ]:
241
+ return f_linear
242
+ elif f is f_exponential or str (f ).lower () in [
243
+ "f_exponential" ,
244
+ "exponential" ,
245
+ "exp" ,
246
+ "e" ,
247
+ ]:
248
+ return f_exponential
249
+ elif f is f_exponential_offset or str (f ).lower () in [
250
+ "f_exponential_offset" ,
251
+ "exponentialoffset" ,
252
+ "exponential_offset" ,
253
+ "offset" ,
254
+ "exp_off" ,
255
+ "exp_offset" ,
256
+ "exp_offs" ,
257
+ "eo" ,
258
+ ]:
259
+ return f_exponential_offset
260
+ elif f is f_two_timescales or str (f ).lower () in [
261
+ "f_two_timescales" ,
262
+ "two_ts" ,
263
+ "two_timescales" ,
264
+ "f_two_ts" ,
265
+ "double_exp" ,
266
+ ]:
267
+ return f_two_timescales
268
+ elif f is f_complex or str (f ).lower () in ["f_complex" , "complex" , "cplx" , "c" ]:
269
+ return f_complex
270
+ elif callable (f ) or callable (f ):
253
271
return f
254
272
else :
255
273
log .exception (f"{ f } of type { type (f ).__name__ } is not a valid fit function." )
@@ -682,18 +700,15 @@ def fit(
682
700
ic = (
683
701
f"{ a :<6} = { b :8.3f} in ({ c :9.4f} , { d :9.4f} )"
684
702
for a , b , c , d in zip (
685
- ic , fitpars [0 ], fitbnds [0 , :], fitbnds [1 , :],
686
- strict = False
703
+ ic , fitpars [0 ], fitbnds [0 , :], fitbnds [1 , :], strict = False
687
704
)
688
705
)
689
706
log .debug ("First parameters:\n " + "\n " .join (ic ))
690
707
except Exception :
691
708
log .debug ("Exception when logging fitpars" , exc_info = True )
692
709
693
710
if fitpars .shape [0 ] > 1 :
694
- log .debug (
695
- f"Repeating fit with { fitpars .shape [0 ]} sets of initial parameters:"
696
- )
711
+ log .debug (f"Repeating fit with { fitpars .shape [0 ]} sets of initial parameters:" )
697
712
698
713
# ------------------------------------------------------------------ #
699
714
# Fit via scipy.curve_fit
@@ -752,8 +767,7 @@ def fitloop(ftcoefficients, ftmaxfev, fitlog=True):
752
767
pass
753
768
else :
754
769
log .warning (
755
- f"No fit converged after { maxfev } "
756
- + "iterations. Increasing to 10000"
770
+ f"No fit converged after { maxfev } " + "iterations. Increasing to 10000"
757
771
)
758
772
maxfev = 10000
759
773
fulpopt , fulpcov , ssresmin = fitloop (
@@ -823,9 +837,7 @@ def fitloop(ftcoefficients, ftmaxfev, fitlog=True):
823
837
if numboot == 0 :
824
838
log .debug ("'numboot=0' skipping bootstrapping" )
825
839
else :
826
- log .info (
827
- f"Bootstrapping { numboot } replicas ({ len (fitpars )} fits each)"
828
- )
840
+ log .info (f"Bootstrapping { numboot } replicas ({ len (fitpars )} fits each)" )
829
841
830
842
log .debug (f"fit() seeding to { seed } " )
831
843
if seed is None :
@@ -869,7 +881,7 @@ def fitloop(ftcoefficients, ftmaxfev, fitlog=True):
869
881
mrequantiles = np .nanpercentile (bsmre , quantiles * 100.0 )
870
882
871
883
tau = tau_from_popt (fitfunc , fulpopt )
872
- mre = None if tau is None else np .exp (- 1 * dt / tau )
884
+ mre = None if tau is None else np .exp (- 1 * dt / tau )
873
885
874
886
fulres = FitResult (
875
887
tau = tau ,
0 commit comments