def generate_model_lightcurve(e): """Function to produce a model lightcurve based on a parameter set fitted by pyLIMA Inputs: e Event object """ lc = e.telescopes[0].lightcurve_magnitude fit_params = e.fits[-1].model.compute_pyLIMA_parameters(e.fits[-1].fit_results) ts = np.linspace(lc[:,0].min(), lc[:,0].max(), len(lc[:,0])) reference_telescope = copy.copy(e.fits[-1].event.telescopes[0]) reference_telescope.lightcurve_magnitude = np.array([ts, [0] * len(ts), [0] * len(ts)]).T reference_telescope.lightcurve_flux = reference_telescope.lightcurve_in_flux() if e.fits[-1].model.parallax_model[0] != 'None': reference_telescope.compute_parallax(e.fits[-1].event, e.fits[-1].model.parallax_model) print_fit_params(fit_params) flux_model = e.fits[-1].model.compute_the_microlensing_model(reference_telescope, fit_params)[0] mag_model = microltoolbox.flux_to_magnitude(flux_model) return mag_model
def lightcurve_in_magnitude(self): """ Transform flux to magnitude using m = 27.4-2.5*log10(flux) convention. Transform error bar accordingly. More details in microltoolbox module. :return: the lightcurve in magnitude, lightcurve_magnitude. :rtype: array_like """ lightcurve = self.lightcurve_flux time = lightcurve[:, 0] flux = lightcurve[:, 1] error_flux = lightcurve[:, 2] magnitude = microltoolbox.flux_to_magnitude(flux) error_magnitude = microltoolbox.error_flux_to_error_magnitude( error_flux, flux) ligthcurve_magnitude = np.array([time, magnitude, error_magnitude]).T return ligthcurve_magnitude # def hidden(self): #import webbrowser #controller = webbrowser.get() #if self.name =='Mexicola': #controller.open("https://www.youtube.com/watch?v=GcQdU2qA7D4&t=1684s")
def test_flux_to_magnitude(): flux = np.array([5000, 7000, 15000]) magnitude = microltoolbox.flux_to_magnitude(flux) assert len(magnitude) == len(flux) assert magnitude[0] > magnitude[1] assert magnitude[1] > magnitude[2]
def align_telescope_lightcurve(lightcurve_telescope_flux, model_ghost, model_telescope): """Align data to the survey telescope (i.e telescope 0). :param array_like lightcurve_telescope_mag: the survey telescope in magnitude :param float fs_reference: thce survey telescope reference source flux (i.e the fitted value) :param float g_reference: the survey telescope reference blending parameter (i.e the fitted value) :param float fs_telescope: the telescope source flux (i.e the fitted value) :param float g_reference: the telescope blending parameter (i.e the fitted value) :return: the aligned to survey lightcurve in magnitude :rtype: array_like """ time = lightcurve_telescope_flux[:, 0] flux = lightcurve_telescope_flux[:, 1] error_flux = lightcurve_telescope_flux[:, 2] err_mag = microltoolbox.error_flux_to_error_magnitude(error_flux, flux) residuals = 2.5 * np.log10(model_telescope / flux) magnitude_normalised = microltoolbox.flux_to_magnitude( model_ghost) + residuals lightcurve_normalised = [time, magnitude_normalised, err_mag] lightcurve_mag_normalised = np.array(lightcurve_normalised).T return lightcurve_mag_normalised
def LM_plot_model(fit, figure_axe): """Plot the microlensing model from the fit. :param object fit: a fit object. See the microlfits for more details. :param matplotlib_axes figure_axe: a matplotlib axes correpsonding to the figure. """ pyLIMA_parameters = fit.model.compute_pyLIMA_parameters(fit.fit_results) min_time = min( [min(i.lightcurve_magnitude[:, 0]) for i in fit.event.telescopes]) max_time = max( [max(i.lightcurve_magnitude[:, 0]) for i in fit.event.telescopes]) time = np.linspace(min_time, max_time + 100, 30000) try: extra_time = np.linspace( pyLIMA_parameters.to - 2 * np.abs(pyLIMA_parameters.tE), pyLIMA_parameters.to + 2 * np.abs(pyLIMA_parameters.tE), 30000) except: extra_time = np.linspace( pyLIMA_parameters.tc - 2 * np.abs(pyLIMA_parameters.tE), pyLIMA_parameters.tc + 2 * np.abs(pyLIMA_parameters.tE), 30000) time = np.sort(np.append(time, extra_time)) reference_telescope = copy.copy(fit.event.telescopes[0]) reference_telescope.lightcurve_magnitude = np.array( [time, [0] * len(time), [0] * len(time)]).T reference_telescope.lightcurve_flux = reference_telescope.lightcurve_in_flux( ) if fit.model.parallax_model[0] != 'None': reference_telescope.compute_parallax(fit.event, fit.model.parallax_model) flux_model = fit.model.compute_the_microlensing_model( reference_telescope, pyLIMA_parameters)[0] magnitude = microltoolbox.flux_to_magnitude(flux_model) figure_axe.plot(time, magnitude, '--k', label=fit.model.model_type, lw=2) figure_axe.set_ylim([ min(magnitude) - plot_lightcurve_windows, max(magnitude) + plot_lightcurve_windows ]) try: figure_axe.set_xlim([ pyLIMA_parameters.to - 3 * np.abs(pyLIMA_parameters.tE), pyLIMA_parameters.to + 3 * np.abs(pyLIMA_parameters.tE) + 100 ]) except: figure_axe.set_xlim([ pyLIMA_parameters.tc - 3 * np.abs(pyLIMA_parameters.tE), pyLIMA_parameters.tc + 3 * np.abs(pyLIMA_parameters.tE) + 100 ]) figure_axe.invert_yaxis() figure_axe.text(0.01, 0.96, 'provided by pyLIMA', style='italic', fontsize=10, transform=figure_axe.transAxes)
def generate_model_lightcurve(e, ts=None, diagnostics=False): """Function to produce a model lightcurve based on a parameter set fitted by pyLIMA Inputs: e Event object, with attributed lightcurve data and model fit(s) """ lc = e.telescopes[0].lightcurve_magnitude fit_params = e.fits[-1].model.compute_pyLIMA_parameters( e.fits[-1].fit_results) if type(ts) != type(np.zeros(1)): ts = np.linspace(lc[:, 0].min(), lc[:, 0].max(), len(lc[:, 0])) reference_telescope = copy.copy(e.fits[-1].event.telescopes[0]) reference_telescope.lightcurve_magnitude = np.array( [ts, [0] * len(ts), [0] * len(ts)]).T reference_telescope.lightcurve_flux = reference_telescope.lightcurve_in_flux( ) if e.fits[-1].model.parallax_model[0] != 'None': reference_telescope.compute_parallax(e.fits[-1].event, e.fits[-1].model.parallax_model) flux_model = e.fits[-1].model.compute_the_microlensing_model( reference_telescope, fit_params)[0] mag_model = microltoolbox.flux_to_magnitude(flux_model) if diagnostics: fig = plt.figure(1, (10, 10)) plt.plot(ts, mag_model, 'r-') plt.xlabel('HJD') plt.ylabel('Magnitude') rev_yaxis = True if rev_yaxis: [xmin, xmax, ymin, ymax] = plt.axis() plt.axis([xmin, xmax, ymax, ymin]) plt.grid() plt.savefig('lc_model_test.png') plt.close(1) return mag_model
def lightcurve_in_magnitude(self): """ Transform flux to magnitude using m = 27.4-2.5*log10(flux) convention. Transform error bar accordingly. More details in microltoolbox module. :return: the lightcurve in magnitude, lightcurve_magnitude. :rtype: array_like """ lightcurve = self.lightcurve_flux time = lightcurve[:, 0] flux = lightcurve[:, 1] error_flux = lightcurve[:, 2] magnitude = microltoolbox.flux_to_magnitude(flux) error_magnitude = microltoolbox.error_flux_to_error_magnitude(error_flux, flux) ligthcurve_magnitude = np.array([time, magnitude, error_magnitude]).T return ligthcurve_magnitude
def MCMC_plot_model(fit, reference_telescope, parameters, couleurs, figure_axes, scalar_couleur_map): """ Plot a model to a given figure, with the color corresponding to the objective function of the model. :param fit: a fit object. See the microlfits for more details. :param parameters: the parameters [list] of the model you want to plot. :param couleurs: the values of the objective function for the model that match the color table scalar_couleur_map :param figure_axes: the axes where the plot are draw :param scalar_couleur_map: a matplotlib table that return a color given a scalar value (the objective function here) """ pyLIMA_parameters = fit.model.compute_pyLIMA_parameters(parameters) flux_model = fit.model.compute_the_microlensing_model( reference_telescope, pyLIMA_parameters)[0] magnitude_model = microltoolbox.flux_to_magnitude(flux_model) figure_axes.plot(reference_telescope.lightcurve_magnitude[:, 0], magnitude_model, color=scalar_couleur_map.to_rgba(couleurs), alpha=0.5)
def initial_guess_PSPL(event): """Function to find initial PSPL guess for Levenberg-Marquardt solver (method=='LM'). This assumes no blending. :param object event: the event object on which you perform the fit on. More details on the event module. :return: the PSPL guess for this event. A list of parameters associated to the PSPL model + the source flux of :return: the PSPL guess for this event. A list of parameters associated to the PSPL model + the source flux of the survey telescope. :rtype: list,float """ # to estimation to_estimations = [] maximum_flux_estimations = [] errors_magnitude = [] for telescope in event.telescopes: # Lot of process here, if one fails, just skip lightcurve_magnitude = telescope.lightcurve_magnitude mean_error_magnitude = np.mean(lightcurve_magnitude[:, 2]) try: # only the best photometry good_photometry_indexes = np.where((lightcurve_magnitude[:, 2] < max(0.1, mean_error_magnitude)))[0] lightcurve_bis = lightcurve_magnitude[good_photometry_indexes] lightcurve_bis = lightcurve_bis[lightcurve_bis[:, 0].argsort(), :] mag = lightcurve_bis[:, 1] flux = microltoolbox.magnitude_to_flux(mag) # clean the lightcurve using Savitzky-Golay filter on 3 points, degree 1. mag_clean = ss.savgol_filter(mag, 3, 1) time = lightcurve_bis[:, 0] flux_clean = microltoolbox.flux_to_magnitude(mag_clean) errmag = lightcurve_bis[:, 2] flux_source = min(flux_clean) good_points = np.where(flux_clean > flux_source)[0] while (np.std(time[good_points]) > 5) | (len(good_points) > 100): indexes = \ np.where((flux_clean[good_points] > np.median(flux_clean[good_points])) & ( errmag[good_points] <= max(0.1, 2.0 * np.mean(errmag[good_points]))))[0] if len(indexes) < 1: break else: good_points = good_points[indexes] # gravity = ( # np.median(time[good_points]), np.median(flux_clean[good_points]), # np.mean(errmag[good_points])) # distances = np.sqrt((time[good_points] - gravity[0]) ** 2 / gravity[0] ** 2) to = np.median(time[good_points]) max_flux = max(flux[good_points]) to_estimations.append(to) maximum_flux_estimations.append(max_flux) errors_magnitude.append(np.mean(lightcurve_bis[good_points, 2])) except: time = lightcurve_magnitude[:, 0] flux = microltoolbox.magnitude_to_flux(lightcurve_magnitude[:, 1]) to = np.median(time) max_flux = max(flux) to_estimations.append(to) maximum_flux_estimations.append(max_flux) errors_magnitude.append(mean_error_magnitude) to_guess = sum(np.array(to_estimations) / np.array(errors_magnitude) ** 2) / sum( 1 / np.array(errors_magnitude) ** 2) survey = event.telescopes[0] lightcurve = survey.lightcurve_magnitude lightcurve = lightcurve[lightcurve[:, 0].argsort(), :] ## fs, uo, tE estimations only one the survey telescope time = lightcurve[:, 0] flux = microltoolbox.magnitude_to_flux(lightcurve[:, 1]) errflux = microltoolbox.error_magnitude_to_error_flux(lightcurve[:, 2], flux) # fs estimation, no blend baseline_flux_0 = np.min(flux) baseline_flux = np.median(flux) while np.abs(baseline_flux_0 - baseline_flux) > 0.01 * baseline_flux: baseline_flux_0 = baseline_flux indexes = np.where((flux < baseline_flux))[0].tolist() + np.where( np.abs(flux - baseline_flux) < np.abs(errflux))[0].tolist() baseline_flux = np.median(flux[indexes]) if len(indexes) < 100: baseline_flux = np.median(flux[flux.argsort()[:100]]) break fs_guess = baseline_flux # uo estimation max_flux = maximum_flux_estimations[0] Amax = max_flux / fs_guess if (Amax < 1.0) | np.isnan(Amax): Amax = 1.1 uo_guess = np.sqrt(-2 + 2 * np.sqrt(1 - 1 / (1 - Amax ** 2))) # tE estimations tE_guesses = [] # Method 1 : flux(t_demi_amplification) = 0.5 * fs_guess * (Amax + 1) half_magnification = 0.5 * (Amax + 1) flux_demi_amplification = fs_guess * half_magnification index_plus = np.where((time > to_guess) & (flux < flux_demi_amplification))[0] index_moins = np.where((time < to_guess) & (flux < flux_demi_amplification))[0] if len(index_plus) != 0: if len(index_moins) != 0: t_demi_amplification = (time[index_plus[0]] - time[index_moins[-1]]) tE_demi_amplification = t_demi_amplification / ( 2 * np.sqrt(-2 + 2 * np.sqrt(1 + 1 / (half_magnification ** 2 - 1)) - uo_guess ** 2)) tE_guesses.append(tE_demi_amplification) else: t_demi_amplification = time[index_plus[0]] - to_guess tE_demi_amplification = t_demi_amplification / np.sqrt( -2 + 2 * np.sqrt(1 + 1 / (half_magnification ** 2 - 1)) - uo_guess ** 2) tE_guesses.append(tE_demi_amplification) else: if len(index_moins) != 0: t_demi_amplification = to_guess - time[index_moins[-1]] tE_demi_amplification = t_demi_amplification / np.sqrt( -2 + 2 * np.sqrt(1 + 1 / (half_magnification ** 2 - 1)) - uo_guess ** 2) tE_guesses.append(tE_demi_amplification) # Method 2 : flux(t_E) = fs_guess * (uo^+3)/[(uo^2+1)^0.5*(uo^2+5)^0.5] amplification_tE = (uo_guess ** 2 + 3) / ((uo_guess ** 2 + 1) ** 0.5 * np.sqrt(uo_guess ** 2 + 5)) flux_tE = fs_guess * amplification_tE index_tE_plus = np.where((flux < flux_tE) & (time > to))[0] index_tE_moins = np.where((flux < flux_tE) & (time < to))[0] if len(index_tE_moins) != 0: index_tE_moins = index_tE_moins[-1] tE_moins = to_guess - time[index_tE_moins] tE_guesses.append(tE_moins) if len(index_tE_plus) != 0: index_tE_plus = index_tE_plus[0] tE_plus = time[index_tE_plus] - to_guess tE_guesses.append(tE_plus) # Method 3 : the first points before/after to_guess that reach the baseline. Very rough # approximation ot tE. index_tE_baseline_plus = np.where((time > to) & (np.abs(flux - fs_guess) < np.abs(errflux)))[0] index_tE_baseline_moins = np.where((time < to) & (np.abs(flux - fs_guess) < np.abs(errflux)))[0] if len(index_tE_baseline_plus) != 0: tEPlus = time[index_tE_baseline_plus[0]] - to_guess tE_guesses.append(tEPlus) if len(index_tE_baseline_moins) != 0: tEMoins = to_guess - time[index_tE_baseline_moins[-1]] tE_guesses.append(tEMoins) tE_guess = np.median(tE_guesses) # safety reason, unlikely if (tE_guess < 0.1) | np.isnan(tE_guess): tE_guess = 20.0 # [to,uo,tE], fsource return [to_guess, uo_guess, tE_guess], fs_guess
def fit_PSPL_parallax(ra, dec, photometry, emag_limit=None, cores=None): # Filter orders filters_order = ['I', 'ip', 'i_ZTF', 'r_ZTF', 'R', 'g_ZTF', 'gp', 'G'] filters = np.unique(photometry[:, -1]) order = [] for fil in filters_order: mask = np.where(filters == fil)[0] if len(mask) != 0: order += mask.tolist() for fil in filters: if fil not in filters_order: mask = np.where(filters == fil)[0] if len(mask) != 0: order += mask.tolist() filters = filters[order] t0_fit, u0_fit, tE_fit, mag_source_fit, mag_blend_fit, mag_baseline_fit, chi2_fit = fit_PSPL( photometry, emag_limit=None, cores=cores) current_event = event.Event() current_event.name = 'MOP_to_fit' current_event.ra = ra current_event.dec = dec for ind, filt in enumerate(filters): if emag_limit: mask = (photometry[:, -1] == filt) & (np.abs( photometry[:, -2].astype(float)) < emag_limit) else: mask = (photometry[:, -1] == filt) lightcurve = photometry[mask, :-1].astype(float) telescope = telescopes.Telescope(name='Tel_' + str(ind), camera_filter=filt, light_curve_magnitude=lightcurve, light_curve_magnitude_dictionnary={ 'time': 0, 'mag': 1, 'err_mag': 2 }, clean_the_lightcurve='Yes') if len(lightcurve) > 5: current_event.telescopes.append(telescope) t0_par = t0_fit Model_parallax = microlmodels.create_model('PSPL', current_event, parallax=['Full', t0_par]) Model_parallax.parameters_boundaries[0] = [t0_fit - 100, t0_fit + 100] Model_parallax.parameters_boundaries[1] = [-2, 2] Model_parallax.parameters_boundaries[2] = [0.1, 500] #Model_parallax.parameters_boundaries[3] = [-1,1] #Model_parallax.parameters_boundaries[4] = [-1,1] Model_parallax.parameters_guess = [t0_fit, u0_fit, tE_fit, 0, 0] if cores != 0: import multiprocessing with multiprocessing.Pool(processes=cores) as pool: current_event.fit(Model_parallax, 'DE', DE_population_size=10, flux_estimation_MCMC='polyfit', computational_pool=pool) else: current_event.fit(Model_parallax, 'DE', DE_population_size=10, flux_estimation_MCMC='polyfit') #if (chi2_fit-current_event.fits[-1].fit_results[-1])/current_event.fits[-1].fit_results[-1]<0.1: #return [t0_fit,u0_fit,tE_fit,None,None,mag_source_fit,mag_blend_fit,mag_baseline_fit] t0_fit = current_event.fits[-1].fit_results[0] u0_fit = current_event.fits[-1].fit_results[1] tE_fit = current_event.fits[-1].fit_results[2] piEN_fit = current_event.fits[-1].fit_results[3] piEE_fit = current_event.fits[-1].fit_results[4] mag_source_fit = flux_to_mag(current_event.fits[-1].fit_results[5]) mag_blend_fit = flux_to_mag(current_event.fits[-1].fit_results[5] * current_event.fits[-1].fit_results[6]) mag_baseline_fit = flux_to_mag(current_event.fits[-1].fit_results[5] * (1 + current_event.fits[-1].fit_results[6])) if np.isnan(mag_blend_fit): mag_blend_fit = "null" microloutputs.create_the_fake_telescopes( current_event.fits[0], current_event.fits[0].fit_results[:-1]) model_telescope = current_event.fits[0].event.fake_telescopes[0] pyLIMA_parameters = Model_parallax.compute_pyLIMA_parameters( current_event.fits[0].fit_results[:-1]) flux_model = current_event.fits[0].model.compute_the_microlensing_model( model_telescope, pyLIMA_parameters)[0] magnitude = microltoolbox.flux_to_magnitude(flux_model) model_telescope.lightcurve_magnitude[:, 1] = magnitude mask = ~np.isnan(magnitude) model_telescope.lightcurve_magnitude = model_telescope.lightcurve_magnitude[ mask] try: to_return = [ np.around(t0_fit, 3), np.around(u0_fit, 5), np.around(tE_fit, 3), np.around(piEN_fit, 5), np.around(piEE_fit, 5), np.around(mag_source_fit, 3), np.around(mag_blend_fit, 3), np.around(mag_baseline_fit, 3), current_event.fits[-1].fit_covariance, model_telescope ] except: to_return = [ np.around(t0_fit, 3), np.around(u0_fit, 5), np.around(tE_fit, 3), np.around(piEN_fit, 5), np.around(piEE_fit, 5), np.around(mag_source_fit, 3), mag_blend_fit, np.around(mag_baseline_fit, 3), current_event.fits[-1].fit_covariance, model_telescope ] return to_return
def plot_model(figure_axe, fit, parameters=None, telescope_index=0, model_color='b', model_alpha=1.0, label=True, bokeh_plot=None): """Plot the microlensing model corresponding to parameters, time and with the same properties as telescope, the best fit and first telescope. :param object fit: a fit object. See the microlfits for more details. :param matplotlib_axes figure_axe: a matplotlib axes correpsonding to the figure. :param list parameters : a list of model parameters. :param np.array time : the time stamps for the model. :param int telescope_index : which telescope you want a model (depends on filter, location etc...) :param str model_color : the model color :param float model_alpha : the intensity of the model line """ if parameters is not None: pyLIMA_parameters = fit.model.compute_pyLIMA_parameters(parameters) else: pyLIMA_parameters = fit.model.compute_pyLIMA_parameters( fit.fit_results) telescope = fit.event.fake_telescopes[telescope_index] time = telescope.lightcurve_flux[:, 0] flux_model = fit.model.compute_the_microlensing_model( telescope, pyLIMA_parameters)[0] magnitude = microltoolbox.flux_to_magnitude(flux_model) if label == True: figure_axe.plot(time, magnitude, c=model_color, label=fit.model.model_type, lw=3, alpha=model_alpha) else: figure_axe.plot(time, magnitude, c=model_color, lw=3, alpha=model_alpha) if telescope_index == 0: figure_axe.set_ylim([ min(magnitude) - plot_lightcurve_windows, max(magnitude) + plot_lightcurve_windows ]) figure_axe.set_xlim([ pyLIMA_parameters.to - 2 * np.abs(pyLIMA_parameters.tE), pyLIMA_parameters.to + 2 * np.abs(pyLIMA_parameters.tE) ]) figure_axe.invert_yaxis() if bokeh_plot is not None: if label == True: bokeh_plot.line(time, magnitude, color=model_color, alpha=model_alpha, legend=fit.model.model_type) else: bokeh_plot.line(time, magnitude, color=model_color, alpha=model_alpha)
def plot_mulens(n_clicks, object_data): """ Fit for microlensing event TODO: implement a fit using pyLIMA """ if n_clicks is not None: pdf_ = pd.read_json(object_data) cols = [ 'i:jd', 'i:magpsf', 'i:sigmapsf', 'i:fid', 'i:ra', 'i:dec', 'i:magnr', 'i:sigmagnr', 'i:magzpsci', 'i:isdiffpos', 'i:objectId' ] pdf = pdf_.loc[:, cols] pdf['i:fid'] = pdf['i:fid'].astype(str) pdf = pdf.sort_values('i:jd', ascending=False) mag_dc, err_dc = np.transpose([ dc_mag(*args) for args in zip( pdf['i:fid'].astype(int).values, pdf['i:magpsf'].astype( float).values, pdf['i:sigmapsf'].astype(float).values, pdf['i:magnr'].astype(float).values, pdf['i:sigmagnr'].astype( float).values, pdf['i:magzpsci'].astype( float).values, pdf['i:isdiffpos'].values) ]) current_event = event.Event() current_event.name = pdf['i:objectId'].values[0] current_event.ra = pdf['i:ra'].values[0] current_event.dec = pdf['i:dec'].values[0] filts = {'1': 'g', '2': 'r'} for fid in np.unique(pdf['i:fid'].values): mask = pdf['i:fid'].values == fid telescope = telescopes.Telescope( name='ztf_{}'.format(filts[fid]), camera_filter=format(filts[fid]), light_curve_magnitude=np.transpose([ pdf['i:jd'].values[mask], pdf['i:magpsf'].values[mask], pdf['i:sigmapsf'].values[mask] ]), light_curve_magnitude_dictionnary={ 'time': 0, 'mag': 1, 'err_mag': 2 }) current_event.telescopes.append(telescope) # Le modele le plus simple mulens_model = microlmodels.create_model('PSPL', current_event) current_event.fit(mulens_model, 'DE') # 4 parameters dof = len(pdf) - 4 - 1 results = current_event.fits[0] normalised_lightcurves = microltoolbox.align_the_data_to_the_reference_telescope( results, 0, results.fit_results) # Model create_the_fake_telescopes(results, results.fit_results) telescope_ = results.event.fake_telescopes[0] flux_model = mulens_model.compute_the_microlensing_model( telescope_, results.model.compute_pyLIMA_parameters(results.fit_results))[0] time = telescope_.lightcurve_flux[:, 0] magnitude = microltoolbox.flux_to_magnitude(flux_model) if '1' in np.unique(pdf['i:fid'].values): plot_filt1 = { 'x': [ convert_jd(t, to='iso') for t in normalised_lightcurves[0][:, 0] ], 'y': normalised_lightcurves[0][:, 1], 'error_y': { 'type': 'data', 'array': normalised_lightcurves[0][:, 2], 'visible': True, 'color': '#1f77b4' }, 'mode': 'markers', 'name': 'g band', 'text': [ convert_jd(t, to='iso') for t in normalised_lightcurves[0][:, 0] ], 'marker': { 'size': 12, 'color': '#1f77b4', 'symbol': 'o' } } else: plot_filt1 = {} if '2' in np.unique(pdf['i:fid'].values): plot_filt2 = { 'x': [ convert_jd(t, to='iso') for t in normalised_lightcurves[1][:, 0] ], 'y': normalised_lightcurves[1][:, 1], 'error_y': { 'type': 'data', 'array': normalised_lightcurves[1][:, 2], 'visible': True, 'color': '#ff7f0e' }, 'mode': 'markers', 'name': 'r band', 'text': [ convert_jd(t, to='iso') for t in normalised_lightcurves[1][:, 0] ], 'marker': { 'size': 12, 'color': '#ff7f0e', 'symbol': 'o' } } else: plot_filt2 = {} fit_filt = { 'x': [convert_jd(float(t), to='iso') for t in time], 'y': magnitude, 'mode': 'lines', 'name': 'fit', 'showlegend': False, 'line': { 'color': '#7f7f7f', } } figure = { 'data': [fit_filt, plot_filt1, plot_filt2], "layout": layout_mulens } # fitted parameters names = results.model.model_dictionnary params = results.fit_results err = np.diag(np.sqrt(results.fit_covariance)) mulens_params = """ ```python # Fitted parameters t0: {} +/- {} (jd) tE: {} +/- {} (days) u0: {} +/- {} chi2/dof: {} ``` --- """.format(params[names['to']], err[names['to']], params[names['tE']], err[names['tE']], params[names['uo']], err[names['uo']], params[-1] / dof) return figure, mulens_params mulens_params = """ ```python # Fitted parameters t0: None tE: None u0: None chi2: None ``` --- """ return {'data': [], "layout": layout_mulens}, mulens_params