forked from rpoleski/MulensModel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
example_09_gradient_fitting.py
executable file
·99 lines (81 loc) · 2.97 KB
/
example_09_gradient_fitting.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
"""
Fit point source point lens model to OB08092 using Newton-CG method from scipy.
This method requires calculating chi^2 gradient.
"""
import os
import scipy.optimize as op
import matplotlib.pyplot as plt
import MulensModel as mm
def set_parameters(theta, event, parameters_to_fit):
"""
Set values of microlensing parameters
"""
for (key, value) in zip(parameters_to_fit, theta):
setattr(event.model.parameters, key, value)
def chi2_fun(theta, event, parameters_to_fit):
"""
for given event set attributes from parameters_to_fit (list of
str) to values from theta list
"""
set_parameters(theta, event, parameters_to_fit)
return event.get_chi2()
def jacobian(theta, event, parameters_to_fit):
"""
Calculate chi^2 gradient (also called Jacobian).
Note: this implementation is robust but possibly inefficient. If
chi2_fun() is ALWAYS called before jacobian with the same parameters,
there is no need to set the parameters in event.model; also,
event.calculate_chi2_gradient() can be used instead (which avoids fitting
for the fluxes twice).
"""
set_parameters(theta, event, parameters_to_fit)
return event.get_chi2_gradient(parameters_to_fit)
# Read in the data file
file_ = os.path.join(mm.DATA_PATH, "photometry_files", "OB08092",
"phot_ob08092_O4.dat")
data = mm.MulensData(file_name=file_)
# Initialize the fit
parameters_to_fit = ["t_0", "u_0", "t_E"]
t_0 = 5380.
u_0 = 0.1
t_E = 18.
model = mm.Model({'t_0': t_0, 'u_0': u_0, 't_E': t_E})
# Link the data and the model
ev = mm.Event(datasets=data, model=model)
(source_flux_init, blend_flux_init) = ev.get_flux_for_dataset(data)
print('Initial Trial\n{0}'.format(ev.model.parameters))
print('Chi2 = {0}\n'.format(ev.get_chi2()))
# Find the best-fit parameters
initial_guess = [t_0, u_0, t_E]
result = op.minimize(
chi2_fun, x0=initial_guess, args=(ev, parameters_to_fit),
method='Newton-CG',
jac=jacobian, tol=1e-3)
(fit_t_0, fit_u_0, fit_t_E) = result.x
# Save the best-fit parameters
chi2 = chi2_fun(result.x, ev, parameters_to_fit)
(source_flux_final, blend_flux_final) = ev.get_flux_for_dataset(data)
# Output the fit parameters
msg = 'Best Fit: t_0 = {0:12.5f}, u_0 = {1:6.4f}, t_E = {2:8.3f}'
print(msg.format(fit_t_0, fit_u_0, fit_t_E))
print('Chi2 = {0:12.2f}'.format(chi2))
print('\nscipy.optimize.minimize result:')
print(result)
# Plot and compare the two models
init_model = mm.Model({'t_0': t_0, 'u_0': u_0, 't_E': t_E})
final_model = mm.Model({'t_0': fit_t_0, 'u_0': fit_u_0, 't_E': fit_t_E})
plt.figure()
init_model.plot_lc(
source_flux=source_flux_init, blend_flux=blend_flux_init,
label='Initial Trial')
final_model.plot_lc(
source_flux=source_flux_final, blend_flux=blend_flux_final,
label='Final Model')
plt.title('Difference b/w Input and Fitted Model')
plt.legend(loc='best')
# Plot the fitted model with the data
plt.figure()
ev.plot_data()
ev.plot_model(color='red')
plt.title('Data and Fitted Model')
plt.show()