def plotmicro(obs, par, scsc, trange=[-5, 10, 1000], **kwargs): '''------------------------------------------------------------ Description: plot the position, of lens and source star, as well as the fitted curve --------------------------------------------------------------- Input: obs: set of observations [[ra,dec],...] par: fitted parameter ------------------------------------------------------------''' time_vec = np.linspace(trange[0], trange[1], num=trange[2], endpoint=True) earth = getSun(t_0 + time_vec) loc_vec = np.stack([(scsc[0] * earth[0] - scsc[1] * earth[1])/ max(scsc[3],1e-6),\ scsc[1] * scsc[2] * earth[0] + scsc[0] * scsc[2] * earth[1] - scsc[3] * earth[2]]).T n_stars = int((len(par) - 1) / 5) plt.plot(obs[:, 0], obs[:, 1], 'x') styl = kwargs.pop('styl', '-') linewidth = kwargs.pop('linewidth', 2) for i in range(n_stars): xx = stars_position_micro(par, np.ones(1000, int) * i, time_vec, loc_vec, scsc, **kwargs) yy = stars_position_micro(par, np.ones(1000, int) * i, time_vec, loc_vec, scsc, ml=True, **kwargs) plt.plot(xx[:, 0], xx[:, 1], styl, linewidth=linewidth) plt.plot(yy[:, 0], yy[:, 1], ':', linewidth=linewidth)
gmag = np.array([Data[1][i] for i in phot]) gmag2 = [12.19, 13.6] par_col = [ 'mass', 'ra', 'dec', 'pmra', 'pmdec', 'parallax', 'ob_ra', 'ob_dec', 'ob_pmra', 'ob_pmdec', 'ob_parallax' ] par = np.array([Data[1][i] for i in par_col]) print(par) par_multi = np.vstack([par, par]) epoch = np.linspace(t_mai - t_0 - 40 / 365, t_mai - t_0 + 40 / 365, 200) epoch_vec = np.repeat(epoch.reshape(-1, 1), 2, axis=1) num = np.arange(2) scsc = sindeg(par[1]), cosdeg(par[1]), sindeg(par[2]),\ max(cosdeg(par[2]), 1e-16) earth = getSun(t_0 + epoch).T loc = np.repeat(np.stack([(scsc[0] * earth[:,0] - scsc[1] * earth[:,1])\ / max(scsc[3],1e-6),\ scsc[1] * scsc[2] * earth[:,0] + scsc[0] * scsc[2]\ * earth[:,1] - scsc[3] * earth[:,2]]).T.reshape(-1,1,2),2,axis = 1 ) num_vec = np.repeat(num.reshape(1, -1), len(epoch), axis=0) pos_vec = stars_position_micro(par_multi, num_vec.reshape(-1), epoch_vec.reshape(-1), loc_vec=loc.reshape(-1, 2), scsc=scsc, ml=True, pml=True) A = pos_vec[1][0] A = A[np.where(A != 0)]
def Fit_Motion(obs,num_vec, time_vec,obs_error = None, sc_scandir = None, loc_vec = None, unit_obs = 'deg', \ unit_pos = 'deg', unit_pm = 'mas/yr', unit_px = 'mas', exact = False,**kwargs): '''------------------------------------------------------------ Description: --------------------------------------------------------------- Input: --------------------------------------------------------------- Output: ------------------------------------------------------------''' obs_error = None if obs_error is None: obs_error = np.ones(len(num_vec)) # translate units from and to mas unit_pos_fac = unitFac('mas', unit_pos) unit_pm_fac = unitFac('mas', unit_pm) unit_px_fac = unitFac('mas', unit_px) unit_obs_fac = unitFac(unit_obs, 'mas') # calculate earth vector # calculate sin(ra),cos(ra),sin(dec),cos(dec) scsc = sindeg(obs[0,0] * unit_obs_fac / 3.6e6) , cosdeg(obs[0,0] * unit_obs_fac / 3.6e6),\ sindeg(obs[0,1] * unit_obs_fac / 3.6e6) , cosdeg(obs[0,1] * unit_obs_fac / 3.6e6) if loc_vec is None: earth = getSun(t_0 + time_vec) loc_vec = np.stack([(scsc[0] * earth[0] - scsc[1] * earth[1])/ max(scsc[3], 1e-6),\ scsc[1] * scsc[2] * earth[0] + scsc[0] * scsc[2] * earth[1] - scsc[3] * earth[2]]).T #switch to relative coordinates by subtracting ra0,dec0 (first observation) radec_0 = obs[0, :] obs_rel = (obs - radec_0.reshape(-1, 2)) * unit_obs_fac #reorder numtimeloc_vec ntl_vec = [num_vec, time_vec, loc_vec] #setup starting value for par and par0 #par = [0.5, ra1,dec1, 0,0,0] par = np.zeros(max(num_vec + 1) * 5) par0 = np.zeros(max(num_vec + 1) * 5) par0[0::5] = radec_0[0] * unit_obs_fac par0[1::5] = radec_0[1] * unit_obs_fac q = [np.where(num_vec == i)[0] for i in range(max(num_vec + 1))] index_0 = [i[0] if len(i) > 0 else -1 for i in q] par[0::5] = obs_rel[index_0, 0] par[1::5] = obs_rel[index_0, 1] qq = np.array([False if len(i) > 0 else True for i in q]) #fitting residual function if sc_scandir is None: par_res = least_squares(FitFunction_Motion,par, xtol = 3e-16 ,jac = Jacobian_Motion, \ args = (ntl_vec, obs_rel, obs_error, scsc[3])) else: par_res = least_squares(FitFunction_Motion_Scandir,par, xtol = 3e-16 ,jac = Jacobian_Motion_Scandir, \ args = (ntl_vec, sc_scandir, obs_rel, obs_error, scsc[3])) #return parameter in requested units par_res.x[0::5] = (par_res.x[0::5] + par0[0::5]) * unit_pos_fac par_res.x[1::5] = (par_res.x[1::5] + par0[1::5]) * unit_pos_fac par_res.x[2::5] = (par_res.x[2::5] + par0[2::5]) * unit_pm_fac par_res.x[3::5] = (par_res.x[3::5] + par0[3::5]) * unit_pm_fac par_res.x[4::5] = (par_res.x[4::5] + par0[4::5]) * unit_px_fac if qq.any(): par_res.x[1 + 5 * np.where(qq)[0]] = None par_res.x[2 + 5 * np.where(qq)[0]] = None par_res.x[3 + 5 * np.where(qq)[0]] = None par_res.x[4 + 5 * np.where(qq)[0]] = None par_res.x[5 + 5 * np.where(qq)[0]] = None return par_res
def Fit_Micro(obs, num_vec, time_vec, obs_error = None, sc_scandir = None, loc_vec = None, unit_obs = 'deg', \ unit_pos = 'deg', unit_pm = 'mas/yr', unit_px = 'mas', plot = False, exact = False, bounds = False, prefit_motion = False,**kwargs): '''------------------------------------------------------------ Description: Fited the stelar motion to de data --------------------------------------------------------------- Input: obs: list of observations numvec: identifier of the coresponding star time_vec: epoch of the observations obs_error: measurement errors for weigting. If none use uniform weights) sc_scandir: sin,cos of the position angle of the scan direction. for each observation If None 2D residuals are used. loc_vec: Location of Gaia. respect to the sun. If None, calculate the position from the epoch unit_**: Units of the observation, position, propermotion and parallax exact: If False, use the center of light as aproximation bounds: Use bounds for the fitting process. prefit_motion: Determine a priors from a fit without microlensing. --------------------------------------------------------------- Output: par_res: leastsquare fit results par_res.x = [mass, ra0_Lens, dec0_Lens, pmra_Lens,pmdec_Lens,px_Lens, ra0_Source1,.... ] ------------------------------------------------------------''' if obs_error is None: obs_error = np.ones(len(obs)) # translate units from and to mas unit_pos_fac = unitFac('mas', unit_pos) unit_pm_fac = unitFac('mas', unit_pm) unit_px_fac = unitFac('mas', unit_px) unit_obs_fac = unitFac(unit_obs, 'mas') # calculate sin(ra),cos(ra),sin(dec),cos(dec) scsc = sindeg(obs[0,0] * unit_obs_fac / 3.6e6) , cosdeg(obs[0,0] * unit_obs_fac / 3.6e6),\ sindeg(obs[0,1] * unit_obs_fac / 3.6e6) , cosdeg(obs[0,1] * unit_obs_fac / 3.6e6) # calculate earth vector if loc_vec is None: earth = getSun(t_0 + time_vec) loc_vec = np.stack([(scsc[0] * earth[0] - scsc[1] * earth[1])/ max(scsc[3], 1e-20),\ scsc[1] * scsc[2] * earth[0] + scsc[0] * scsc[2] * earth[1] - scsc[3] * earth[2]]).T #switch to relative coordinates by subtracting ra0,dec0 (first observation) radec_0 = obs[0, :] obs_rel = (obs - radec_0.reshape(-1, 2)) * unit_obs_fac #reorder numtimeloc_vec ntl_vec = [num_vec, time_vec, loc_vec] #setup starting value for par and par0 #par = [0.5, ra1,dec1, 0,0,0] if len(np.where(num_vec == 0)[0]) == 0: #test source only par = np.zeros(max(num_vec + 1) * 5 + 1) par0 = np.zeros(max(num_vec + 1) * 5 + 1) par0[1::5] = radec_0[0] * unit_obs_fac par0[2::5] = radec_0[1] * unit_obs_fac par[0] = 0.5 q = [np.where(num_vec == i)[0] for i in range(max(num_vec + 1))] index_0 = [i[0] if len(i) > 0 else -1 for i in q] par[1::5] = obs_rel[index_0, 0] par[2::5] = obs_rel[index_0, 1] par[2] = par[7] par[1] = par[6] #calculat preset parameters if sc_scandir is None: par_1 = least_squares(fm.FitFunction_Motion,par[1:], xtol = 3e-8 ,jac = fm.Jacobian_Motion, \ args = (ntl_vec, obs_rel, obs_error, scsc[3])) else: par_1 = least_squares(fm.FitFunction_Motion_Scandir,par[1:], xtol = 3e-8 ,jac = fm.Jacobian_Motion_Scandir, \ args = (ntl_vec, sc_scandir, obs_rel, obs_error, scsc[3])) nn = np.where(np.abs(par_1.fun) == max(np.abs(par_1.fun)))[0] mm = par_1.fun[nn] * obs_error[nn] ThetaE2 = const_Einsteinradius * const_Einsteinradius * 0.5 * 100 deltaphi = -(ThetaE2 / mm + np.sqrt(max(ThetaE2**2 / mm**2 - 8 * ThetaE2, 0))) / 2 par[1:3] = obs_rel[nn] + deltaphi * sc_scandir[nn] par[5] = 100 par[6:] = par_1.x[5:] qq = np.array([False, False]) else: par = np.zeros(max(num_vec + 1) * 5 + 1) par0 = np.zeros(max(num_vec + 1) * 5 + 1) par0[1::5] = radec_0[0] * unit_obs_fac par0[2::5] = radec_0[1] * unit_obs_fac par[0] = 0.5 if prefit_motion: if sc_scandir is None: par_res = least_squares(fm.FitFunction_Motion,par[1:], xtol = 3e-8 ,jac = fm.Jacobian_Motion, \ args = (ntl_vec, obs_rel, obs_error, scsc[3])) else: par_res = least_squares(fm.FitFunction_Motion_Scandir,par[1:], xtol = 3e-8 ,jac = fm.Jacobian_Motion_Scandir, \ args = (ntl_vec, sc_scandir, obs_rel, obs_error, scsc[3])) par0[1:] = par_res.x q = [np.where(num_vec == i)[0] for i in range(max(num_vec + 1))] index_0 = [i[0] if len(i) > 0 else -1 for i in q] par[1::5] = obs_rel[index_0, 0] par[2::5] = obs_rel[index_0, 1] qq = np.array([False if len(i) > 0 else True for i in q]) if bounds: bounds = (-np.inf, [1000, *(np.inf * np.ones(len(par) - 1))]) else: bounds = (-np.inf, np.inf) #fitting residual function if sc_scandir is None: par_res = least_squares(FitFunction_Micro,par, xtol = 3e-16 ,jac = Jacobian_Micro, bounds = bounds, \ args = (ntl_vec, obs_rel, obs_error, scsc[3], exact)) else: par_res = least_squares(FitFunction_Micro_Scandir,par, xtol = 3e-16 ,jac = Jacobian_Micro_Scandir, \ bounds = bounds, args = (ntl_vec, sc_scandir, obs_rel, obs_error, scsc[3], exact)) r = np.random.uniform() if False: cost = lambda x, i: np.sum( FitFunction_Micro_Scandir([ *par_res.x[0:i], x, *par_res.x[i + 1:] ], ntl_vec, sc_scandir, obs_rel, obs_error, scsc[3], exact)**2) xx = np.linspace(-1, 1, 1000) sfactor = [1, 1, 1, 0.1, 0.1, 1, 1, 1, 0.1, 0.1, 1] y = [ np.array([cost(x * sfactor[i] + par_res.x[i], i) for x in xx]) for i in range(11) ] par_name = [ 'mass, M_sun', 'ra1, mas', 'dec1, mas', 'pmra1, 0.1mas/yr', 'pmdec1, 0.1mas/yr', 'px1, mas', 'ra2', 'dec2', 'pmra2', 'pmdec2', 'px2' ] fig = plt.figure(figsize=(11, 10)) for i in range(11): plt.plot(xx, y[i], label=par_name[i]) plt.xlabel('delta_par') plt.ylim([0, 5 * par_res.cost]) plt.legend(fontsize=20) fig.savefig(imagepath + 'Cost_function_' + str(int(r * 10000)) + '.png') plt.close(fig) fig = plt.figure(figsize=(11, 10)) xx = np.linspace(-1000, 1000, 10000) xx2 = np.linspace(-999.999, 1000.001, 10000) y = [ np.array([cost(x * sfactor[i] + par_res.x[i], i) for x in xx]) for i in range(1) ] y2 = [ np.array([cost(x * sfactor[i] + par_res.x[i], i) for x in xx2]) for i in range(1) ] for i in range(1): plt.plot(xx, y[i] - y2[i], label=par_name[i]) fig.savefig(imagepath + 'Cost_function_' + str(int(r * 10000)) + '_2.png') plt.close(fig) if plot: plotMicro(obs_rel, par_res.x, scsc, styl = '-', linewidth=2, out_unit = 'mas', \ unit_pos = 'mas', unit_pm = 'mas/yr', unit_px = 'mas') #return parameter in requested units par_res.x[1::5] = (par_res.x[1::5] + par0[1::5]) * unit_pos_fac par_res.x[2::5] = (par_res.x[2::5] + par0[2::5]) * unit_pos_fac par_res.x[3::5] = (par_res.x[3::5] + par0[3::5]) * unit_pm_fac par_res.x[4::5] = (par_res.x[4::5] + par0[4::5]) * unit_pm_fac par_res.x[5::5] = (par_res.x[5::5] + par0[5::5]) * unit_px_fac if qq.any(): par_res.x[1 + 5 * np.where(qq)[0]] = None par_res.x[2 + 5 * np.where(qq)[0]] = None par_res.x[3 + 5 * np.where(qq)[0]] = None par_res.x[4 + 5 * np.where(qq)[0]] = None par_res.x[5 + 5 * np.where(qq)[0]] = None return par_res
def __init__(self, Stars, Epoch, ScanDir, NCCD, Mass = None,\ out_unit = 'deg', n_par_picks = None, onlysource = False,timer =False, **kwargs): '''--------------------------------------------------------------- Creats simulated sets of noice free observational Data (i.e no observational errors are included) Creats one observation for every source and every epoch (if resolvable) ------------------------------------------------------------------ Input: Stars: vector of 1 lens and multiple source stars Epoch: epoch of observation for the event ScanDir: Position angle of the scan dirrection for each epoch [rad] NCCD: Number of CCD for the observation Mass: mass of the lens out_unit: unit of the observations n_par_picks2: number of different Sets if none return one set 1 if list: [number of differne parameters, number of different masses] onlysource: returns only data of the source timer: print computing time for different steps) **kwargs: vary_par for Star.getParameters exact for StelarMotion.stars_position_micro ext_obs for resolvable ---------------------------------------------------------------''' #compunting-time-tracker cputt = [0, 0, 0] cputt[0] -= time.time() #----------------------------------------------------------------- # Determine number of different sets if n_par_picks is None: n_par = 1 n_mass = 1 elif isinstance(n_par_picks, list): n_par = n_par_picks[0] n_mass = n_par_picks[1] else: n_mass = n_par_picks n_par = n_par_picks #----------------------------------------------------------------- #----------------------------------------------------------------- #unit of the data and input parameters self.Stars = np.array(Stars) self.unit = [out_unit, *Stars[0].unit] # Number of stars self.NumStars = len(Stars) # setup Data array dat_multi = [] # setup array for multiple sets of input parameters par_multi = np.zeros((n_par, len(Stars) * 5 + 1)) # setup array for G magnitudes Gmag = np.zeros(len(Stars)) for pick in range(n_par): for i in range(len(Stars)): if i == 0: #store parameters of the lens par_multi[pick, 0:6] = Stars[i].getParameters(**kwargs) if Mass is not None: par_multi[pick, 0] = Mass elif pick % (n_par / n_mass) != 0: par_multi[pick, 0] = par_multi[pick - 1, 0] elif pick == 0: self.Mass_lens = par_multi[pick, 0] else: #store parameters of the Sources par_multi[pick, 5 * i + 1:5 * i + 6] = Stars[i].getParameters(**kwargs)[1:] # store Gmagnitude of lens and source if pick == 0: Gmag[i] = Stars[i].getMag() #----------------------------------------------------------------- #----------------------------------------------------------------- #caluclate sin(alpha),cos(alpha),sin(delta),cos(delta) if 'deg' in self.unit[1]: scsc = sindeg(par_multi[0,1]), cosdeg(par_multi[0,1]), sindeg(par_multi[0,2]),\ max(cosdeg(par_multi[0,2]), 1e-16) if 'mas' in self.unit[1]: scsc = sinmas(par_multi[0,2]), cosmas(par_multi[0,1]), sinmas(par_multi[0,2]),\ max(cosmas(par_multi[0,2]), 1e-16) if 'arcsec' in self.unit[1]: scsc = sinmas(par_multi[0,1]/1000), cosmas(par_multi[0,1]/1000), sinmas(par_multi[0,2]/1000),\ max(cosmas(par_multi[0,2]/1000), 1e-16) #----------------------------------------------------------------- cputt[0] += time.time() cputt[1] -= time.time() #----------------------------------------------------------------- # positional shift due to the parallax # calculat position of Lagrange point 2 L2 = getSun(t_0 + Epoch).T # caluate the invers Jacobean for the parallax effect loc = np.repeat(np.stack([(scsc[0] * L2[:,0] - scsc[1] * L2[:,1])\ / max(scsc[3],1e-6),\ scsc[1] * scsc[2] * L2[:,0] + scsc[0] * scsc[2]\ * L2[:,1] - scsc[3] * L2[:,2]]).T.reshape(-1,1,2),self.NumStars,axis = 1) #----------------------------------------------------------------- #----------------------------------------------------------------- # Calculat position for each star # epoch for all Stars Epoch_vec = np.repeat(Epoch.reshape(-1, 1), self.NumStars, axis=1) # identifier for all Stars num = np.arange(self.NumStars) num_vec = np.repeat(num.reshape(1, -1), len(Epoch), axis=0) # observed position of lens and sources for every parameterpick pos_vec = stars_position_micro(par_multi, num_vec.reshape(-1), Epoch_vec.reshape(-1), loc_vec=loc.reshape(-1, 2), scsc=scsc, out_unit=self.unit[0], unit_pos=self.unit[1], unit_pm=self.unit[2], unit_px=self.unit[3], **kwargs) pos_vec = pos_vec.reshape(n_par, -1, self.NumStars, 2) #----------------------------------------------------------------- #Translate NCCD and ScanDir into numpy arrays ScanDir = np.array(ScanDir) NCCD = np.array(NCCD) cputt[1] += time.time() cputt[2] -= time.time() #loop over parameter pics for k in range(n_par): #get position for this set of parameters pos_k = pos_vec[k] if onlysource: #return only the observations of the source W = np.ones((len(pos_k), len(Gmag))) W[:, 0] = 0 else: #check if lens and sources are resolvable which = resolvable(pos_k, Gmag, ScanDir, **kwargs) #store ID,alpha,delta,Epoch,ScanDir, Loc, NCCD for each resolved datapoint dat = np.hstack([which[1].reshape(-1,1),pos_k[which],Epoch[which[0]].reshape(-1,1),\ ScanDir[which[0]].reshape(-1,1),loc[which[0],0,:],NCCD[which[0]].reshape(-1,1)]) dat_multi.append(dat) cputt[2] += time.time() #print computing time if timer: print('RD: %.2f, %.2f, %.2f' % tuple(cputt)) self.data = dat_multi self.par = par_multi