def test_lb_to_radec(): ra, dec= 120, 60. lb= bovy_coords.radec_to_lb(ra,dec,degree=True,epoch=2000.) rat, dect= bovy_coords.lb_to_radec(lb[0],lb[1],degree=True,epoch=2000.) assert numpy.fabs(ra-rat) < 10.**-10., 'lb_to_radec is not the inverse of radec_to_lb' assert numpy.fabs(dec-dect) < 10.**-10., 'lb_to_radec is not the inverse of radec_to_lb' # Also test this for degree=False lb= bovy_coords.radec_to_lb(ra/180.*numpy.pi,dec/180.*numpy.pi, degree=False,epoch=2000.) rat, dect= bovy_coords.lb_to_radec(lb[0],lb[1],degree=False,epoch=2000.) assert numpy.fabs(ra/180.*numpy.pi-rat) < 10.**-10., 'lb_to_radec is not the inverse of radec_to_lb' assert numpy.fabs(dec/180.*numpy.pi-dect) < 10.**-10., 'lb_to_radec is not the inverse of radec_to_lb' # And also test this for arrays os= numpy.ones(2) lb= bovy_coords.radec_to_lb(os*ra/180.*numpy.pi,os*dec/180.*numpy.pi, degree=False,epoch=2000.) ratdect= bovy_coords.lb_to_radec(lb[:,0],lb[:,1],degree=False,epoch=2000.) rat= ratdect[:,0] dect= ratdect[:,1] assert numpy.all(numpy.fabs(ra/180.*numpy.pi-rat) < 10.**-10.), 'lb_to_radec is not the inverse of radec_to_lb' assert numpy.all(numpy.fabs(dec/180.*numpy.pi-dect) < 10.**-10.), 'lb_to_radec is not the inverse of radec_to_lb' #Also test for a negative l l,b= 240., 60. ra,dec= bovy_coords.lb_to_radec(l,b,degree=True) lt,bt= bovy_coords.radec_to_lb(ra,dec,degree=True) assert numpy.fabs(lt-l) < 10.**-10., 'lb_to_radec is not the inverse of radec_to_lb' assert numpy.fabs(bt-b) < 10.**-10., 'lb_to_radec is not the inverse of radec_to_lb' return None
def process_mock_densdata(options): print ("Using mock Pal 5 data from %s" % options.mockfilename) # Read and prep data for mocks xvid = numpy.loadtxt(options.mockfilename) xv = xvid[:, :6] xv = xv[numpy.argsort(xvid[:, 6])] XYZ = bovy_coords.galcenrect_to_XYZ(xv[:, 0], xv[:, 1], xv[:, 2], Xsun=R0, Zsun=0.025) lbd = bovy_coords.XYZ_to_lbd(XYZ[0], XYZ[1], XYZ[2], degree=True) radec = bovy_coords.lb_to_radec(lbd[:, 0], lbd[:, 1], degree=True) xieta = pal5_util.radec_to_pal5xieta(radec[:, 0], radec[:, 1], degree=True) # make sure the progenitor is at (0,0) xieta[:, 0] -= numpy.median(xieta[:, 0]) xieta[:, 1] -= numpy.median(xieta[:, 1]) h, e = numpy.histogram(xieta[:, 0], range=[0.2, 14.3], bins=141) xdata = numpy.arange(0.25, 14.35, 0.1) # Compute power spectrum tdata = h - 0.0 pp = Polynomial.fit(xdata, tdata, deg=options.polydeg, w=1.0 / numpy.sqrt(h + 1.0)) tdata /= pp(xdata) ll = xdata py = signal.csd(tdata, tdata, fs=1.0 / (ll[1] - ll[0]), scaling="spectrum", nperseg=len(ll))[1] py = py.real # Also compute the bispectrum Bspec, Bpx = bispectrum.bispectrum(numpy.vstack((tdata, tdata)).T, nfft=len(tdata), wind=7, nsamp=1, overlap=0) ppyr = numpy.fabs(Bspec[len(Bspec) // 2 + _BISPECIND, len(Bspec) // 2 :].real) ppyi = numpy.fabs(Bspec[len(Bspec) // 2 + _BISPECIND, len(Bspec) // 2 :].imag) return (numpy.sqrt(py * (ll[-1] - ll[0])), numpy.sqrt(h + 1.0) / pp(xdata), ppyr, ppyi)
def vdisp_trailing(sdf) -> float: """Return the velocity dispersion in km/s for the trailing tail. Parameters ---------- sdf: streamdf Returns ------- vdisp: float the width of the stream """ # Go out to RA=245 deg trackRADec_trailing = bovy_coords.lb_to_radec( sdf._interpolatedObsTrackLB[:, 0], sdf._interpolatedObsTrackLB[:, 1], degree=True, ) cindx = range(len(trackRADec_trailing))[np.argmin( np.fabs(trackRADec_trailing[:, 0] - 245.0))] ws = np.zeros(cindx) for ii, cc in enumerate(range(1, cindx + 1)): xy = [sdf._interpolatedObsTrackLB[cc, 0], None, None, None, None, None] ws[ii] = np.sqrt(sdf.gaussApprox(xy=xy, lb=True, cindx=cc)[1][2, 2]) return np.mean(ws)
def process_mock_densdata(options): print("Using mock Pal 5 data from %s" % options.mockfilename) # Read and prep data for mocks xvid= numpy.loadtxt(options.mockfilename) xv= xvid[:,:6] xv= xv[numpy.argsort(xvid[:,6])] XYZ= bovy_coords.galcenrect_to_XYZ(xv[:,0],xv[:,1],xv[:,2], Xsun=R0,Zsun=0.025) lbd= bovy_coords.XYZ_to_lbd(XYZ[0],XYZ[1],XYZ[2],degree=True) radec= bovy_coords.lb_to_radec(lbd[:,0],lbd[:,1],degree=True) xieta= pal5_util.radec_to_pal5xieta(radec[:,0],radec[:,1],degree=True) # make sure the progenitor is at (0,0) xieta[:,0]-= numpy.median(xieta[:,0]) xieta[:,1]-= numpy.median(xieta[:,1]) h,e= numpy.histogram(xieta[:,0],range=[0.2,14.3],bins=141) xdata= numpy.arange(0.25,14.35,0.1) # Compute power spectrum tdata= h-0. pp= Polynomial.fit(xdata,tdata,deg=options.polydeg,w=1./numpy.sqrt(h+1.)) tdata/= pp(xdata) ll= xdata py= signal.csd(tdata,tdata,fs=1./(ll[1]-ll[0]),scaling='spectrum', nperseg=len(ll))[1] py= py.real # Also compute the bispectrum Bspec, Bpx= bispectrum.bispectrum(numpy.vstack((tdata,tdata)).T, nfft=len(tdata),wind=7,nsamp=1,overlap=0) ppyr= numpy.fabs(Bspec[len(Bspec)//2+_BISPECIND,len(Bspec)//2:].real) ppyi= numpy.fabs(Bspec[len(Bspec)//2+_BISPECIND,len(Bspec)//2:].imag) return (numpy.sqrt(py*(ll[-1]-ll[0])),numpy.sqrt(h+1.)/pp(xdata), ppyr,ppyi)
def get_track_RADec(*sdfs): """get_track_RaDec. Parameters ---------- *sdfs : streamdf(s) Returns ------- trackRADec(s) : (n, 2) array, or list of trackRADecs the track in ra, dec of the streamdf """ if len(sdfs) == 0: raise ValueError trackRADec = [] for sdf in sdfs: trackRADec.append( lb_to_radec( sdf._interpolatedObsTrackLB[:, 0], sdf._interpolatedObsTrackLB[:, 1], degree=True, )) if len(trackRADec) == 1: return trackRADec[0] return trackRADec
def convert(): global req_params #if position given in ra & dec, convert to l & b if (req_params.get('l') == -9.999): req_params['l'], req_params['b'] = b_c.radec_to_lb(req_params['ra'], req_params['dec'], degree=True, epoch=2000.0) #if position given in l & b, convert to ra & dec if (req_params.get('ra') == -9.999): req_params['ra'], req_params['dec'] = b_c.lb_to_radec(req_params['l'], req_params['b'], degree=True, epoch=2000.0) #if proper motion given in pmra & pmdec, convert to pml & pmb if (req_params.get('pml') == -9.999): req_params['pml'], req_params['pmb'] = b_c.pmrapmdec_to_pmllpmbb( req_params['pmra'], req_params['pmdec'], req_params['ra'], req_params['dec'], degree=True, epoch=2000.0)
def lb_to_phi12(l,b,degree=False): """ NAME: lb_to_phi12 PURPOSE: Transform Galactic coordinates (l,b) to (phi1,phi2) INPUT: l - Galactic longitude (rad or degree) b - Galactic latitude (rad or degree) degree= (False) if True, input and output are in degrees OUTPUT: (phi1,phi2) for scalar input [:,2] array for vector input HISTORY: 2014-11-04 - Written - Bovy (IAS) """ #First convert to ra and dec radec= bovy_coords.lb_to_radec(l,b) ra= radec[:,0] dec= radec[:,1] XYZ= numpy.array([numpy.cos(dec)*numpy.cos(ra), numpy.cos(dec)*numpy.sin(ra), numpy.sin(dec)]) phiXYZ= numpy.dot(_TKOP,XYZ) phi2= numpy.arcsin(phiXYZ[2]) phi1= numpy.arctan2(phiXYZ[1],phiXYZ[0]) phi1[phi1<0.]+= 2.*numpy.pi return numpy.array([phi1,phi2]).T
def convert_dens_to_obs(sdf_pepper, apars, dens, mO, dens_smooth, minxi=0.25, maxxi=14.35): """ NAME: convert_dens_to_obs PURPOSE: Convert track to observed coordinates INPUT: sdf_pepper - streampepperdf object apars - parallel angles dens - density(apars) dens_smooth - smooth density(apars) mO= (None) mean parallel frequency (1D) [needs to be set to get density on same grid as track] minxi= (0.25) minimum xi to consider OUTPUT: (xi,dens/smooth) """ mT = sdf_pepper.meanTrack(apars, _mO=mO, coord="lb") mradec = bovy_coords.lb_to_radec(mT[0], mT[1], degree=True) mxieta = pal5_util.radec_to_pal5xieta(mradec[:, 0], mradec[:, 1], degree=True) outll = numpy.arange(minxi, maxxi, 0.1) # Interpolate density ipll = interpolate.InterpolatedUnivariateSpline(mxieta[:, 0], apars) ipdens = interpolate.InterpolatedUnivariateSpline(apars, dens / dens_smooth) return (outll, ipdens(ipll(outll)))
def convert_dens_to_obs(sdf_pepper, apars, dens, mO, dens_smooth, minxi=0.25, maxxi=14.35): """ NAME: convert_dens_to_obs PURPOSE: Convert track to observed coordinates INPUT: sdf_pepper - streampepperdf object apars - parallel angles dens - density(apars) dens_smooth - smooth density(apars) mO= (None) mean parallel frequency (1D) [needs to be set to get density on same grid as track] minxi= (0.25) minimum xi to consider OUTPUT: (xi,dens/smooth) """ mT = sdf_pepper.meanTrack(apars, _mO=mO, coord='lb') mradec = bovy_coords.lb_to_radec(mT[0], mT[1], degree=True) mxieta = pal5_util.radec_to_pal5xieta(mradec[:, 0], mradec[:, 1], degree=True) outll = np.arange(minxi, maxxi, 0.1) # Interpolate density ipll = interpolate.InterpolatedUnivariateSpline(mxieta[:, 0], apars) ipdens = interpolate.InterpolatedUnivariateSpline(apars, dens / dens_smooth) return (outll, ipdens(ipll(outll)))
def sky_coords(cluster): """Get the sky coordinates of every star in the cluster Parameters ---------- cluster : class StarCluster Returns ------- ra,dec,d0,pmra,pmdec,vr0 : float on-sky positions and velocities of cluster stars History ------- 2018 - Written - Webb (UofT) """ origin0 = cluster.origin if origin0 != "galaxy": cluster.to_galaxy() x0, y0, z0 = bovy_coords.galcenrect_to_XYZ(cluster.x, cluster.y, cluster.z, Xsun=8.0, Zsun=0.025).T vx0, vy0, vz0 = bovy_coords.galcenrect_to_vxvyvz( cluster.vx, cluster.vy, cluster.vz, Xsun=8.0, Zsun=0.025, vsun=[-11.1, 244.0, 7.25], ).T l0, b0, d0 = bovy_coords.XYZ_to_lbd(x0, y0, z0, degree=True).T ra, dec = bovy_coords.lb_to_radec(l0, b0, degree=True).T vr0, pmll0, pmbb0 = bovy_coords.vxvyvz_to_vrpmllpmbb(vx0, vy0, vz0, l0, b0, d0, degree=True).T pmra, pmdec = bovy_coords.pmllpmbb_to_pmrapmdec(pmll0, pmbb0, l0, b0, degree=True).T if origin0 == "centre": cluster.to_centre() elif origin0 == "cluster": cluster.to_cluster() return ra, dec, d0, pmra, pmdec, vr0
def pmllpmbb_to_pmphi12(pmll,pmbb,l,b,degree=False): """ NAME: pmllpmbb_to_pmphi12 PURPOSE: Transform proper motions in Galactic coordinates (l,b) to (phi1,phi2) INPUT: pmll - proper motion Galactic longitude (rad or degree); contains xcosb pmbb - Galactic latitude (rad or degree) l - Galactic longitude (rad or degree) b - Galactic latitude (rad or degree) degree= (False) if True, input (l,b) are in degrees OUTPUT: (pmphi1,pmphi2) for scalar input [:,2] array for vector input HISTORY: 2014-11-04 - Written - Bovy (IAS) """ #First go to ra and dec radec= bovy_coords.lb_to_radec(l,b) ra= radec[:,0] dec= radec[:,1] pmradec= bovy_coords.pmllpmbb_to_pmrapmdec(pmll,pmbb,l,b,degree=False) pmra= pmradec[:,0] pmdec= pmradec[:,1] #Now transform ra,dec pm to phi1,phi2 phi12= lb_to_phi12(l,b,degree=False) phi1= phi12[:,0] phi2= phi12[:,1] #Build A and Aphi matrices A= numpy.zeros((3,3,len(ra))) A[0,0]= numpy.cos(ra)*numpy.cos(dec) A[0,1]= -numpy.sin(ra) A[0,2]= -numpy.cos(ra)*numpy.sin(dec) A[1,0]= numpy.sin(ra)*numpy.cos(dec) A[1,1]= numpy.cos(ra) A[1,2]= -numpy.sin(ra)*numpy.sin(dec) A[2,0]= numpy.sin(dec) A[2,1]= 0. A[2,2]= numpy.cos(dec) AphiInv= numpy.zeros((3,3,len(ra))) AphiInv[0,0]= numpy.cos(phi1)*numpy.cos(phi2) AphiInv[0,1]= numpy.cos(phi2)*numpy.sin(phi1) AphiInv[0,2]= numpy.sin(phi2) AphiInv[1,0]= -numpy.sin(phi1) AphiInv[1,1]= numpy.cos(phi1) AphiInv[1,2]= 0. AphiInv[2,0]= -numpy.cos(phi1)*numpy.sin(phi2) AphiInv[2,1]= -numpy.sin(phi1)*numpy.sin(phi2) AphiInv[2,2]= numpy.cos(phi2) TA= numpy.dot(_TKOP,numpy.swapaxes(A,0,1)) #Got lazy... trans= numpy.zeros((2,2,len(ra))) for ii in range(len(ra)): trans[:,:,ii]= numpy.dot(AphiInv[:,:,ii],TA[:,:,ii])[1:,1:] return (trans*numpy.array([[pmra,pmdec],[pmra,pmdec]])).sum(1).T
def pmphi12_to_pmllpmbb(pmphi1, pmphi2, phi1, phi2, degree=False): """ NAME: pmllpmbb_to_pmphi12 PURPOSE: Transform proper motions in (phi1,phi2) to Galactic coordinates (l,b) INPUT: pmphi1 - proper motion Galactic longitude (rad or degree); contains xcosphi2 pmphi2 - Galactic latitude (rad or degree) phi1 - phi longitude (rad or degree) phi2 - phi latitude (rad or degree) degree= (False) if True, input (phi1,phi2) are in degrees OUTPUT: (pmll,pmbb) for scalar input [:,2] array for vector input HISTORY: 2014-11-04 - Written - Bovy (IAS) """ #First go from phi12 to ra and dec lb = phi12_to_lb(phi1, phi2) radec = bovy_coords.lb_to_radec(lb[:, 0], lb[:, 1]) ra = radec[:, 0] dec = radec[:, 1] #Build A and Aphi matrices AInv = numpy.zeros((3, 3, len(ra))) AInv[0, 0] = numpy.cos(ra) * numpy.cos(dec) AInv[0, 1] = numpy.sin(ra) * numpy.cos(dec) AInv[0, 2] = numpy.sin(dec) AInv[1, 0] = -numpy.sin(ra) AInv[1, 1] = numpy.cos(ra) AInv[1, 2] = 0. AInv[2, 0] = -numpy.cos(ra) * numpy.sin(dec) AInv[2, 1] = -numpy.sin(ra) * numpy.sin(dec) AInv[2, 2] = numpy.cos(dec) Aphi = numpy.zeros((3, 3, len(ra))) Aphi[0, 0] = numpy.cos(phi1) * numpy.cos(phi2) Aphi[0, 1] = -numpy.sin(phi1) Aphi[0, 2] = -numpy.cos(phi1) * numpy.sin(phi2) Aphi[1, 0] = numpy.sin(phi1) * numpy.cos(phi2) Aphi[1, 1] = numpy.cos(phi1) Aphi[1, 2] = -numpy.sin(phi1) * numpy.sin(phi2) Aphi[2, 0] = numpy.sin(phi2) Aphi[2, 1] = 0. Aphi[2, 2] = numpy.cos(phi2) TAphi = numpy.dot(_TKOP.T, numpy.swapaxes(Aphi, 0, 1)) #Got lazy... trans = numpy.zeros((2, 2, len(ra))) for ii in range(len(ra)): trans[:, :, ii] = numpy.dot(AInv[:, :, ii], TAphi[:, :, ii])[1:, 1:] pmradec = (trans * numpy.array([[pmphi1, pmphi2], [pmphi1, pmphi2]])).sum(1).T pmra = pmradec[:, 0] pmdec = pmradec[:, 1] #Now convert to pmll return bovy_coords.pmrapmdec_to_pmllpmbb(pmra, pmdec, ra, dec)
def sky_coords(cluster): """ NAME: sky_coords PURPOSE: Get the sky coordinates of every star in the cluster INPUT: cluster - a StarCluster-class object OUTPUT: ra,dec,d0,pmra,pmdec,vr0 HISTORY: 2018 - Written - Webb (UofT) """ origin0 = cluster.origin if origin0 != "galaxy": cluster.to_galaxy() x0, y0, z0 = bovy_coords.galcenrect_to_XYZ( cluster.x, cluster.y, cluster.z, Xsun=8.0, Zsun=0.025 ).T vx0, vy0, vz0 = bovy_coords.galcenrect_to_vxvyvz( cluster.vx, cluster.vy, cluster.vz, Xsun=8.0, Zsun=0.025, vsun=[-11.1, 244.0, 7.25], ).T l0, b0, d0 = bovy_coords.XYZ_to_lbd(x0, y0, z0, degree=True).T ra, dec = bovy_coords.lb_to_radec(l0, b0, degree=True).T vr0, pmll0, pmbb0 = bovy_coords.vxvyvz_to_vrpmllpmbb( vx0, vy0, vz0, l0, b0, d0, degree=True ).T pmra, pmdec = bovy_coords.pmllpmbb_to_pmrapmdec(pmll0, pmbb0, l0, b0, degree=True).T if origin0 == "centre": cluster.to_centre() elif origin0 == "cluster": cluster.to_cluster() return ra, dec, d0, pmra, pmdec, vr0
def looks_funny(tsdf_trailing, tsdf_leading): radecs_trailing=\ bovy_coords.lb_to_radec(tsdf_trailing._interpolatedObsTrackLB[:,0], tsdf_trailing._interpolatedObsTrackLB[:,1], degree=True) if not tsdf_leading is None: radecs_leading=\ bovy_coords.lb_to_radec(tsdf_leading._interpolatedObsTrackLB[:,0], tsdf_leading._interpolatedObsTrackLB[:,1], degree=True) try: if radecs_trailing[0, 1] > 0.625: return True elif radecs_trailing[0, 1] < -0.1: return True elif numpy.any((numpy.roll(radecs_trailing[:,0],-1)-radecs_trailing[:,0])\ [(radecs_trailing[:,0] < 250.)\ *(radecs_trailing[:,1] > -1.)\ *(radecs_trailing[:,1] < 10.)] < 0.): return True elif not tsdf_leading is None and \ numpy.any((numpy.roll(radecs_leading[:,0],-1)-radecs_leading[:,0])\ [(radecs_leading[:,0] > 225.)\ *(radecs_leading[:,1] > -4.5)\ *(radecs_leading[:,1] < 0.)] > 0.): return True elif False: #numpy.isnan(width_trailing(tsdf_trailing)): return True elif numpy.isnan( tsdf_trailing.length(ang=True, coord='customra', threshold=0.3)): return True elif numpy.fabs(tsdf_trailing._dOdJpEig[0][2]\ /tsdf_trailing._dOdJpEig[0][1]) < 0.05: return True else: return False except: return True
def vdisp_trailing(sdf): """Return the velocity dispersion in km/s for the trailing tail""" # Go out to RA=245 deg trackRADec_trailing=\ bovy_coords.lb_to_radec(sdf._interpolatedObsTrackLB[:,0], sdf._interpolatedObsTrackLB[:,1], degree=True) cindx= range(len(trackRADec_trailing))[\ numpy.argmin(numpy.fabs(trackRADec_trailing[:,0]-245.))] ws = numpy.zeros(cindx) for ii, cc in enumerate(range(1, cindx + 1)): xy = [sdf._interpolatedObsTrackLB[cc, 0], None, None, None, None, None] ws[ii] = numpy.sqrt(sdf.gaussApprox(xy=xy, lb=True, cindx=cc)[1][2, 2]) return numpy.mean(ws)
def width_trailing(sdf): """Return the FWHM width in arcmin for the trailing tail""" # Go out to RA=245 deg trackRADec_trailing=\ bovy_coords.lb_to_radec(sdf._interpolatedObsTrackLB[:,0], sdf._interpolatedObsTrackLB[:,1], degree=True) cindx= range(len(trackRADec_trailing))[\ numpy.argmin(numpy.fabs(trackRADec_trailing[:,0]-245.))] ws = numpy.zeros(cindx) for ii, cc in enumerate(range(1, cindx + 1)): xy = [sdf._interpolatedObsTrackLB[cc, 0], None, None, None, None, None] ws[ii] = numpy.sqrt(sdf.gaussApprox(xy=xy, lb=True, cindx=cc)[1][0, 0]) # return 2.355*60.*ws return 2.355 * 60. * numpy.mean(ws)
def xyzuvw_to_skycoord(xyzuvw_in, solarmotion='schoenrich', reverse_x_sign=True): """Converts XYZUVW with respect to the LSR or the sun to RAdeg, DEdeg, plx, pmra, pmdec, RV Parameters ---------- xyzuvw_in: XYZUVW with respect to the LSR. solarmotion: string The reference of assumed solar motion. "schoenrich" or None if inputs are already relative to the sun. reverse_x_sign: bool Do we reverse the sign of the X co-ordinate? This is needed for dealing with galpy sign conventions. TODO: not working at all... fix this """ if solarmotion==None: xyzuvw_sun = np.zeros(6) elif solarmotion=='schoenrich': xyzuvw_sun = [0,0,25,11.1,12.24,7.25] else: raise UserWarning #Make coordinates relative to sun xyzuvw = xyzuvw_in - xyzuvw_sun #Special for the sun itself... #FIXME: This seems like a hack. #if (np.sum(xyzuvw**2) < 1) and solarmotion != None: # return [0,0,1e5, 0,0,0] #Find l, b and distance. #!!! WARNING: the X-coordinate may have to be reversed here, just like everywhere else, #because of the convention in Orbit.x(), which doesn't seem to match X. if reverse_x_sign: lbd = bovy_coords.XYZ_to_lbd(-xyzuvw[0]/1e3, xyzuvw[1]/1e3, xyzuvw[2]/1e3, degree=True) else: lbd = bovy_coords.XYZ_to_lbd(xyzuvw[0]/1e3, xyzuvw[1]/1e3, xyzuvw[2]/1e3, degree=True) radec = bovy_coords.lb_to_radec(lbd[0], lbd[1], degree=True) vrpmllpmbb = bovy_coords.vxvyvz_to_vrpmllpmbb(xyzuvw[3],xyzuvw[4], xyzuvw[5],\ lbd[0],lbd[1],lbd[2], degree=True) pmrapmdec = bovy_coords.pmllpmbb_to_pmrapmdec(vrpmllpmbb[1],vrpmllpmbb[2],lbd[0],lbd[1],degree=True) return [radec[0], radec[1], 1.0/lbd[2], pmrapmdec[0], pmrapmdec[1], vrpmllpmbb[0]]
def get_star_dx(pepperdf, n=1000, returnapar=False, returnxi=False): (Omega, angle, dt) = pepperdf.sample(n=n, returnaAdt=True) RvR = pepperdf._approxaAInv(Omega[0], Omega[1], Omega[2], angle[0], angle[1], angle[2]) vo = pepperdf._vo ro = pepperdf._ro R0 = pepperdf._R0 Zsun = pepperdf._Zsun vsun = pepperdf._vsun XYZ = bovy_coords.galcencyl_to_XYZ(RvR[0] * ro, RvR[5], RvR[3] * ro, Xsun=R0, Zsun=Zsun).T slbd = bovy_coords.XYZ_to_lbd(XYZ[0], XYZ[1], XYZ[2], degree=True) sradec = bovy_coords.lb_to_radec(slbd[:, 0], slbd[:, 1], degree=True) xieta = pal5_util.radec_to_pal5xieta(sradec[:, 0], sradec[:, 1], degree=True) l = slbd[:, 0] b = slbd[:, 1] r = slbd[:, 2] if returnapar: closesttrackindexes = np.zeros(len(r)) for i in np.arange(len(r)): closesttrackindexes[i] = pepperdf.find_closest_trackpoint( RvR[0][i], RvR[1][i], RvR[2][i], RvR[3][i], RvR[4][i], RvR[5][i], interp=True) starapar = pepperdf._interpolatedThetasTrack[( closesttrackindexes).astype(int)] return starapar if returnxi: return xieta[:, 0] else: return None
def convert_track_to_obs(apars,mO,coord): """ NAME: convert_track_to_obs PURPOSE: Convert track to observed coordinates INPUT: apars - parallel angles mO - mean parallel frequency (1D) coord - coordinate to convert to (1: eta, 2: distance, 3: vlos, 4: pmll, 5: pmbb) OUTPUT: (longitude,(track-smooth)[coord]) """ mT= sdf_pepper.meanTrack(apars,_mO=mO,coord='lb') mradec= bovy_coords.lb_to_radec(mT[0],mT[1],degree=True) mxieta= pal5_util.radec_to_pal5xieta(mradec[:,0],mradec[:,1],degree=True) mT[0]= mxieta[:,0] mT[1]= mxieta[:,1] # Interpolate ipll= interpolate.InterpolatedUnivariateSpline(mT[0],apars) ipcoord= interpolate.InterpolatedUnivariateSpline(apars,mT[coord]) outll= numpy.arange(minxi,14.35,0.1) return (outll,ipcoord(ipll(outll))-smooth_track[coord](smooth_ll(outll)))
def convertHelioCentricToRADEC(xyzuvw_hc, kpc=False): """ Generate astrometry values from cartesian coordinates centred on sun Parameters ---------- xyzuvw_hc : [6] array [kpc, kpc, kpc, km/s, km/s, km/s] Returns ------- astrometry : [6] array [RA, DEC, pi, pm_ra, pm_dec, vr] """ # if not kpc: # xyzuvw_hc = xyzuvw_hc.copy() # xyzuvw_hc[:3] /= 1e3 logging.debug("Positions is: {}".format(xyzuvw_hc[:3])) logging.debug("Velocity is: {}".format(xyzuvw_hc[3:])) lbdist = convertHelioCentricTolbdist(xyzuvw_hc) radec = bovy_coords.lb_to_radec(lbdist[0], lbdist[1], degree=True) vrpmllpmbb = bovy_coords.vxvyvz_to_vrpmllpmbb(xyzuvw_hc[3], xyzuvw_hc[4], xyzuvw_hc[5], lbdist[0], lbdist[1], lbdist[2], degree=True) pmrapmdec = bovy_coords.pmllpmbb_to_pmrapmdec(vrpmllpmbb[1], vrpmllpmbb[2], lbdist[0], lbdist[1], degree=True) return [ radec[0], radec[1], 1.0 / lbdist[2], pmrapmdec[0], pmrapmdec[1], vrpmllpmbb[0] ]
def lb_to_phi12(l,b,degree=False): """ NAME: lb_to_phi12 PURPOSE: Transform Galactic coordinates (l,b) to (phi1,phi2) INPUT: l - Galactic longitude (rad or degree) b - Galactic latitude (rad or degree) degree= (False) if True, input and output are in degrees OUTPUT: (phi1,phi2) for scalar input [:,2] array for vector input HISTORY: 2014-11-04 - Written - Bovy (IAS) """ import numpy from galpy.util import bovy_coords _TKOP= numpy.zeros((3,3)) _TKOP[0,:]= [-0.4776303088,-0.1738432154,0.8611897727] _TKOP[1,:]= [0.510844589,-0.8524449229,0.111245042] _TKOP[2,:]= [0.7147776536,0.4930681392,0.4959603976] #First convert to ra and dec radec= bovy_coords.lb_to_radec(l,b) ra= radec[:,0] dec= radec[:,1] XYZ= numpy.array([numpy.cos(dec)*numpy.cos(ra), numpy.cos(dec)*numpy.sin(ra), numpy.sin(dec)]) phiXYZ= numpy.dot(_TKOP,XYZ) phi2= numpy.arcsin(phiXYZ[2]) phi1= numpy.arctan2(phiXYZ[1],phiXYZ[0]) phi1[phi1<0.]+= 2.*numpy.pi return numpy.array([phi1,phi2]).T
def convert_dens_to_obs(apars,dens,dens_smooth,mO,poly_deg=3): """ NAME: convert_dens_to_obs PURPOSE: Convert track to observed coordinates INPUT: apars - parallel angles dens - density(apars) dens_smooth - smooth-stream density(apars) mO= (None) mean parallel frequency (1D) [needs to be set to get density on same grid as track] poly_deg= (3) degree of the polynomial to fit for the 'smooth' stream OUTPUT: (xi,dens/smooth) """ mT= sdf_pepper.meanTrack(apars,_mO=mO,coord='lb') mradec= bovy_coords.lb_to_radec(mT[0],mT[1],degree=True) mxieta= pal5_util.radec_to_pal5xieta(mradec[:,0],mradec[:,1],degree=True) outll= numpy.arange(minxi,14.35,0.1) # Interpolate density ipll= interpolate.InterpolatedUnivariateSpline(mxieta[:,0],apars) ipdens= interpolate.InterpolatedUnivariateSpline(apars,dens/dens_smooth) return (outll,ipdens(ipll(outll)))
def looks_funny(tsdf_trailing: streamdf, tsdf_leading: Optional[streamdf]) -> bool: """looks funny. Parameters ---------- tsdf_trailing tsdf_leading Returns ------- bool """ isfunny = False radecs_trailing = bovy_coords.lb_to_radec( tsdf_trailing._interpolatedObsTrackLB[:, 0], tsdf_trailing._interpolatedObsTrackLB[:, 1], degree=True, ) if tsdf_leading is not None: radecs_leading = bovy_coords.lb_to_radec( tsdf_leading._interpolatedObsTrackLB[:, 0], tsdf_leading._interpolatedObsTrackLB[:, 1], degree=True, ) try: if radecs_trailing[0, 1] > 0.625: isfunny = True elif radecs_trailing[0, 1] < -0.1: isfunny = True elif np.any( (np.roll(radecs_trailing[:, 0], -1) - radecs_trailing[:, 0])[(radecs_trailing[:, 0] < 250.0) * (radecs_trailing[:, 1] > -1.0) * (radecs_trailing[:, 1] < 10.0)] < 0.0): isfunny = True elif tsdf_leading is not None and np.any( (np.roll(radecs_leading[:, 0], -1) - radecs_leading[:, 0])[(radecs_leading[:, 0] > 225.0) * (radecs_leading[:, 1] > -4.5) * (radecs_leading[:, 1] < 0.0)] > 0.0): isfunny = True elif False: # np.isnan(width_trailing(tsdf_trailing)): # FIXME isfunny = True elif np.isnan( tsdf_trailing.length(ang=True, coord="customra", threshold=0.3)): isfunny = True elif (np.fabs(tsdf_trailing._dOdJpEig[0][2] / tsdf_trailing._dOdJpEig[0][1]) < 0.05): isfunny = True else: isfunny = False except: isfunny = True return isfunny
def to_radec(cluster, do_order=False, do_key_params=False, ro=8.0, vo=220.0): """Convert to on-sky position, proper motion, and radial velocity of cluster Parameters ---------- cluster : class StarCluster do_order : bool sort star by radius after coordinate change (default: False) do_key_params : bool call key_params to calculate key parameters after unit change (default: False) ro : float galpy radius scaling parameter vo : float galpy velocity scaling parameter Returns ------- None History: ------- 2018 - Written - Webb (UofT) """ if len(cluster.ra) == len(cluster.x): cluster.x = copy(cluster.ra) cluster.y = copy(cluster.dec) cluster.z = copy(cluster.dist) cluster.vx = copy(cluster.pmra) cluster.vy = copy(cluster.pmdec) cluster.vz = copy(cluster.vlos) cluster.units = "radec" cluster.origin = "sky" else: units0, origin0 = cluster.units, cluster.origin cluster.to_galaxy() cluster.to_kpckms() x0, y0, z0 = bovy_coords.galcenrect_to_XYZ(cluster.x, cluster.y, cluster.z, Xsun=8.0, Zsun=0.025).T cluster.dist = np.sqrt(x0**2.0 + y0**2.0 + z0**2.0) vx0, vy0, vz0 = bovy_coords.galcenrect_to_vxvyvz( cluster.vx, cluster.vy, cluster.vz, Xsun=8.0, Zsun=0.025, vsun=[-11.1, 244.0, 7.25], ).T cluster.vlos = (vx0 * x0 + vy0 * y0 + vz0 * z0) / np.sqrt(x0**2.0 + y0**2.0 + z0**2.0) l0, b0, cluster.dist = bovy_coords.XYZ_to_lbd(x0, y0, z0, degree=True).T cluster.ra, cluster.dec = bovy_coords.lb_to_radec(l0, b0, degree=True).T vr0, pmll0, pmbb0 = bovy_coords.vxvyvz_to_vrpmllpmbb(vx0, vy0, vz0, l0, b0, cluster.dist, degree=True).T cluster.pmra, cluster.pmdec = bovy_coords.pmllpmbb_to_pmrapmdec( pmll0, pmbb0, l0, b0, degree=True).T x0, y0, z0 = bovy_coords.galcenrect_to_XYZ(cluster.xgc, cluster.ygc, cluster.zgc, Xsun=8.0, Zsun=0.025) vx0, vy0, vz0 = bovy_coords.galcenrect_to_vxvyvz( cluster.vxgc, cluster.vygc, cluster.vzgc, Xsun=8.0, Zsun=0.025, vsun=[-11.1, 244.0, 7.25], ) cluster.vlos_gc = (vx0 * x0 + vy0 * y0 + vz0 * z0) / np.sqrt(x0**2.0 + y0**2.0 + z0**2.0) l0, b0, cluster.dist_gc = bovy_coords.XYZ_to_lbd(x0, y0, z0, degree=True) cluster.ra_gc, cluster.dec_gc = bovy_coords.lb_to_radec(l0, b0, degree=True) vr0, pmll0, pmbb0 = bovy_coords.vxvyvz_to_vrpmllpmbb(vx0, vy0, vz0, l0, b0, cluster.dist_gc, degree=True) cluster.pmra_gc, cluster.pmdec_gc = bovy_coords.pmllpmbb_to_pmrapmdec( pmll0, pmbb0, l0, b0, degree=True) cluster.x = copy(cluster.ra) cluster.y = copy(cluster.dec) cluster.z = copy(cluster.dist) cluster.vx = copy(cluster.pmra) cluster.vy = copy(cluster.pmdec) cluster.vz = copy(cluster.vlos) cluster.xgc = copy(cluster.ra_gc) cluster.ygc = copy(cluster.dec_gc) cluster.zgc = copy(cluster.dist_gc) cluster.vxgc = copy(cluster.pmra_gc) cluster.vygc = copy(cluster.pmdec_gc) cluster.vzgc = copy(cluster.vlos_gc) cluster.units = "radec" cluster.origin = "sky" cluster.rv3d() if do_key_params: cluster.key_params(do_order=do_order)
def predict_pal5obs(pot_params, c, b=1., pa=0., sigv=0.2, td=10., dist=23.2, pmra=-2.296, pmdec=-2.257, vlos=-58.7, ro=_REFR0, vo=_REFV0, singlec=False, interpcs=None, interpk=None, isob=None, nTrackChunks=8, multi=None, trailing_only=False, useTM=False, verbose=True): """ NAME: predict_pal5obs PURPOSE: Function that generates the location and velocity of the Pal 5 stream, its width, and its length for a given potential and progenitor phase-space position INPUT: pot_params- array with the parameters of a potential model (see MWPotential2014Likelihood.setup_potential; only the basic parameters of the disk and halo are used, flattening is specified separately) c- halo flattening b= (1.) halo-squashed pa= (0.) halo PA sigv= (0.4) velocity dispersion in km/s (can be array of same len as interpcs) td= (5.) stream age in Gyr (can be array of same len as interpcs) dist= (23.2) progenitor distance in kpc pmra= (-2.296) progenitor proper motion in RA * cos(Dec) in mas/yr pmdec= (-2.257) progenitor proper motion in Dec in mas/yr vlos= (-58.7) progenitor line-of-sight velocity in km/s ro= (project default) distance to the GC in kpc vo= (project default) circular velocity at R0 in km/s singlec= (False) if True, just compute the observables for a single c interpcs= (None) values of c at which to compute the model for interpolation nTrackChunks= (8) nTrackChunks input to streamdf multi= (None) multi input to streamdf isob= (None) if given, b parameter of actionAngleIsochroneApprox trailing_only= (False) if True, only predict the trailing arm useTM= (True) use the TorusMapper to compute the track verbose= (True) print messages OUTPUT: (trailing track in RA,Dec, leading track in RA,Dec, trailing track in RA,Vlos, leading track in RA,Vlos, trailing width in arcmin, trailing length in deg) all arrays with the shape of c HISTORY: 2016-06-24 - Written - Bovy (UofT) """ # First compute the model for all cs at which we will interpolate if singlec: interpcs = [c] elif interpcs is None: interpcs = [0.5, 0.75, 1., 1.25, 1.55, 1.75, 2., 2.25, 2.5, 2.75, 3.] else: interpcs = copy.deepcopy(interpcs) # bc we might want to remove some if isinstance(sigv, float): sigv = [sigv for i in interpcs] if isinstance(td, float): td = [td for i in interpcs] if isinstance(isob, float) or isob is None: isob = [isob for i in interpcs] prog = Orbit([229.018, -0.124, dist, pmra, pmdec, vlos], radec=True, ro=ro, vo=vo, solarmotion=[-11.1, 24., 7.25]) # Setup the model sdf_trailing_varyc = [] sdf_leading_varyc = [] ii = 0 ninterpcs = len(interpcs) this_useTM = copy.deepcopy(useTM) this_nTrackChunks = nTrackChunks ntries = 0 while ii < ninterpcs: ic = interpcs[ii] pot = MWPotential2014Likelihood.setup_potential(pot_params, ic, False, False, ro, vo, b=b, pa=pa) success = True wentIn = ntries != 0 # Make sure this doesn't run forever signal.signal(signal.SIGALRM, timeout_handler) signal.alarm(300) try: tsdf_trailing, tsdf_leading = setup_sdf( pot, prog, sigv[ii], td[ii], ro, vo, multi=multi, isob=isob[ii], nTrackChunks=this_nTrackChunks, trailing_only=trailing_only, verbose=verbose, useTM=this_useTM) except: # Catches errors and time-outs success = False signal.alarm(0) # Check for calc. issues if not success or \ (not this_useTM and looks_funny(tsdf_trailing,tsdf_leading)): # Try again with TM this_useTM = True this_nTrackChunks = 21 # might as well #wentIn= True #print("Here",ntries,success) #sys.stdout.flush() ntries += 1 else: success = not this_useTM #if wentIn: # print(success) # sys.stdout.flush() ii += 1 # reset this_useTM = useTM this_nTrackChunks = nTrackChunks ntries = 0 # Add to the list sdf_trailing_varyc.append(tsdf_trailing) sdf_leading_varyc.append(tsdf_leading) if not singlec and len(sdf_trailing_varyc) <= 1: # Almost everything bad!! return (numpy.zeros((len(c), 1001, 2)), numpy.zeros( (len(c), 1001, 2)), numpy.zeros( (len(c), 1001, 2)), numpy.zeros( (len(c), 1001, 2)), numpy.zeros( (len(c))), numpy.zeros((len(c))), [], success) # Compute the track properties for each model trackRADec_trailing= numpy.zeros((len(interpcs), sdf_trailing_varyc[0]\ .nInterpolatedTrackChunks,2)) trackRADec_leading= numpy.zeros((len(interpcs), sdf_trailing_varyc[0]\ .nInterpolatedTrackChunks,2)) trackRAVlos_trailing= numpy.zeros((len(interpcs), sdf_trailing_varyc[0]\ .nInterpolatedTrackChunks,2)) trackRAVlos_leading= numpy.zeros((len(interpcs), sdf_trailing_varyc[0]\ .nInterpolatedTrackChunks,2)) width = numpy.zeros(len(interpcs)) length = numpy.zeros(len(interpcs)) for ii in range(len(interpcs)): trackRADec_trailing[ii]= bovy_coords.lb_to_radec(\ sdf_trailing_varyc[ii]._interpolatedObsTrackLB[:,0], sdf_trailing_varyc[ii]._interpolatedObsTrackLB[:,1], degree=True) if not trailing_only: trackRADec_leading[ii]= bovy_coords.lb_to_radec(\ sdf_leading_varyc[ii]._interpolatedObsTrackLB[:,0], sdf_leading_varyc[ii]._interpolatedObsTrackLB[:,1], degree=True) trackRAVlos_trailing[ii][:, 0] = trackRADec_trailing[ii][:, 0] trackRAVlos_trailing[ii][:,1]= \ sdf_trailing_varyc[ii]._interpolatedObsTrackLB[:,3] if not trailing_only: trackRAVlos_leading[ii][:, 0] = trackRADec_leading[ii][:, 0] trackRAVlos_leading[ii][:,1]= \ sdf_leading_varyc[ii]._interpolatedObsTrackLB[:,3] width[ii] = width_trailing(sdf_trailing_varyc[ii]) length[ii]=\ sdf_trailing_varyc[ii].length(ang=True,coord='customra', threshold=0.3) if singlec: #if wentIn: # print(success) # sys.stdout.flush() return (trackRADec_trailing, trackRADec_leading, trackRAVlos_trailing, trackRAVlos_leading, width, length, interpcs, success) # Interpolate; output grids trackRADec_trailing_out= numpy.zeros((len(c),sdf_trailing_varyc[0]\ .nInterpolatedTrackChunks,2)) trackRADec_leading_out= numpy.zeros((len(c),sdf_trailing_varyc[0]\ .nInterpolatedTrackChunks,2)) trackRAVlos_trailing_out= numpy.zeros((len(c),sdf_trailing_varyc[0]\ .nInterpolatedTrackChunks,2)) trackRAVlos_leading_out= numpy.zeros((len(c),sdf_trailing_varyc[0]\ .nInterpolatedTrackChunks,2)) if interpk is None: interpk = numpy.amin([len(interpcs) - 1, 3]) for ii in range(sdf_trailing_varyc[0].nInterpolatedTrackChunks): ip= interpolate.InterpolatedUnivariateSpline(\ interpcs,trackRADec_trailing[:,ii,0],k=interpk,ext=0) trackRADec_trailing_out[:, ii, 0] = ip(c) ip= interpolate.InterpolatedUnivariateSpline(\ interpcs,trackRADec_trailing[:,ii,1],k=interpk,ext=0) trackRADec_trailing_out[:, ii, 1] = ip(c) ip= interpolate.InterpolatedUnivariateSpline(\ interpcs,trackRAVlos_trailing[:,ii,0],k=interpk,ext=0) trackRAVlos_trailing_out[:, ii, 0] = ip(c) ip= interpolate.InterpolatedUnivariateSpline(\ interpcs,trackRAVlos_trailing[:,ii,1],k=interpk,ext=0) trackRAVlos_trailing_out[:, ii, 1] = ip(c) if not trailing_only: ip= interpolate.InterpolatedUnivariateSpline(\ interpcs,trackRADec_leading[:,ii,0],k=interpk,ext=0) trackRADec_leading_out[:, ii, 0] = ip(c) ip= interpolate.InterpolatedUnivariateSpline(\ interpcs,trackRADec_leading[:,ii,1],k=interpk,ext=0) trackRADec_leading_out[:, ii, 1] = ip(c) ip= interpolate.InterpolatedUnivariateSpline(\ interpcs,trackRAVlos_leading[:,ii,0],k=interpk,ext=0) trackRAVlos_leading_out[:, ii, 0] = ip(c) ip= interpolate.InterpolatedUnivariateSpline(\ interpcs,trackRAVlos_leading[:,ii,1],k=interpk,ext=0) trackRAVlos_leading_out[:, ii, 1] = ip(c) ip= interpolate.InterpolatedUnivariateSpline(\ interpcs,width,k=interpk,ext=0) width_out = ip(c) ip= interpolate.InterpolatedUnivariateSpline(\ interpcs,length,k=interpk,ext=0) length_out = ip(c) return (trackRADec_trailing_out, trackRADec_leading_out, trackRAVlos_trailing_out, trackRAVlos_leading_out, width_out, length_out, interpcs, success)
def propagate(self, potential, dt=0.01 * u.Myr, threshold=None): ''' Propagates the sample in the Galaxy, changes cattype from 0 to 1. Parameters ---------- potential : galpy potential instance Potential instance of the galpy library used to integrate the orbits dt : Quantity Integration timestep. Defaults to 0.01 Myr threshold : float Maximum relative energy difference between the initial energy and the energy at any point needed to consider an integration step an energy outliar. E.g. for threshold=0.01, any excess or deficit of 1% (or more) of the initial energy is enough to be registered as outliar. A table E_data.fits is created in the working directory containing for every orbit the percentage of outliar points (pol) ''' from galpy.orbit import Orbit from galpy.util.bovy_coords import pmllpmbb_to_pmrapmdec, lb_to_radec, vrpmllpmbb_to_vxvyvz, lbd_to_XYZ if (self.cattype > 0): raise RuntimeError('This sample is already propagated!') if (threshold is None): check = False else: check = True # Integration time step self.dt = dt nsteps = np.ceil((self.tflight / self.dt).to('1').value) nsteps[nsteps < 100] = 100 # Initialize position in cylindrical coords rho = self.r0 * np.sin(self.theta0) z = self.r0 * np.cos(self.theta0) phi = self.phi0 #... and velocity vR = self.v0 * np.sin(self.thetav0) * np.cos(self.phiv0) vT = self.v0 * np.sin(self.thetav0) * np.sin(self.phiv0) vz = self.v0 * np.cos(self.thetav0) # Initialize empty arrays to save orbit data and integration steps self.pmll, self.pmbb, self.ll, self.bb, self.vlos, self.dist, self.energy_var = \ (np.zeros(self.size) for i in xrange(7)) self.orbits = [None] * self.size #Integration loop for the self.size orbits for i in xrange(self.size): ts = np.linspace(0, 1, nsteps[i]) * self.tflight[i] self.orbits[i] = Orbit( vxvv=[rho[i], vR[i], vT[i], z[i], vz[i], phi[i]], solarmotion=self.solarmotion) self.orbits[i].integrate(ts, potential, method='dopr54_c') # Export the final position self.dist[i], self.ll[i], self.bb[i], self.pmll[i], self.pmbb[i], self.vlos[i] = \ self.orbits[i].dist(self.tflight[i], use_physical=True), \ self.orbits[i].ll(self.tflight[i], use_physical=True), \ self.orbits[i].bb(self.tflight[i], use_physical=True), \ self.orbits[i].pmll(self.tflight[i], use_physical=True) , \ self.orbits[i].pmbb(self.tflight[i], use_physical=True) , \ self.orbits[i].vlos(self.tflight[i], use_physical=True) # Energy check if (check): energy_array = self.orbits[i].E(ts) idx_energy = np.absolute(energy_array / energy_array[0] - 1) > threshold self.energy_var[i] = float( idx_energy.sum()) / nsteps[i] # percentage of outliars # Radial velocity and distance + distance modulus self.vlos, self.dist = self.vlos * u.km / u.s, self.dist * u.kpc # Sky coordinates and proper motion data = pmllpmbb_to_pmrapmdec( self.pmll, self.pmbb, self.ll, self.bb, degree=True) * u.mas / u.year self.pmra, self.pmdec = data[:, 0], data[:, 1] data = lb_to_radec(self.ll, self.bb, degree=True) * u.deg self.ra, self.dec = data[:, 0], data[:, 1] # Done propagating self.cattype = 1 # Save the energy check information if (check): from astropy.table import Table e_data = Table([self.m, self.tflight, self.energy_var], names=['m', 'tflight', 'pol']) e_data.write('E_data.fits', overwrite=True)
plotvlos= vlos*218.-218 save_pickles(mean_savefilename, plotds,plotvlos) #Now calculate the whole vlos distribution at each d dist_savefilename= 'vhelio_l90_dist.sav' if os.path.exists(dist_savefilename): savefile= open(dist_savefilename,'rb') plotds= pickle.load(savefile) plotvloss= pickle.load(savefile) vlos_dist= pickle.load(savefile) savefile.close() else: nvloss= 101 vloss= numpy.linspace(-0.7,0.25,nvloss) vlos_dist= numpy.zeros((nds,nvloss)) ra, dec= bovy_coords.lb_to_radec(90.,0.,degree=True) for ii in range(nds): print ii for jj in range(nvloss): #Setup this Orbit o= Orbit([ra,dec,ds[ii],0.,0.,vloss[jj]], radec=True,vo=1.,ro=1.,zo=0., solarmotion=[0.,25./218.,0.]) vlos_dist[ii,jj]= dfc(o,marginalizeVperp=True) plotds= ds*8. plotvloss= vloss*218. save_pickles(dist_savefilename,plotds,plotvloss,vlos_dist) #Now plot bovy_plot.bovy_print() for ii in range(nds): vlos_dist[ii,:]/= numpy.sum(vlos_dist[ii,:])
threshold = 0.3 print("Angular length: %f deg (leading,trailing)=(%f,%f) deg" % ( sdf_leading.length(ang=True, coord="customra", threshold=threshold) + sdf_trailing.length(ang=True, coord="customra", threshold=threshold), sdf_leading.length(ang=True, coord="customra", threshold=threshold), sdf_trailing.length(ang=True, coord="customra", threshold=threshold), )) print("Angular width (FWHM): %f arcmin" % (width_trailing(sdf_trailing))) print("Velocity dispersion: %f km/s" % (pal5_util.vdisp_trailing(sdf_trailing))) # ---------------------------------------------------------- trackRADec_trailing = bovy_coords.lb_to_radec( sdf_trailing._interpolatedObsTrackLB[:, 0], sdf_trailing._interpolatedObsTrackLB[:, 1], degree=True, ) trackRADec_leading = bovy_coords.lb_to_radec( sdf_leading._interpolatedObsTrackLB[:, 0], sdf_leading._interpolatedObsTrackLB[:, 1], degree=True, ) lb_sample_trailing = sdf_trailing.sample(n=10000, lb=True) lb_sample_leading = sdf_leading.sample(n=10000, lb=True) radec_sample_trailing = bovy_coords.lb_to_radec(lb_sample_trailing[0], lb_sample_trailing[1], degree=True) radec_sample_leading = bovy_coords.lb_to_radec(lb_sample_leading[0], lb_sample_leading[1], degree=True)
def xyzuvw_to_skycoord(xyzuvw_in, solarmotion='schoenrich', reverse_x_sign=True): """Converts XYZUVW with respect to the LSR or the sun to RAdeg, DEdeg, plx, pmra, pmdec, RV Parameters ---------- xyzuvw_in: XYZUVW with respect to the LSR. solarmotion: string The reference of assumed solar motion. "schoenrich" or None if inputs are already relative to the sun. reverse_x_sign: bool Do we reverse the sign of the X co-ordinate? This is needed for dealing with galpy sign conventions. TODO: not working at all... fix this """ if solarmotion == None: xyzuvw_sun = np.zeros(6) elif solarmotion == 'schoenrich': xyzuvw_sun = [0, 0, 25, 11.1, 12.24, 7.25] else: raise UserWarning #Make coordinates relative to sun xyzuvw = xyzuvw_in - xyzuvw_sun #Special for the sun itself... #FIXME: This seems like a hack. #if (np.sum(xyzuvw**2) < 1) and solarmotion != None: # return [0,0,1e5, 0,0,0] #Find l, b and distance. #!!! WARNING: the X-coordinate may have to be reversed here, just like everywhere else, #because of the convention in Orbit.x(), which doesn't seem to match X. if reverse_x_sign: lbd = bovy_coords.XYZ_to_lbd(-xyzuvw[0] / 1e3, xyzuvw[1] / 1e3, xyzuvw[2] / 1e3, degree=True) else: lbd = bovy_coords.XYZ_to_lbd(xyzuvw[0] / 1e3, xyzuvw[1] / 1e3, xyzuvw[2] / 1e3, degree=True) radec = bovy_coords.lb_to_radec(lbd[0], lbd[1], degree=True) vrpmllpmbb = bovy_coords.vxvyvz_to_vrpmllpmbb(xyzuvw[3],xyzuvw[4], xyzuvw[5],\ lbd[0],lbd[1],lbd[2], degree=True) pmrapmdec = bovy_coords.pmllpmbb_to_pmrapmdec(vrpmllpmbb[1], vrpmllpmbb[2], lbd[0], lbd[1], degree=True) return [ radec[0], radec[1], 1.0 / lbd[2], pmrapmdec[0], pmrapmdec[1], vrpmllpmbb[0] ]
def propagate_initial(self, potential, index, dt=0.01 * u.Myr, size=100, deltav=5. * u.km / u.s, deltat=0.5 * u.Myr): ''' Propagates the index-th star and _size_ more stars with random spread in initial velocity and flight time dictated by deltav, deltat. This overwrites the original catalogue! Parameters ---------- index : int Index of the star to propagate this in. size : int dv, dt : Quantity Spread in initial velocity and See self.propagate() for the other parameters. ''' from galpy.orbit import Orbit from galpy.util.bovy_coords import pmllpmbb_to_pmrapmdec, lb_to_radec, vrpmllpmbb_to_vxvyvz, lbd_to_XYZ self.r0, self.theta0, self.phi0, self.v0, self.phiv0, self.thetav0, self.tflight, self.tage, self.m = np.ones(size)*self.r0[index], np.ones(size)*self.theta0[index], \ np.ones(size)*self.phi0[index], np.ones(size)*self.v0[index], np.ones(size)*self.phiv0[index], np.ones(size)*self.thetav0[index], \ np.ones(size)*self.tflight[index], np.ones(size)*self.tage[index], np.ones(size)*self.m[index] self.v0 = self.v0 + np.random.normal(size=size) * deltav self.tflight = self.tflight + np.random.normal(size=size) * deltat self.size = size # Integration time step self.dt = dt nsteps = np.ceil((self.tflight / self.dt).to('1').value) nsteps[nsteps < 100] = 100 # Initialize position in cylindrical coords rho = self.r0 * np.sin(self.theta0) z = self.r0 * np.cos(self.theta0) phi = self.phi0 #... and velocity vR = self.v0 * np.sin(self.thetav0) * np.cos(self.phiv0) vT = self.v0 * np.sin(self.thetav0) * np.sin(self.phiv0) vz = self.v0 * np.cos(self.thetav0) # Initialize empty arrays to save orbit data and integration steps self.pmll, self.pmbb, self.ll, self.bb, self.vlos, self.dist, self.energy_var = \ (np.zeros(self.size) for i in xrange(7)) self.orbits = [None] * self.size #Integration loop for the self.size orbits for i in xrange(self.size): ts = np.linspace(0, 1, nsteps[i]) * self.tflight[i] self.orbits[i] = Orbit( vxvv=[rho[i], vR[i], vT[i], z[i], vz[i], phi[i]], solarmotion=self.solarmotion) self.orbits[i].integrate(ts, potential, method='dopr54_c') # Export the final position self.dist[i], self.ll[i], self.bb[i], self.pmll[i], self.pmbb[i], self.vlos[i] = \ self.orbits[i].dist(self.tflight[i], use_physical=True), \ self.orbits[i].ll(self.tflight[i], use_physical=True), \ self.orbits[i].bb(self.tflight[i], use_physical=True), \ self.orbits[i].pmll(self.tflight[i], use_physical=True) , \ self.orbits[i].pmbb(self.tflight[i], use_physical=True) , \ self.orbits[i].vlos(self.tflight[i], use_physical=True) # Radial velocity and distance + distance modulus self.vlos, self.dist = self.vlos * u.km / u.s, self.dist * u.kpc # Sky coordinates and proper motion data = pmllpmbb_to_pmrapmdec( self.pmll, self.pmbb, self.ll, self.bb, degree=True) * u.mas / u.year self.pmra, self.pmdec = data[:, 0], data[:, 1] data = lb_to_radec(self.ll, self.bb, degree=True) * u.deg self.ra, self.dec = data[:, 0], data[:, 1] # Done propagating self.cattype = 1
def fakeDFData(binned,qdf,ii,params,fehs,afes,options, rmin,rmax, platelb, grmin,grmax, fehrange, colordist, fehdist,feh,sf, mapfehs,mapafes, ro=None,vo=None, ndata=None,#If set, supersedes binned, only to be used w/ returnlist=True returnlist=False): #last one useful for pixelFitDF normintstuff if ro is None: ro= get_ro(params,options) if vo is None: vo= get_vo(params,options,len(fehs)) thishr= qdf.estimate_hr(1.,z=0.125)*_REFR0*ro #qdf._hr*_REFR0*ro thishz= qdf.estimate_hz(1.,z=0.125)*_REFR0*ro if thishr < 0.: thishr= 10. #Probably close to flat if thishz < 0.1: thishz= 0.2 thissr= qdf._sr*_REFV0*vo thissz= qdf._sz*_REFV0*vo thishsr= qdf._hsr*_REFR0*ro thishsz= qdf._hsz*_REFR0*ro if True: if options.aAmethod.lower() == 'staeckel': #Make everything 10% larger thishr*= 1.2 thishz*= 1.2 thishsr*= 1.2 thishsz*= 1.2 thissr*= 2. thissz*= 2. else: #Make everything 20% larger thishr*= 1.2 thishz*= 1.2 thishsr*= 1.2 thishsz*= 1.2 thissr*= 2. thissz*= 2. #Find nearest mono-abundance bin that has a measurement abindx= numpy.argmin((fehs[ii]-mapfehs)**2./0.01 \ +(afes[ii]-mapafes)**2./0.0025) #Calculate the r-distribution for each plate nrs= 1001 ngr, nfeh= 11, 11 #BOVY: INCREASE? tgrs= numpy.linspace(grmin,grmax,ngr) tfehs= numpy.linspace(fehrange[0]+0.00001,fehrange[1]-0.00001,nfeh) #Calcuate FeH and gr distriutions fehdists= numpy.zeros(nfeh) for jj in range(nfeh): fehdists[jj]= fehdist(tfehs[jj]) fehdists= numpy.cumsum(fehdists) fehdists/= fehdists[-1] colordists= numpy.zeros(ngr) for jj in range(ngr): colordists[jj]= colordist(tgrs[jj]) colordists= numpy.cumsum(colordists) colordists/= colordists[-1] rs= numpy.linspace(rmin,rmax,nrs) rdists= numpy.zeros((len(sf.plates),nrs,ngr,nfeh)) #outlier model that we want to sample (not the one to aid in the sampling) srhalo= _SRHALO/vo/_REFV0 sphihalo= _SPHIHALO/vo/_REFV0 szhalo= _SZHALO/vo/_REFV0 logoutfrac= numpy.log(get_outfrac(params,ii,options)) loghalodens= numpy.log(ro*outDens(1.,0.,None)) #Calculate surface(R=1.) for relative outlier normalization logoutfrac+= numpy.log(qdf.surfacemass_z(1.,ngl=options.ngl)) if options.mcout: fidoutfrac= get_outfrac(params,ii,options) rdistsout= numpy.zeros((len(sf.plates),nrs,ngr,nfeh)) lagoutfrac= 0.15 #.0000000000000000000000001 #seems good #Setup density model use_real_dens= True if use_real_dens: #nrs, nzs= 101, 101 nrs, nzs= 64, 64 thisRmin, thisRmax= 4./_REFR0, 15./_REFR0 thiszmin, thiszmax= 0., .8 Rgrid= numpy.linspace(thisRmin,thisRmax,nrs) zgrid= numpy.linspace(thiszmin,thiszmax,nzs) surfgrid= numpy.empty((nrs,nzs)) for ll in range(nrs): for jj in range(nzs): sys.stdout.write('\r'+"Working on grid-point %i/%i" % (jj+ll*nzs+1,nzs*nrs)) sys.stdout.flush() surfgrid[ll,jj]= qdf.density(Rgrid[ll],zgrid[jj], nmc=options.nmcv, ngl=options.ngl) sys.stdout.write('\r'+_ERASESTR+'\r') sys.stdout.flush() if _SURFSUBTRACTEXPON: Rs= numpy.tile(Rgrid,(nzs,1)).T Zs= numpy.tile(zgrid,(nrs,1)) ehr= qdf.estimate_hr(1.,z=0.125) # ehz= qdf.estimate_hz(1.,zmin=0.5,zmax=0.7)#Get large z behavior right ehz= qdf.estimate_hz(1.,z=0.125) surfInterp= interpolate.RectBivariateSpline(Rgrid,zgrid, numpy.log(surfgrid) +Rs/ehr+numpy.fabs(Zs)/ehz, kx=3,ky=3, s=0.) # s=10.*float(nzs*nrs)) else: surfInterp= interpolate.RectBivariateSpline(Rgrid,zgrid, numpy.log(surfgrid), kx=3,ky=3, s=0.) # s=10.*float(nzs*nrs)) if _SURFSUBTRACTEXPON: compare_func= lambda x,y,du: numpy.exp(surfInterp.ev(x/ro/_REFR0,numpy.fabs(y)/ro/_REFR0)-x/ro/_REFR0/ehr-numpy.fabs(y)/ehz/ro/_REFR0) else: compare_func= lambda x,y,du: numpy.exp(surfInterp.ev(x/ro/_REFR0,numpy.fabs(y)/ro/_REFR0)) else: compare_func= lambda x,y,z: fidDens(x,y,thishr,thishz,z) for jj in range(len(sf.plates)): p= sf.plates[jj] sys.stdout.write('\r'+"Working on plate %i (%i/%i)" % (p,jj+1,len(sf.plates))) sys.stdout.flush() rdists[jj,:,:,:]= _predict_rdist_plate(rs, compare_func, None,rmin,rmax, platelb[jj,0],platelb[jj,1], grmin,grmax, fehrange[0],fehrange[1],feh, colordist, fehdist,sf,sf.plates[jj], dontmarginalizecolorfeh=True, ngr=ngr,nfeh=nfeh) if options.mcout: rdistsout[jj,:,:,:]= _predict_rdist_plate(rs, lambda x,y,z: outDens(x,y,z), None,rmin,rmax, platelb[jj,0],platelb[jj,1], grmin,grmax, fehrange[0],fehrange[1],feh, colordist, fehdist,sf,sf.plates[jj], dontmarginalizecolorfeh=True, ngr=ngr,nfeh=nfeh) sys.stdout.write('\r'+_ERASESTR+'\r') sys.stdout.flush() numbers= numpy.sum(rdists,axis=3) numbers= numpy.sum(numbers,axis=2) numbers= numpy.sum(numbers,axis=1) numbers= numpy.cumsum(numbers) if options.mcout: totfid= numbers[-1] numbers/= numbers[-1] rdists= numpy.cumsum(rdists,axis=1) for ll in range(len(sf.plates)): for jj in range(ngr): for kk in range(nfeh): rdists[ll,:,jj,kk]/= rdists[ll,-1,jj,kk] if options.mcout: numbersout= numpy.sum(rdistsout,axis=3) numbersout= numpy.sum(numbersout,axis=2) numbersout= numpy.sum(numbersout,axis=1) numbersout= numpy.cumsum(numbersout) totout= fidoutfrac*numbersout[-1] totnumbers= totfid+totout totfid/= totnumbers totout/= totnumbers if _DEBUG: print totfid, totout numbersout/= numbersout[-1] rdistsout= numpy.cumsum(rdistsout,axis=1) for ll in range(len(sf.plates)): for jj in range(ngr): for kk in range(nfeh): rdistsout[ll,:,jj,kk]/= rdistsout[ll,-1,jj,kk] #Now sample thisout= [] newrs= [] newls= [] newbs= [] newplate= [] newgr= [] newfeh= [] newds= [] newzs= [] newvas= [] newRs= [] newphi= [] newvr= [] newvt= [] newvz= [] newlogratio= [] newfideval= [] newqdfeval= [] newpropeval= [] if ndata is None: thisdata= binned(fehs[ii],afes[ii]) thisdataIndx= binned.callIndx(fehs[ii],afes[ii]) ndata= len(thisdata) #First sample from spatial density for ll in range(ndata): #First sample a plate ran= numpy.random.uniform() kk= 0 while numbers[kk] < ran: kk+= 1 #Also sample a FeH and a color ran= numpy.random.uniform() ff= 0 while fehdists[ff] < ran: ff+= 1 ran= numpy.random.uniform() cc= 0 while colordists[cc] < ran: cc+= 1 #plate==kk, feh=ff,color=cc; now sample from the rdist of this plate ran= numpy.random.uniform() jj= 0 if options.mcout and numpy.random.uniform() < totout: #outlier while rdistsout[kk,jj,cc,ff] < ran: jj+= 1 thisoutlier= True else: while rdists[kk,jj,cc,ff] < ran: jj+= 1 thisoutlier= False #r=jj newrs.append(rs[jj]) newls.append(platelb[kk,0]) newbs.append(platelb[kk,1]) newplate.append(sf.plates[kk]) newgr.append(tgrs[cc]) newfeh.append(tfehs[ff]) dist= _ivezic_dist(tgrs[cc],rs[jj],tfehs[ff]) newds.append(dist) #calculate R,z XYZ= bovy_coords.lbd_to_XYZ(platelb[kk,0],platelb[kk,1], dist,degree=True) R= ((_REFR0-XYZ[0])**2.+XYZ[1]**2.)**(0.5) newRs.append(R) phi= numpy.arcsin(XYZ[1]/R) if (_REFR0-XYZ[0]) < 0.: phi= numpy.pi-phi newphi.append(phi) z= XYZ[2]+_ZSUN newzs.append(z) newrs= numpy.array(newrs) newls= numpy.array(newls) newbs= numpy.array(newbs) newplate= numpy.array(newplate) newgr= numpy.array(newgr) newfeh= numpy.array(newfeh) newds= numpy.array(newds) newRs= numpy.array(newRs) newzs= numpy.array(newzs) newphi= numpy.array(newphi) #Add mock velocities newvr= numpy.empty_like(newrs) newvt= numpy.empty_like(newrs) newvz= numpy.empty_like(newrs) use_sampleV= True if use_sampleV: for kk in range(ndata): newv= qdf.sampleV(newRs[kk]/_REFR0,newzs[kk]/_REFR0,n=1) newvr[kk]= newv[0,0]*_REFV0*vo newvt[kk]= newv[0,1]*_REFV0*vo newvz[kk]= newv[0,2]*_REFV0*vo else: accept_v= numpy.zeros(ndata,dtype='bool') naccept= numpy.sum(accept_v) sigz= thissz*numpy.exp(-(newRs-_REFR0)/thishsz) sigr= thissr*numpy.exp(-(newRs-_REFR0)/thishsr) va= numpy.empty_like(newrs) sigphi= numpy.empty_like(newrs) maxqdf= numpy.empty_like(newrs) nvt= 101 tvt= numpy.linspace(0.1,1.2,nvt) for kk in range(ndata): #evaluate qdf for vt pvt= qdf(newRs[kk]/ro/_REFR0+numpy.zeros(nvt), numpy.zeros(nvt), tvt, newzs[kk]/ro/_REFR0+numpy.zeros(nvt), numpy.zeros(nvt),log=True) pvt_maxindx= numpy.argmax(pvt) va[kk]= (1.-tvt[pvt_maxindx])*_REFV0*vo if options.aAmethod.lower() == 'adiabaticgrid' and options.flatten >= 0.9: maxqdf[kk]= pvt[pvt_maxindx]+numpy.log(250.) elif options.aAmethod.lower() == 'adiabaticgrid' and options.flatten >= 0.8: maxqdf[kk]= pvt[pvt_maxindx]+numpy.log(250.) else: maxqdf[kk]= pvt[pvt_maxindx]+numpy.log(40.) sigphi[kk]= _REFV0*vo*4.*numpy.sqrt(numpy.sum(numpy.exp(pvt)*tvt**2.)/numpy.sum(numpy.exp(pvt))-(numpy.sum(numpy.exp(pvt)*tvt)/numpy.sum(numpy.exp(pvt)))**2.) ntries= 0 ngtr1= 0 while naccept < ndata: sys.stdout.write('\r %i %i %i \r' % (ntries,naccept,ndata)) sys.stdout.flush() #print ntries, naccept, ndata ntries+= 1 accept_v_comp= True-accept_v prop_vr= numpy.random.normal(size=ndata)*sigr prop_vt= numpy.random.normal(size=ndata)*sigphi+vo*_REFV0-va prop_vz= numpy.random.normal(size=ndata)*sigz qoverp= numpy.zeros(ndata)-numpy.finfo(numpy.dtype(numpy.float64)).max qoverp[accept_v_comp]= (qdf(newRs[accept_v_comp]/ro/_REFR0, prop_vr[accept_v_comp]/vo/_REFV0, prop_vt[accept_v_comp]/vo/_REFV0, newzs[accept_v_comp]/ro/_REFR0, prop_vz[accept_v_comp]/vo/_REFV0,log=True) -maxqdf[accept_v_comp] #normalize max to 1 -(-0.5*(prop_vr[accept_v_comp]**2./sigr[accept_v_comp]**2.+prop_vz[accept_v_comp]**2./sigz[accept_v_comp]**2.+(prop_vt[accept_v_comp]-_REFV0*vo+va[accept_v_comp])**2./sigphi[accept_v_comp]**2.))) if numpy.any(qoverp > 0.): ngtr1+= numpy.sum((qoverp > 0.)) if ngtr1 > 5: qindx= (qoverp > 0.) print naccept, ndata, newRs[qindx], newzs[qindx], prop_vr[qindx], va[qindx], sigphi[qindx], prop_vt[qindx], prop_vz[qindx], qoverp[qindx] raise RuntimeError("max qoverp = %f > 1, but shouldn't be" % (numpy.exp(numpy.amax(qoverp)))) accept_these= numpy.log(numpy.random.uniform(size=ndata)) #print accept_these, (accept_these < qoverp) accept_these= (accept_these < qoverp) newvr[accept_these]= prop_vr[accept_these] newvt[accept_these]= prop_vt[accept_these] newvz[accept_these]= prop_vz[accept_these] accept_v[accept_these]= True naccept= numpy.sum(accept_v) sys.stdout.write('\r'+_ERASESTR+'\r') sys.stdout.flush() """ ntot= 0 nsamples= 0 itt= 0 fracsuccess= 0. fraccomplete= 0. while fraccomplete < 1.: if itt == 0: nthis= numpy.amax([ndata,_NMIN]) else: nthis= int(numpy.ceil((1-fraccomplete)/fracsuccess*ndata)) itt+= 1 count= 0 while count < nthis: count+= 1 sigz= thissz*numpy.exp(-(R-_REFR0)/thishsz) sigr= thissr*numpy.exp(-(R-_REFR0)/thishsr) sigphi= sigr #/numpy.sqrt(2.) #BOVY: FOR NOW #Estimate asymmetric drift va= sigr**2./2./_REFV0/vo\ *(-.5+R*(1./thishr+2./thishsr))+10.*numpy.fabs(z) newvas.append(va) if options.mcout and thisoutlier: #Sample from outlier gaussian newvz.append(numpy.random.normal()*_SZHALOFAKE*2.) newvr.append(numpy.random.normal()*_SRHALOFAKE*2.) newvt.append(numpy.random.normal()*_SPHIHALOFAKE*2.) elif numpy.random.uniform() < lagoutfrac: #Sample from lagging gaussian newvz.append(numpy.random.normal()*_SZHALOFAKE) newvr.append(numpy.random.normal()*_SRHALOFAKE) newvt.append(numpy.random.normal()*_SPHIHALOFAKE*2.+_REFV0*vo/4.) else: #Sample from disk gaussian newvz.append(numpy.random.normal()*sigz) newvr.append(numpy.random.normal()*sigr) newvt.append(numpy.random.normal()*sigphi+_REFV0*vo-va) newlogratio= list(newlogratio) fidlogeval= numpy.log(1.-lagoutfrac)\ -numpy.log(sigr)-numpy.log(sigphi)-numpy.log(sigz)-0.5*(newvr[-1]**2./sigr**2.+newvz[-1]**2./sigz**2.+(newvt[-1]-_REFV0*vo+va)**2./sigphi**2.) lagoutlogeval= numpy.log(lagoutfrac)\ -numpy.log(_SRHALOFAKE)\ -numpy.log(_SPHIHALOFAKE*2.)\ -numpy.log(_SZHALOFAKE)\ -0.5*(newvr[-1]**2./_SRHALOFAKE**2.+newvz[-1]**2./_SZHALOFAKE**2.+(newvt[-1]-_REFV0*vo/4.)**2./_SPHIHALOFAKE**2./4.) if use_real_dens: fidlogeval+= numpy.log(compare_func(R,z,None)[0]) lagoutlogeval+= numpy.log(compare_func(R,z,None)[0]) else: fidlogeval+= numpy.log(fidDens(R,z,thishr,thishz,None)) lagoutlogeval+= numpy.log(fidDens(R,z,thishr,thishz,None)) newfideval.append(fidlogeval) if options.mcout: fidoutlogeval= numpy.log(fidoutfrac)\ +numpy.log(outDens(R,z,None))\ -numpy.log(_SRHALOFAKE*2.)\ -numpy.log(_SPHIHALOFAKE*2.)\ -numpy.log(_SZHALOFAKE*2.)\ -0.5*(newvr[-1]**2./_SRHALOFAKE**2./4.+newvz[-1]**2./_SZHALOFAKE**2./4.+newvt[-1]**2./_SPHIHALOFAKE**2./4.) newpropeval.append(logsumexp([fidoutlogeval,fidlogeval, lagoutlogeval])) else: newpropeval.append(logsumexp([lagoutlogeval,fidlogeval])) qdflogeval= qdf(R/ro/_REFR0,newvr[-1]/vo/_REFV0,newvt[-1]/vo/_REFV0,z/ro/_REFR0,newvz[-1]/vo/_REFV0,log=True) if isinstance(qdflogeval,(list,numpy.ndarray)): qdflogeval= qdflogeval[0] if options.mcout: outlogeval= logoutfrac+loghalodens\ -numpy.log(srhalo)-numpy.log(sphihalo)-numpy.log(szhalo)\ -0.5*((newvr[-1]/vo/_REFV0)**2./srhalo**2.+(newvz[-1]/vo/_REFV0)**2./szhalo**2.+(newvt[-1]/vo/_REFV0)**2./sphihalo**2.)\ -1.5*numpy.log(2.*numpy.pi) newqdfeval.append(logsumexp([qdflogeval,outlogeval])) else: newqdfeval.append(qdflogeval) newlogratio.append(qdflogeval -newpropeval[-1])#logsumexp([fidlogeval,fidoutlogeval])) newlogratio= numpy.array(newlogratio) thisnewlogratio= copy.copy(newlogratio) maxnewlogratio= numpy.amax(thisnewlogratio) if False: argsort_thisnewlogratio= numpy.argsort(thisnewlogratio)[::-1] thisnewlogratio-= thisnewlogratio[argsort_thisnewlogratio[2]] #3rd largest else: thisnewlogratio-= numpy.amax(thisnewlogratio) thisnewratio= numpy.exp(thisnewlogratio) if len(thisnewratio.shape) > 1 and thisnewratio.shape[1] == 1: thisnewratio= numpy.reshape(thisnewratio,(thisnewratio.shape[0])) #Rejection sample accept= numpy.random.uniform(size=len(thisnewratio)) accept= (accept < thisnewratio) fraccomplete= float(numpy.sum(accept))/ndata fracsuccess= float(numpy.sum(accept))/len(thisnewratio) if _DEBUG: print fraccomplete, fracsuccess, ndata print numpy.histogram(thisnewratio,bins=16) indx= numpy.argmax(thisnewratio) print numpy.array(newvr)[indx], \ numpy.array(newvt)[indx], \ numpy.array(newvz)[indx], \ numpy.array(newrs)[indx], \ numpy.array(newds)[indx], \ numpy.array(newls)[indx], \ numpy.array(newbs)[indx], \ numpy.array(newfideval)[indx] bovy_plot.bovy_print() bovy_plot.bovy_plot(numpy.array(newvt), numpy.exp(numpy.array(newqdfeval)),'b,', xrange=[-300.,500.],yrange=[0.,1.]) bovy_plot.bovy_plot(newvt, numpy.exp(numpy.array(newpropeval+maxnewlogratio)), 'g,', overplot=True) bovy_plot.bovy_plot(numpy.array(newvt), numpy.exp(numpy.array(newlogratio-maxnewlogratio)), 'b,', xrange=[-300.,500.], # xrange=[0.,20.], # xrange=[0.,3.], # xrange=[6.,9.], yrange=[0.001,1.],semilogy=True) bovy_plot.bovy_end_print('/home/bovy/public_html/segue-local/test.png') #Now collect the samples newrs= numpy.array(newrs)[accept][0:ndata] newls= numpy.array(newls)[accept][0:ndata] newbs= numpy.array(newbs)[accept][0:ndata] newplate= numpy.array(newplate)[accept][0:ndata] newgr= numpy.array(newgr)[accept][0:ndata] newfeh= numpy.array(newfeh)[accept][0:ndata] newvr= numpy.array(newvr)[accept][0:ndata] newvt= numpy.array(newvt)[accept][0:ndata] newvz= numpy.array(newvz)[accept][0:ndata] newphi= numpy.array(newphi)[accept][0:ndata] newds= numpy.array(newds)[accept][0:ndata] newqdfeval= numpy.array(newqdfeval)[accept][0:ndata] """ vx, vy, vz= bovy_coords.galcencyl_to_vxvyvz(newvr,newvt,newvz,newphi, vsun=[_VRSUN,_VTSUN,_VZSUN]) vrpmllpmbb= bovy_coords.vxvyvz_to_vrpmllpmbb(vx,vy,vz,newls,newbs,newds, XYZ=False,degree=True) pmrapmdec= bovy_coords.pmllpmbb_to_pmrapmdec(vrpmllpmbb[:,1], vrpmllpmbb[:,2], newls,newbs, degree=True) #Dump everything for debugging the coordinate transformation from galpy.util import save_pickles save_pickles('dump.sav', newds,newls,newbs,newphi, newvr,newvt,newvz, vx, vy, vz, vrpmllpmbb, pmrapmdec) if returnlist: out= [] for ii in range(ndata): out.append([newrs[ii], newgr[ii], newfeh[ii], newls[ii], newbs[ii], newplate[ii], newds[ii], False, #outlier? vrpmllpmbb[ii,0], vrpmllpmbb[ii,1], vrpmllpmbb[ii,2]])#, # newqdfeval[ii]]) return out #Load into data binned.data.feh[thisdataIndx]= newfeh oldgr= thisdata.dered_g-thisdata.dered_r oldr= thisdata.dered_r if options.noerrs: binned.data.dered_r[thisdataIndx]= newrs else: binned.data.dered_r[thisdataIndx]= newrs\ +numpy.random.normal(size=numpy.sum(thisdataIndx))\ *ivezic_dist_gr(oldgr,0., #g-r is all that counts binned.data.feh[thisdataIndx], dg=binned.data[thisdataIndx].g_err, dr=binned.data[thisdataIndx].r_err, dfeh=binned.data[thisdataIndx].feh_err, return_error=True, _returndmr=True) binned.data.dered_r[(binned.data.dered_r >= rmax)]= rmax #tweak to make sure everything stays within the observed range if False: binned.data.dered_r[(binned.data.dered_r <= rmin)]= rmin binned.data.dered_g[thisdataIndx]= oldgr+binned.data[thisdataIndx].dered_r #Also change plate and l and b binned.data.plate[thisdataIndx]= newplate radec= bovy_coords.lb_to_radec(newls,newbs,degree=True) binned.data.ra[thisdataIndx]= radec[:,0] binned.data.dec[thisdataIndx]= radec[:,1] binned.data.l[thisdataIndx]= newls binned.data.b[thisdataIndx]= newbs if options.noerrs: binned.data.vr[thisdataIndx]= vrpmllpmbb[:,0] binned.data.pmra[thisdataIndx]= pmrapmdec[:,0] binned.data.pmdec[thisdataIndx]= pmrapmdec[:,1] else: binned.data.vr[thisdataIndx]= vrpmllpmbb[:,0]+numpy.random.normal(size=numpy.sum(thisdataIndx))*binned.data.vr_err[thisdataIndx] binned.data.pmra[thisdataIndx]= pmrapmdec[:,0]+numpy.random.normal(size=numpy.sum(thisdataIndx))*binned.data.pmra_err[thisdataIndx] binned.data.pmdec[thisdataIndx]= pmrapmdec[:,1]+numpy.random.normal(size=numpy.sum(thisdataIndx))*binned.data.pmdec_err[thisdataIndx] return binned
def pmllpmbb_to_pmphi12(pmll,pmbb,l,b,degree=False): """ NAME: pmllpmbb_to_pmphi12 PURPOSE: Transform proper mtions in Galactic coordinates (l,b) to (phi1,phi2) INPUT: pmll - proper motion Galactic longitude (rad or degree); contains xcosb pmbb - Galactic latitude (rad or degree) l - Galactic longitude (rad or degree) b - Galactic latitude (rad or degree) degree= (False) if True, input (l,b) are in degrees OUTPUT: (pmphi1,pmphi2) for scalar input [:,2] array for vector input HISTORY: 2014-11-04 - Written - Bovy (IAS) """ import numpy from galpy.util import bovy_coords _TKOP= numpy.zeros((3,3)) _TKOP[0,:]= [-0.4776303088,-0.1738432154,0.8611897727] _TKOP[1,:]= [0.510844589,-0.8524449229,0.111245042] _TKOP[2,:]= [0.7147776536,0.4930681392,0.4959603976] #First go to ra and dec radec= bovy_coords.lb_to_radec(l,b) ra= radec[:,0] dec= radec[:,1] pmradec= bovy_coords.pmllpmbb_to_pmrapmdec(pmll,pmbb,l,b,degree=False) pmra= pmradec[:,0] pmdec= pmradec[:,1] #Now transform ra,dec pm to phi1,phi2 phi12= lb_to_phi12(l,b,degree=False) phi1= phi12[:,0] phi2= phi12[:,1] #Build A and Aphi matrices A= numpy.zeros((3,3,len(ra))) A[0,0]= numpy.cos(ra)*numpy.cos(dec) A[0,1]= -numpy.sin(ra) A[0,2]= -numpy.cos(ra)*numpy.sin(dec) A[1,0]= numpy.sin(ra)*numpy.cos(dec) A[1,1]= numpy.cos(ra) A[1,2]= -numpy.sin(ra)*numpy.sin(dec) A[2,0]= numpy.sin(dec) A[2,1]= 0. A[2,2]= numpy.cos(dec) AphiInv= numpy.zeros((3,3,len(ra))) AphiInv[0,0]= numpy.cos(phi1)*numpy.cos(phi2) AphiInv[0,1]= numpy.cos(phi2)*numpy.sin(phi1) AphiInv[0,2]= numpy.sin(phi2) AphiInv[1,0]= -numpy.sin(phi1) AphiInv[1,1]= numpy.cos(phi1) AphiInv[1,2]= 0. AphiInv[2,0]= -numpy.cos(phi1)*numpy.sin(phi2) AphiInv[2,1]= -numpy.sin(phi1)*numpy.sin(phi2) AphiInv[2,2]= numpy.cos(phi2) TA= numpy.dot(_TKOP,numpy.swapaxes(A,0,1)) #Got lazy... trans= numpy.zeros((2,2,len(ra))) for ii in range(len(ra)): trans[:,:,ii]= numpy.dot(AphiInv[:,:,ii],TA[:,:,ii])[1:,1:] return (trans*numpy.array([[pmra,pmdec],[pmra,pmdec]])).sum(1).T
sdf_smooth= pal5_util.setup_pal5model() pepperfilename= 'pal5pepper1sampling.pkl' if os.path.exists(pepperfilename): with open(pepperfilename,'rb') as savefile: sdf_pepper= pickle.load(savefile) else: import simulate_streampepper timpacts= simulate_streampepper.parse_times('1sampling',9.) sdf_pepper= pal5_util.setup_pal5model(timpact=timpacts, hernquist=True) save_pickles(pepperfilename,sdf_pepper) # Convert track to xi, eta trackRADec=\ bovy_coords.lb_to_radec(sdf_smooth._interpolatedObsTrackLB[:,0], sdf_smooth._interpolatedObsTrackLB[:,1], degree=True) trackXiEta=\ pal5_util.radec_to_pal5xieta(trackRADec[:,0], trackRADec[:,1],degree=True) smooth_track= [] for coord in range(6): if coord < 2: smooth_track.append(\ interpolate.InterpolatedUnivariateSpline(sdf_smooth._interpolatedThetasTrack, trackXiEta[:,coord])) else: smooth_track.append(\ interpolate.InterpolatedUnivariateSpline(sdf_smooth._interpolatedThetasTrack, sdf_smooth._interpolatedObsTrackLB[:,coord])) smooth_ll= interpolate.InterpolatedUnivariateSpline(trackXiEta[:,0],
def predict_pal5obs( pot_params: list, c: float, b: float = 1.0, pa: float = 0.0, sigv: Union[float, list] = 0.2, td: float = 10.0, dist: float = 23.2, pmra: float = -2.296, pmdec: float = -2.257, vlos: float = -58.7, ro: float = REFR0, vo: float = REFV0, singlec: bool = False, interpcs: Optional[float] = None, interpk: Optional[float] = None, isob: Optional[float] = None, nTrackChunks: int = 8, multi: Optional = None, trailing_only: bool = False, useTM: bool = False, verbose: bool = True, ) -> TrackTuple: """Predict Pal 5 Observed. Function that generates the location and velocity of the Pal 5 stream, its width, and its length for a given potential and progenitor phase-space position Parameters ---------- pot_params: array parameters of a potential model (see mw_pot.setup_potential; only the basic parameters of the disk and halo are used, flattening is specified separately) c : float halo flattening b : float, optional (1.) halo-squashed pa: float, optional (0.) halo PA sigv : float, optional (0.4) velocity dispersion in km/s (can be array of same len as interpcs) td : float, optional (5.) stream age in Gyr (can be array of same len as interpcs) dist : float, optional (23.2) progenitor distance in kpc pmra : float, optional (-2.296) progenitor proper motion in RA * cos(Dec) in mas/yr pmdec : float, optional (-2.257) progenitor proper motion in Dec in mas/yr vlos : float, optional (-58.7) progenitor line-of-sight velocity in km/s ro : float, optional (project default) distance to the GC in kpc vo : float, optional (project default) circular velocity at R0 in km/s singlec : bool, optional (False) if True, just compute the observables for a single c interpcs : float or None, optional (None) values of c at which to compute the model for interpolation nTrackChunks : int, optional (8) nTrackChunks input to streamdf multi : float or None, optional (None) multi input to streamdf isob : float or None, optional (None) if given, b parameter of actionAngleIsochroneApprox trailing_only : bool, optional (False) if True, only predict the trailing arm useTM : bool, optional (True) use the TorusMapper to compute the track verbose : bool, optional (True) print messages Returns ------- trackRADec_trailing_out : array trailing track in RA, Dec all arrays with the shape of c trackRADec_leading_out : array leading track in RA, Dec all arrays with the shape of c trackRAVlos_trailing_out : array trailing track in RA, Vlos all arrays with the shape of c trackRAVlos_leading_out : array leading track in RA, Vlos all arrays with the shape of c width_out : float trailing width in arcmin length_out : float trailing length in deg interpcs : array success : bool """ # First compute the model for all cs at which we will interpolate interpcs: list if singlec: interpcs = [c] elif interpcs is None: interpcs = [ 0.5, 0.75, 1.0, 1.25, 1.55, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, ] else: interpcs = copy.deepcopy(interpcs) # bc we might want to remove some if isinstance(sigv, float): sigv: list = [sigv for i in interpcs] if isinstance(td, float): td: list = [td for i in interpcs] if isinstance(isob, float) or isob is None: isob: list = [isob for i in interpcs] prog: Orbit = Orbit( [229.018, -0.124, dist, pmra, pmdec, vlos], radec=True, ro=ro, vo=vo, solarmotion=[-11.1, 24.0, 7.25], ) # Setup the model sdf_trailing_varyc: list = [] sdf_leading_varyc: list = [] ii: int = 0 ninterpcs: int = len(interpcs) this_useTM: bool = copy.deepcopy(useTM) this_nTrackChunks: int = nTrackChunks ntries: int = 0 while ii < ninterpcs: ic = interpcs[ii] pot = mw_pot.setup_potential(pot_params, ic, False, False, ro, vo, b=b, pa=pa) success: bool = True # wentIn = ntries != 0 # Make sure this doesn't run forever signal.signal(signal.SIGALRM, timeout_handler) signal.alarm(300) try: tsdf_trailing, tsdf_leading = setup_sdf( pot, prog, sigv[ii], td[ii], ro, vo, multi=multi, isob=isob[ii], nTrackChunks=this_nTrackChunks, trailing_only=trailing_only, verbose=verbose, useTM=this_useTM, ) except Exception: # Catches errors and time-outs success = False signal.alarm(0) # Check for calc. issues if not success or (not this_useTM and looks_funny(tsdf_trailing, tsdf_leading)): # Try again with TM this_useTM = True this_nTrackChunks = 21 # might as well # wentIn= True # print("Here",ntries,success) # sys.stdout.flush() ntries += 1 else: success = not this_useTM # if wentIn: # print(success) # sys.stdout.flush() ii += 1 # reset this_useTM = useTM this_nTrackChunks = nTrackChunks ntries = 0 # Add to the list sdf_trailing_varyc.append(tsdf_trailing) sdf_leading_varyc.append(tsdf_leading) if not singlec and len(sdf_trailing_varyc) <= 1: # Almost everything bad!! return ( np.zeros((len(c), 1001, 2)), np.zeros((len(c), 1001, 2)), np.zeros((len(c), 1001, 2)), np.zeros((len(c), 1001, 2)), np.zeros((len(c))), np.zeros((len(c))), [], success, ) # Compute the track properties for each model trackRADec_trailing: np.ndarray = np.zeros( (len(interpcs), sdf_trailing_varyc[0].nInterpolatedTrackChunks, 2)) trackRADec_leading: np.ndarray = np.zeros( (len(interpcs), sdf_trailing_varyc[0].nInterpolatedTrackChunks, 2)) trackRAVlos_trailing: np.ndarray = np.zeros( (len(interpcs), sdf_trailing_varyc[0].nInterpolatedTrackChunks, 2)) trackRAVlos_leading: np.ndarray = np.zeros( (len(interpcs), sdf_trailing_varyc[0].nInterpolatedTrackChunks, 2)) # TODO put in distances (can use _interpolatedObsTrackLB[:,2],) width: np.ndarray = np.zeros(len(interpcs)) length: np.ndarray = np.zeros(len(interpcs)) for ii in range(len(interpcs)): trackRADec_trailing[ii] = bovy_coords.lb_to_radec( sdf_trailing_varyc[ii]._interpolatedObsTrackLB[:, 0], sdf_trailing_varyc[ii]._interpolatedObsTrackLB[:, 1], degree=True, ) if not trailing_only: trackRADec_leading[ii] = bovy_coords.lb_to_radec( sdf_leading_varyc[ii]._interpolatedObsTrackLB[:, 0], sdf_leading_varyc[ii]._interpolatedObsTrackLB[:, 1], degree=True, ) trackRAVlos_trailing[ii][:, 0] = trackRADec_trailing[ii][:, 0] trackRAVlos_trailing[ii][:, 1] = sdf_trailing_varyc[ ii]._interpolatedObsTrackLB[:, 3] if not trailing_only: trackRAVlos_leading[ii][:, 0] = trackRADec_leading[ii][:, 0] trackRAVlos_leading[ii][:, 1] = sdf_leading_varyc[ ii]._interpolatedObsTrackLB[:, 3] width[ii] = width_trailing(sdf_trailing_varyc[ii]) length[ii] = sdf_trailing_varyc[ii].length(ang=True, coord="customra", threshold=0.3) if singlec: # if wentIn: # print(success) # sys.stdout.flush() return ( trackRADec_trailing, trackRADec_leading, trackRAVlos_trailing, trackRAVlos_leading, width, length, interpcs, success, ) # Interpolate; output grids trackRADec_trailing_out: np.ndarray = np.zeros( (len(c), sdf_trailing_varyc[0].nInterpolatedTrackChunks, 2)) trackRADec_leading_out: np.ndarray = np.zeros( (len(c), sdf_trailing_varyc[0].nInterpolatedTrackChunks, 2)) trackRAVlos_trailing_out: np.ndarray = np.zeros( (len(c), sdf_trailing_varyc[0].nInterpolatedTrackChunks, 2)) trackRAVlos_leading_out: np.ndarray = np.zeros( (len(c), sdf_trailing_varyc[0].nInterpolatedTrackChunks, 2)) if interpk is None: interpk = np.amin([len(interpcs) - 1, 3]) for ii in range(sdf_trailing_varyc[0].nInterpolatedTrackChunks): ip = interpolate.InterpolatedUnivariateSpline(interpcs, trackRADec_trailing[:, ii, 0], k=interpk, ext=0) trackRADec_trailing_out[:, ii, 0] = ip(c) ip = interpolate.InterpolatedUnivariateSpline(interpcs, trackRADec_trailing[:, ii, 1], k=interpk, ext=0) trackRADec_trailing_out[:, ii, 1] = ip(c) ip = interpolate.InterpolatedUnivariateSpline(interpcs, trackRAVlos_trailing[:, ii, 0], k=interpk, ext=0) trackRAVlos_trailing_out[:, ii, 0] = ip(c) ip = interpolate.InterpolatedUnivariateSpline(interpcs, trackRAVlos_trailing[:, ii, 1], k=interpk, ext=0) trackRAVlos_trailing_out[:, ii, 1] = ip(c) if not trailing_only: ip = interpolate.InterpolatedUnivariateSpline( interpcs, trackRADec_leading[:, ii, 0], k=interpk, ext=0) trackRADec_leading_out[:, ii, 0] = ip(c) ip = interpolate.InterpolatedUnivariateSpline( interpcs, trackRADec_leading[:, ii, 1], k=interpk, ext=0) trackRADec_leading_out[:, ii, 1] = ip(c) ip = interpolate.InterpolatedUnivariateSpline( interpcs, trackRAVlos_leading[:, ii, 0], k=interpk, ext=0) trackRAVlos_leading_out[:, ii, 0] = ip(c) ip = interpolate.InterpolatedUnivariateSpline( interpcs, trackRAVlos_leading[:, ii, 1], k=interpk, ext=0) trackRAVlos_leading_out[:, ii, 1] = ip(c) # /for ip = interpolate.InterpolatedUnivariateSpline(interpcs, width, k=interpk, ext=0) width_out = ip(c) ip = interpolate.InterpolatedUnivariateSpline(interpcs, length, k=interpk, ext=0) length_out = ip(c) return TrackTuple( trackRADec_trailing_out=trackRADec_trailing_out, trackRADec_leading_out=trackRADec_leading_out, trackRAVlos_trailing_out=trackRAVlos_trailing_out, trackRAVlos_leading_out=trackRAVlos_leading_out, width_out=width_out, length_out=length_out, interpcs=interpcs, success=success, )
def _fit_orbit_mlogl(new_vxvv,vxvv,vxvv_err,pot,radec,lb,tmockAA, ro,vo,obs): """The log likelihood for fitting an orbit""" #Use this _parse_args routine, which does forward and backward integration iR,ivR,ivT,iz,ivz,iphi= tmockAA._parse_args(True,False, new_vxvv[0], new_vxvv[1], new_vxvv[2], new_vxvv[3], new_vxvv[4], new_vxvv[5]) if radec or lb: #Need to transform to ra,dec #First transform to X,Y,Z,vX,vY,vZ (Galactic) X,Y,Z = coords.galcencyl_to_XYZ(iR.flatten(),iphi.flatten(), iz.flatten(), Xsun=obs[0]/ro, Ysun=obs[1]/ro, Zsun=obs[2]/ro) vX,vY,vZ = coords.galcencyl_to_vxvyvz(ivR.flatten(),ivT.flatten(), ivz.flatten(),iphi.flatten(), vsun=nu.array(\ obs[3:6])/vo) bad_indx= (X == 0.)*(Y == 0.)*(Z == 0.) if True in bad_indx: X[bad_indx]+= ro/10000. lbdvrpmllpmbb= coords.rectgal_to_sphergal(X*ro,Y*ro,Z*ro, vX*vo,vY*vo,vZ*vo, degree=True) if lb: orb_vxvv= nu.array([lbdvrpmllpmbb[:,0], lbdvrpmllpmbb[:,1], lbdvrpmllpmbb[:,2], lbdvrpmllpmbb[:,4], lbdvrpmllpmbb[:,5], lbdvrpmllpmbb[:,3]]).T else: #Further transform to ra,dec,pmra,pmdec radec= coords.lb_to_radec(lbdvrpmllpmbb[:,0], lbdvrpmllpmbb[:,1],degree=True) pmrapmdec= coords.pmllpmbb_to_pmrapmdec(lbdvrpmllpmbb[:,4], lbdvrpmllpmbb[:,5], lbdvrpmllpmbb[:,0], lbdvrpmllpmbb[:,1], degree=True) orb_vxvv= nu.array([radec[:,0],radec[:,1], lbdvrpmllpmbb[:,2], pmrapmdec[:,0],pmrapmdec[:,1], lbdvrpmllpmbb[:,3]]).T else: #shape=(2tintJ-1,6) orb_vxvv= nu.array([iR.flatten(),ivR.flatten(),ivT.flatten(), iz.flatten(),ivz.flatten(),iphi.flatten()]).T out= 0. for ii in range(vxvv.shape[0]): sub_vxvv= (orb_vxvv-vxvv[ii,:].flatten())**2. #print sub_vxvv[nu.argmin(nu.sum(sub_vxvv,axis=1))] if not vxvv_err is None: sub_vxvv/= vxvv_err[ii,:]**2. else: sub_vxvv/= 0.01**2. out+= logsumexp(-0.5*nu.sum(sub_vxvv,axis=1)) return -out
def example_integrate_orbit(): # Use 'MWPotential2014' as an example my_potential = MWPotential2014 # integration time in units of (_R0/_V0) time_start = 0. time_end = 100. my_time_step = numpy.linspace(time_start, time_end, 1001) # read 6D astrometric data # (0) [mas] parallax # (1) [deg] ell # (2) [deg] b # (3) [km/s] heliocentric line-of-sight velocity # (4) [mas/yr] proper motion along ell direction (mu_ellstar = mu_ell * cos(b)) # (5) [mas/yr] proper motion along b direction (mu_b) my_filename = 'parallax_ell_b_heliocentricLineOfSightVelocity_properMotionEllStar_properMotionB.txt' my_file = open(my_filename, 'r') my_data = numpy.loadtxt(my_file, comments='#') my_parallax_mas = my_data[:, 0] my_ell_deg = my_data[:, 1] my_b_deg = my_data[:, 2] my_hlosv_kms = my_data[:, 3] my_muellstar_masyr = my_data[:, 4] my_mub_masyr = my_data[:, 5] # count sample size my_sample_size = len(my_ell_deg) for i in range(my_sample_size): print('star ID=%d' % (i)) # convert parallax to distance distance_kpc = 1. / my_parallax_mas[i] # convert (ell, b) to (RA, DEC) RA_deg, DEC_deg = bovy_coords.lb_to_radec(my_ell_deg[i], my_b_deg[i], degree=True, epoch=_my_epoch) # heliocentric line-of-sight velocity hlosv_kms = my_hlosv_kms[i] # convert (mu_ellstar, mu_b) to (mu_RAstar, mu_DEC) muRAstar_masyr, muDEC_masyr = bovy_coords.pmllpmbb_to_pmrapmdec( my_muellstar_masyr[i], my_mub_masyr[i], my_ell_deg[i], my_b_deg[i], degree=True, epoch=_my_epoch) # create orbit instance obs_6D = Orbit(vxvv=[ RA_deg, DEC_deg, distance_kpc, muRAstar_masyr, muDEC_masyr, hlosv_kms ], radec=True, ro=_R0, vo=_V0, zo=0., solarmotion=[_Usun, _Vsun, _Wsun]) # integrate orbit in my_potential obs_6D.integrate(my_time_step, my_potential) # file on which we write 6D data at each time step outfile_i = open("t_x_y_z_vx_vy_vz_R__orbitID%03d.txt" % (i), 'w') # For illustrative purpose, I use an explicit expression to access 6D data at each time. for j in range(len(my_time_step)): # Here I assume that # (a) Galactic Center is located at (x,y)=(0,0) kpc # (b) Sun is located at (x,y)=(-8,0) kpc # (c) Nearby disc stars with circular orbits move towards (vx,vy)=(0,220) km/s # This is why I add a minus sign (-) to x and vx. x = -obs_6D.x(my_time_step[j]) y = obs_6D.y(my_time_step[j]) z = obs_6D.z(my_time_step[j]) vx = -obs_6D.vx(my_time_step[j]) vy = obs_6D.vy(my_time_step[j]) vz = obs_6D.vz(my_time_step[j]) R = obs_6D.R(my_time_step[j]) printline = '%lf %lf %lf %lf %lf %lf %lf %lf\n' % ( my_time_step[j], x, y, z, vx, vy, vz, R) outfile_i.write(printline) # close file outfile_i.close() return None
def pmphi12_to_pmllpmbb(pmphi1,pmphi2,phi1,phi2,degree=False): """ NAME: pmllpmbb_to_pmphi12 PURPOSE: Transform proper motions in (phi1,phi2) to Galactic coordinates (l,b) INPUT: pmphi1 - proper motion Galactic longitude (rad or degree); contains xcosphi2 pmphi2 - Galactic latitude (rad or degree) phi1 - phi longitude (rad or degree) phi2 - phi latitude (rad or degree) degree= (False) if True, input (phi1,phi2) are in degrees OUTPUT: (pmll,pmbb) for scalar input [:,2] array for vector input HISTORY: 2014-11-04 - Written - Bovy (IAS) """ import numpy _TKOP= numpy.zeros((3,3)) _TKOP[0,:]= [-0.4776303088,-0.1738432154,0.8611897727] _TKOP[1,:]= [0.510844589,-0.8524449229,0.111245042] _TKOP[2,:]= [0.7147776536,0.4930681392,0.4959603976] #First go from phi12 to ra and dec lb= phi12_to_lb(phi1,phi2) radec= bovy_coords.lb_to_radec(lb[:,0],lb[:,1]) ra= radec[:,0] dec= radec[:,1] #Build A and Aphi matrices AInv= numpy.zeros((3,3,len(ra))) AInv[0,0]= numpy.cos(ra)*numpy.cos(dec) AInv[0,1]= numpy.sin(ra)*numpy.cos(dec) AInv[0,2]= numpy.sin(dec) AInv[1,0]= -numpy.sin(ra) AInv[1,1]= numpy.cos(ra) AInv[1,2]= 0. AInv[2,0]= -numpy.cos(ra)*numpy.sin(dec) AInv[2,1]= -numpy.sin(ra)*numpy.sin(dec) AInv[2,2]= numpy.cos(dec) Aphi= numpy.zeros((3,3,len(ra))) Aphi[0,0]= numpy.cos(phi1)*numpy.cos(phi2) Aphi[0,1]= -numpy.sin(phi1) Aphi[0,2]= -numpy.cos(phi1)*numpy.sin(phi2) Aphi[1,0]= numpy.sin(phi1)*numpy.cos(phi2) Aphi[1,1]= numpy.cos(phi1) Aphi[1,2]= -numpy.sin(phi1)*numpy.sin(phi2) Aphi[2,0]= numpy.sin(phi2) Aphi[2,1]= 0. Aphi[2,2]= numpy.cos(phi2) TAphi= numpy.dot(_TKOP.T,numpy.swapaxes(Aphi,0,1)) #Got lazy... trans= numpy.zeros((2,2,len(ra))) for ii in range(len(ra)): trans[:,:,ii]= numpy.dot(AInv[:,:,ii],TAphi[:,:,ii])[1:,1:] pmradec= (trans*numpy.array([[pmphi1,pmphi2],[pmphi1,pmphi2]])).sum(1).T pmra= pmradec[:,0] pmdec= pmradec[:,1] #Now convert to pmll return bovy_coords.pmrapmdec_to_pmllpmbb(pmra,pmdec,ra,dec)
def fiducial_model( sdf_trailing="output/sdf_trailing.pkl", sdf_leading="output/sdf_leading.pkl", threshold=0.3, ro=REFR0, vo=REFV0, ): """Fiducial Model. The fiducial model assumes a spherical halo, with the best-fit parameters from fitting to the MWPotential2014 data """ p_b15 = [ 0.60122692, 0.36273147, -0.97591502, -3.34169377, 0.71877924, -0.01519337, -0.01928001, ] pot = mw_pot.setup_potential(p_b15, 1.0, False, False, ro, vo) prog = Orbit( [229.018, -0.124, 23.2, -2.296, -2.257, -58.7], radec=True, ro=ro, vo=vo, solarmotion=[-11.1, 24.0, 7.25], ) aAI = actionAngleIsochroneApprox(pot=pot, b=0.8) sigv = 0.2 # ---------------------------------------------------------- try: with open(sdf_trailing, "rb") as file: sdf_trailing = pickle.load(file) except Exception: sdf_trailing = streamdf( sigv / vo, progenitor=prog, pot=pot, aA=aAI, leading=False, nTrackChunks=11, tdisrupt=10.0 / bovy_conversion.time_in_Gyr(vo, ro), ro=ro, vo=vo, R0=ro, vsun=[-11.1, vo + 24.0, 7.25], custom_transform=pal5_util._TPAL5, ) with open(sdf_trailing, "wb") as file: pickle.dump(sdf_trailing, file) try: with open(sdf_leading, "rb") as file: sdf_leading = pickle.load(file) except Exception: sdf_leading = streamdf( sigv / vo, progenitor=prog, pot=pot, aA=aAI, leading=True, nTrackChunks=11, tdisrupt=10.0 / bovy_conversion.time_in_Gyr(vo, ro), ro=ro, vo=vo, R0=ro, vsun=[-11.1, vo + 24.0, 7.25], custom_transform=pal5_util._TPAL5, ) with open(sdf_leading, "wb") as file: pickle.dump(sdf_leading, file) # ---------------------------------------------------------- print("Angular length: %f deg (leading,trailing)=(%f,%f) deg" % ( sdf_leading.length(ang=True, coord="customra", threshold=threshold) + sdf_trailing.length(ang=True, coord="customra", threshold=threshold), sdf_leading.length(ang=True, coord="customra", threshold=threshold), sdf_trailing.length(ang=True, coord="customra", threshold=threshold), )) print("Angular width (FWHM): %f arcmin" % (pal5_util.width_trailing(sdf_trailing))) print("Velocity dispersion: %f km/s" % (pal5_util.vdisp_trailing(sdf_trailing))) # ---------------------------------------------------------- trackRADec_trailing = bovy_coords.lb_to_radec( sdf_trailing._interpolatedObsTrackLB[:, 0], sdf_trailing._interpolatedObsTrackLB[:, 1], degree=True, ) trackRADec_leading = bovy_coords.lb_to_radec( sdf_leading._interpolatedObsTrackLB[:, 0], sdf_leading._interpolatedObsTrackLB[:, 1], degree=True, ) lb_sample_trailing = sdf_trailing.sample(n=10000, lb=True) lb_sample_leading = sdf_leading.sample(n=10000, lb=True) radec_sample_trailing = bovy_coords.lb_to_radec(lb_sample_trailing[0], lb_sample_trailing[1], degree=True) radec_sample_leading = bovy_coords.lb_to_radec(lb_sample_leading[0], lb_sample_leading[1], degree=True) # ---------------------------------------------------------- # plotting plt.figure(figsize=(12, 4)) plt.subplot(1, 2, 1) bovy_plot.bovy_plot( trackRADec_trailing[:, 0], trackRADec_trailing[:, 1], color=sns.color_palette()[0], xrange=[250.0, 210.0], yrange=[-15.0, 9.0], xlabel=r"$\mathrm{RA}\,(\mathrm{degree})$", ylabel=r"$\mathrm{Dec}\,(\mathrm{degree})$", gcf=True, ) bovy_plot.bovy_plot( trackRADec_leading[:, 0], trackRADec_leading[:, 1], color=sns.color_palette()[0], overplot=True, ) plt.plot( radec_sample_trailing[:, 0], radec_sample_trailing[:, 1], "k.", alpha=0.01, zorder=0, ) plt.plot( radec_sample_leading[:, 0], radec_sample_leading[:, 1], "k.", alpha=0.01, zorder=0, ) plt.errorbar( pos_radec[:, 0], pos_radec[:, 1], yerr=pos_radec[:, 2], ls="none", marker="o", color=sns.color_palette()[2], ) plt.subplot(1, 2, 2) bovy_plot.bovy_plot( trackRADec_trailing[:, 0], sdf_trailing._interpolatedObsTrackLB[:, 3], color=sns.color_palette()[0], xrange=[250.0, 210.0], yrange=[-80.0, 0.0], xlabel=r"$\mathrm{RA}\,(\mathrm{degree})$", ylabel=r"$V_{\mathrm{los}}\,(\mathrm{km\,s}^{-1})$", gcf=True, ) bovy_plot.bovy_plot( trackRADec_leading[:, 0], sdf_leading._interpolatedObsTrackLB[:, 3], color=sns.color_palette()[0], overplot=True, ) plt.plot( radec_sample_trailing[:, 0], lb_sample_trailing[3], "k.", alpha=0.01, zorder=0, ) plt.plot( radec_sample_leading[:, 0], lb_sample_leading[3], "k.", alpha=0.01, zorder=0, ) plt.errorbar( rvel_ra[:, 0], rvel_ra[:, 1], yerr=rvel_ra[:, 2], ls="none", marker="o", color=sns.color_palette()[2], ) plt.savefig("figures/fiducial_model.pdf") return
def _fit_orbit_mlogl(new_vxvv, vxvv, vxvv_err, pot, radec, lb, customsky, lb_to_customsky, pmllpmbb_to_customsky, tmockAA, ro, vo, obs): """The log likelihood for fitting an orbit""" #Use this _parse_args routine, which does forward and backward integration iR, ivR, ivT, iz, ivz, iphi = tmockAA._parse_args(True, False, new_vxvv[0], new_vxvv[1], new_vxvv[2], new_vxvv[3], new_vxvv[4], new_vxvv[5]) if radec or lb or customsky: #Need to transform to (l,b), (ra,dec), or a custom set #First transform to X,Y,Z,vX,vY,vZ (Galactic) X, Y, Z = coords.galcencyl_to_XYZ(iR.flatten(), iphi.flatten(), iz.flatten(), Xsun=obs[0] / ro, Zsun=obs[2] / ro).T vX,vY,vZ = coords.galcencyl_to_vxvyvz(ivR.flatten(),ivT.flatten(), ivz.flatten(),iphi.flatten(), vsun=nu.array(\ obs[3:6])/vo,Xsun=obs[0]/ro,Zsun=obs[2]/ro).T bad_indx = (X == 0.) * (Y == 0.) * (Z == 0.) if True in bad_indx: X[bad_indx] += ro / 10000. lbdvrpmllpmbb = coords.rectgal_to_sphergal(X * ro, Y * ro, Z * ro, vX * vo, vY * vo, vZ * vo, degree=True) if lb: orb_vxvv = nu.array([ lbdvrpmllpmbb[:, 0], lbdvrpmllpmbb[:, 1], lbdvrpmllpmbb[:, 2], lbdvrpmllpmbb[:, 4], lbdvrpmllpmbb[:, 5], lbdvrpmllpmbb[:, 3] ]).T elif radec: #Further transform to ra,dec,pmra,pmdec radec = coords.lb_to_radec(lbdvrpmllpmbb[:, 0], lbdvrpmllpmbb[:, 1], degree=True, epoch=None) pmrapmdec = coords.pmllpmbb_to_pmrapmdec(lbdvrpmllpmbb[:, 4], lbdvrpmllpmbb[:, 5], lbdvrpmllpmbb[:, 0], lbdvrpmllpmbb[:, 1], degree=True, epoch=None) orb_vxvv = nu.array([ radec[:, 0], radec[:, 1], lbdvrpmllpmbb[:, 2], pmrapmdec[:, 0], pmrapmdec[:, 1], lbdvrpmllpmbb[:, 3] ]).T elif customsky: #Further transform to ra,dec,pmra,pmdec customradec = lb_to_customsky(lbdvrpmllpmbb[:, 0], lbdvrpmllpmbb[:, 1], degree=True) custompmrapmdec = pmllpmbb_to_customsky(lbdvrpmllpmbb[:, 4], lbdvrpmllpmbb[:, 5], lbdvrpmllpmbb[:, 0], lbdvrpmllpmbb[:, 1], degree=True) orb_vxvv = nu.array([ customradec[:, 0], customradec[:, 1], lbdvrpmllpmbb[:, 2], custompmrapmdec[:, 0], custompmrapmdec[:, 1], lbdvrpmllpmbb[:, 3] ]).T else: #shape=(2tintJ-1,6) orb_vxvv = nu.array([ iR.flatten(), ivR.flatten(), ivT.flatten(), iz.flatten(), ivz.flatten(), iphi.flatten() ]).T out = 0. for ii in range(vxvv.shape[0]): sub_vxvv = (orb_vxvv - vxvv[ii, :].flatten())**2. #print(sub_vxvv[nu.argmin(nu.sum(sub_vxvv,axis=1))]) if not vxvv_err is None: sub_vxvv /= vxvv_err[ii, :]**2. else: sub_vxvv /= 0.01**2. out += logsumexp(-0.5 * nu.sum(sub_vxvv, axis=1)) return -out
def main(args: Optional[list] = None, opts: Optional[Namespace] = None): """Fit MWPotential2014 Script Function. Parameters ---------- args : list, optional an optional single argument that holds the sys.argv list, except for the script name (e.g., argv[1:]) opts : Namespace, optional pre-constructed results of parsed args if not None, used ONLY if args is None """ if opts is not None and args is None: pass else: if opts is not None: warnings.warn("Not using `opts` because `args` are given") parser = make_parser() opts = parser.parse_args(args) fpath = opts.fpath + "/" if not opts.fpath.endswith("/") else opts.fpath opath = opts.opath + "/" if not opts.opath.endswith("/") else opts.opath # plot chains print("Plotting Chains") fig = mcmc_util.plot_chains(opath) fig.savefig(fpath + "chains.pdf") plt.close(fig) print("Need to continue chains:", end=" ") for i in range(32): ngood = mcmc_util.determine_nburn( filename=opath + f"mwpot14-fitsigma-{i:02}.dat", return_nsamples=True, ) if ngood < 4000: print(f"{i:02} (N={ngood})", end=", ") ############################################################### # RESULTING PDFS data, _, weights, _ = read_mcmc(nburn=None, skip=1, evi_func=lambda x: 1.0) plot_corner(data, weights=weights) plt.savefig("figures/PDFs/corner.pdf") plt.close() # -------------- savefilename = "output/pal5_forces_mcmc.pkl" if not os.path.exists(savefilename): data_wf, index_wf, weights_wf, evi_wf = read_mcmc( nburn=None, addforces=True, skip=1, evi_func=lambda x: 1.0 ) save_pickles(savefilename, data_wf, index_wf, weights_wf, evi_wf) else: with open(savefilename, "rb") as savefile: data_wf = pickle.load(savefile) index_wf = pickle.load(savefile) weights_wf = pickle.load(savefile) evi_wf = pickle.load(savefile) # -------------- plot_corner(data_wf, weights=weights_wf, addvcprior=False) plt.savefig("figures/PDFs/corner_wf.pdf") plt.close() # -------------- # Which potential is preferred? data_noforce, potindx, weights, evidences = read_mcmc(evi_func=evi_harmonic) fig = plt.figure(figsize=(6, 4)) bovy_plot.bovy_plot( potindx, np.log(evidences), "o", xrange=[-1, 34], yrange=[-35, -22], xlabel=r"$\mathrm{Potential\ index}$", ylabel=r"$\ln\ \mathrm{evidence}$", ) data_noforce, potindx, weights, evidences = read_mcmc(evi_func=evi_laplace) bovy_plot.bovy_plot(potindx, np.log(evidences) - 30.0, "d", overplot=True) data_noforce, potindx, weights, evidences = read_mcmc( evi_func=lambda x: np.exp(np.amax(x[:, -1])) ) bovy_plot.bovy_plot(potindx, np.log(evidences) - 8.0, "s", overplot=True) data_noforce, potindx, weights, evidences = read_mcmc( evi_func=lambda x: np.exp(-25.0) if (np.log(evi_harmonic(x)) > -25.0) else np.exp(-50.0) ) bovy_plot.bovy_plot(potindx, np.log(evidences), "o", overplot=True) plt.savefig("figures/PDFs/preferred_pot.pdf") plt.close() ############################################################### # Look at the results for individual potentials # -------------- # The flattening $c$ npot = 32 nwalkers = 12 plt.figure(figsize=(16, 6)) cmap = cm.plasma maxl = np.zeros((npot, 2)) for en, ii in enumerate(range(npot)): data_ip, _, weights_ip, evi_ip = read_mcmc(singlepot=ii, evi_func=evi_harmonic) try: maxl[en, 0] = np.amax(data_ip[:, -1]) maxl[en, 1] = np.log(evi_ip[0]) except ValueError: maxl[en] = -10000000.0 plt.subplot(2, 4, en // 4 + 1) bovy_plot.bovy_hist( data_ip[:, 0], range=[0.5, 2.0], bins=26, histtype="step", color=cmap((en % 4) / 3.0), normed=True, xlabel=r"$c$", lw=1.5, overplot=True, ) if en % 4 == 0: bovy_plot.bovy_text( r"$\mathrm{Potential\ %i\ to\ % i}$" % (en, en + 3), size=17.0, top_left=True, ) plt.tight_layout() plt.savefig("figures/flattening_c.pdf") plt.close() ############################################################### # What is the effective prior in $(F_R,F_Z)$? frfzprior_savefilename = "frfzprior.pkl" if not os.path.exists(frfzprior_savefilename): # Compute for each potential separately nvoc = 10000 ro = 8.0 npot = 32 fs = np.zeros((2, nvoc, npot)) for en, ii in tqdm(enumerate(range(npot))): fn = f"output/fitsigma/mwpot14-fitsigma-{i:02}.dat" # Read the potential parameters with open(fn, "r") as savefile: line1 = savefile.readline() potparams = [float(s) for s in (line1.split(":")[1].split(","))] for jj in range(nvoc): c = np.random.uniform() * 1.5 + 0.5 tvo = np.random.uniform() * 50.0 + 200.0 pot = mw_pot.setup_potential(potparams, c, False, False, REFR0, tvo) fs[:, jj, ii] = np.array(pal5_util.force_pal5(pot, 23.46, REFR0, tvo))[ :2 ] save_pickles(frfzprior_savefilename, fs) else: with open(frfzprior_savefilename, "rb") as savefile: fs = pickle.load(savefile) # -------------- plt.figure(figsize=(6, 6)) bovy_plot.scatterplot( fs[0].flatten(), fs[1].flatten(), "k,", xrange=[-1.75, -0.25], yrange=[-2.5, -1.2], xlabel=r"$F_R(\mathrm{Pal\ 5})$", ylabel=r"$F_Z(\mathrm{Pal\ 5})$", onedhists=True, ) bovy_plot.scatterplot( data_wf[:, 7], data_wf[:, 8], weights=weights_wf, bins=26, xrange=[-1.75, -0.25], yrange=[-2.5, -1.2], justcontours=True, cntrcolors="w", overplot=True, onedhists=True, ) plt.axvline(-0.81, color=sns.color_palette()[0]) plt.axhline(-1.85, color=sns.color_palette()[0]) plt.savefig("figures/effective_force_prior.pdf") plt.close() # -------------- # The ratio of the posterior and the prior bovy_plot.bovy_print( axes_labelsize=17.0, text_fontsize=12.0, xtick_labelsize=14.0, ytick_labelsize=14.0, ) plt.figure(figsize=(12.5, 4)) def axes_white(): for k, spine in plt.gca().spines.items(): # ax.spines is a dictionary spine.set_color("w") plt.gca().tick_params(axis="x", which="both", colors="w") plt.gca().tick_params(axis="y", which="both", colors="w") [t.set_color("k") for t in plt.gca().xaxis.get_ticklabels()] [t.set_color("k") for t in plt.gca().yaxis.get_ticklabels()] return None bins = 32 trange = [[-1.75, -0.25], [-2.5, -1.2]] tw = copy.deepcopy(weights_wf) tw[index_wf == 14] = 0.0 # Didn't converge properly H_prior, xedges, yedges = np.histogram2d( fs[0].flatten(), fs[1].flatten(), bins=bins, range=trange, normed=True ) H_post, xedges, yedges = np.histogram2d( data_wf[:, 7], data_wf[:, 8], weights=tw, bins=bins, range=trange, normed=True, ) H_like = H_post / H_prior H_like[H_prior == 0.0] = 0.0 plt.subplot(1, 3, 1) bovy_plot.bovy_dens2d( H_prior.T, origin="lower", cmap="viridis", interpolation="nearest", xrange=[xedges[0], xedges[-1]], yrange=[yedges[0], yedges[-1]], xlabel=r"$F_R(\mathrm{Pal\ 5})\,(\mathrm{km\,s}^{-1}\,\mathrm{Myr}^{-1})$", ylabel=r"$F_Z(\mathrm{Pal\ 5})\,(\mathrm{km\,s}^{-1}\,\mathrm{Myr}^{-1})$", gcf=True, ) bovy_plot.bovy_text(r"$\mathbf{Prior}$", top_left=True, size=19.0, color="w") axes_white() plt.subplot(1, 3, 2) bovy_plot.bovy_dens2d( H_post.T, origin="lower", cmap="viridis", interpolation="nearest", xrange=[xedges[0], xedges[-1]], yrange=[yedges[0], yedges[-1]], xlabel=r"$F_R(\mathrm{Pal\ 5})\,(\mathrm{km\,s}^{-1}\,\mathrm{Myr}^{-1})$", gcf=True, ) bovy_plot.bovy_text(r"$\mathbf{Posterior}$", top_left=True, size=19.0, color="w") axes_white() plt.subplot(1, 3, 3) bovy_plot.bovy_dens2d( H_like.T, origin="lower", cmap="viridis", interpolation="nearest", vmin=0.1, vmax=4.0, xrange=[xedges[0], xedges[-1]], yrange=[yedges[0], yedges[-1]], xlabel=r"$F_R(\mathrm{Pal\ 5})\,(\mathrm{km\,s}^{-1}\,\mathrm{Myr}^{-1})$", gcf=True, ) bovy_plot.bovy_text(r"$\mathbf{Likelihood}$", top_left=True, size=19.0, color="w") axes_white() def qline(FR, q=0.95): return 2.0 * FR / q ** 2.0 q = 0.94 plt.plot([-1.25, -0.2], [qline(-1.25, q=q), qline(-0.2, q=q)], "w--") bovy_plot.bovy_text(-1.7, -2.2, r"$q_\Phi = 0.94$", size=16.0, color="w") plt.plot((-1.25, -1.02), (-2.19, qline(-1.02, q=q)), "w-", lw=0.8) plt.tight_layout() plt.savefig( "figures/pal5post.pdf", bbox_inches="tight", ) plt.close() # -------------- # Projection onto the direction perpendicular to constant $q = 0.94$: frs = np.tile(0.5 * (xedges[:-1] + xedges[1:]), (len(yedges) - 1, 1)).T fzs = np.tile(0.5 * (yedges[:-1] + yedges[1:]), (len(xedges) - 1, 1)) plt.figure(figsize=(6, 4)) txlabel = r"$F_\perp$" dum = bovy_plot.bovy_hist( (-2.0 * (frs + 0.8) + 0.94 ** 2.0 * (fzs + 1.82)).flatten(), weights=H_prior.flatten(), bins=21, histtype="step", lw=2.0, xrange=[-1.5, 1.5], xlabel=txlabel, normed=True, ) dum = bovy_plot.bovy_hist( (-2.0 * (frs + 0.8) + 0.94 ** 2.0 * (fzs + 1.82)).flatten(), weights=H_post.flatten(), bins=21, histtype="step", lw=2.0, overplot=True, xrange=[-1.5, 1.5], normed=True, ) dum = bovy_plot.bovy_hist( (-2.0 * (frs + 0.8) + 0.94 ** 2.0 * (fzs + 1.82)).flatten(), weights=H_like.flatten(), bins=21, histtype="step", lw=2.0, overplot=True, xrange=[-1.5, 1.5], normed=True, ) plt.savefig("figures/PDFs/projection_perp_to_q0p94.pdf") plt.close() mq = ( np.sum( (-2.0 * (frs + 0.8) + 0.94 ** 2.0 * (fzs + 1.82)).flatten() * H_like.flatten() ) ) / np.sum(H_like.flatten()) print( mq, np.sqrt( ( np.sum( ((-2.0 * (frs + 0.8) + 0.94 ** 2.0 * (fzs + 1.82)).flatten() - mq) ** 2.0 * H_like.flatten() ) ) / np.sum(H_like.flatten()) ), ) # -------------- # Projection onto the direction parallel to constant $q = 0.94$: frs = np.tile(0.5 * (xedges[:-1] + xedges[1:]), (len(yedges) - 1, 1)).T fzs = np.tile(0.5 * (yedges[:-1] + yedges[1:]), (len(xedges) - 1, 1)) plt.figure(figsize=(6, 4)) txlabel = r"$F_\parallel$" dum = bovy_plot.bovy_hist( (0.94 ** 2.0 * (frs + 0.8) + 2.0 * (fzs + 1.82)).flatten(), weights=H_prior.flatten(), bins=21, histtype="step", lw=2.0, xrange=[-2.5, 2.5], xlabel=txlabel, normed=True, ) dum = bovy_plot.bovy_hist( (0.94 ** 2.0 * (frs + 0.8) + 2.0 * (fzs + 1.82)).flatten(), weights=H_post.flatten(), bins=21, histtype="step", lw=2.0, overplot=True, xrange=[-2.5, 2.5], normed=True, ) dum = bovy_plot.bovy_hist( (0.94 ** 2.0 * (frs + 0.8) + 2.0 * (fzs + 1.82)).flatten(), weights=H_like.flatten(), bins=21, histtype="step", lw=2.0, overplot=True, xrange=[-2.5, 2.5], normed=True, ) plt.savefig("figures/PDFs/projection_prll_to_q0p94.pdf") plt.close() mq = ( np.sum( (0.94 ** 2.0 * (frs + 0.8) + 2.0 * (fzs + 1.82)).flatten() * H_like.flatten() ) ) / np.sum(H_like.flatten()) print( mq, np.sqrt( ( np.sum( ((0.94 ** 2.0 * (frs + 0.8) + 2.0 * (fzs + 1.82)).flatten() - mq) ** 2.0 * H_like.flatten() ) ) / np.sum(H_like.flatten()) ), ) # -------------- # Thus, there is only a weak constraint on $F_\parallel$. nrow = int(np.ceil(npot / 4.0)) plt.figure(figsize=(16, nrow * 4)) for en, ii in enumerate(range(npot)): plt.subplot(nrow, 4, en + 1) if ii % 4 == 0: tylabel = r"$F_Z(\mathrm{Pal\ 5})$" else: tylabel = None if ii // 4 == nrow - 1: txlabel = r"$F_R(\mathrm{Pal\ 5})$" else: txlabel = None bovy_plot.scatterplot( fs[0][:, en], fs[1][:, en], "k,", xrange=[-1.75, -0.25], yrange=[-2.5, -1.0], xlabel=txlabel, ylabel=tylabel, gcf=True, ) bovy_plot.scatterplot( data_wf[:, 7], data_wf[:, 8], weights=weights_wf, bins=26, xrange=[-1.75, -0.25], yrange=[-2.5, -1.0], justcontours=True, cntrcolors="w", overplot=True, ) bovy_plot.scatterplot( data_wf[index_wf == ii, 7], data_wf[index_wf == ii, 8], weights=weights_wf[index_wf == ii], bins=26, xrange=[-1.75, -0.25], yrange=[-2.5, -1.0], justcontours=True, # cntrcolors=sns.color_palette()[2], overplot=True, ) plt.axvline(-0.80, color=sns.color_palette()[0]) plt.axhline(-1.83, color=sns.color_palette()[0]) bovy_plot.bovy_text(r"$\mathrm{Potential}\ %i$" % ii, size=17.0, top_left=True) plt.savefig("figures/PDFs/constain_F_prll.pdf") plt.close() # -------------- # Let's plot four representative ones for the paper: bovy_plot.bovy_print( axes_labelsize=17.0, text_fontsize=12.0, xtick_labelsize=14.0, ytick_labelsize=14.0, ) nullfmt = NullFormatter() nrow = 1 plt.figure(figsize=(15, nrow * 4)) for en, ii in enumerate([0, 15, 24, 25]): plt.subplot(nrow, 4, en + 1) if en % 4 == 0: tylabel = ( r"$F_Z(\mathrm{Pal\ 5})\,(\mathrm{km\,s}^{-1}\,\mathrm{Myr}^{-1})$" ) else: tylabel = None if en // 4 == nrow - 1: txlabel = ( r"$F_R(\mathrm{Pal\ 5})\,(\mathrm{km\,s}^{-1}\,\mathrm{Myr}^{-1})$" ) else: txlabel = None bovy_plot.scatterplot( fs[0][:, ii], fs[1][:, ii], "k,", bins=31, xrange=[-1.75, -0.25], yrange=[-2.5, -1.0], xlabel=txlabel, ylabel=tylabel, gcf=True, ) bovy_plot.scatterplot( data_wf[:, 7], data_wf[:, 8], weights=weights_wf, bins=21, xrange=[-1.75, -0.25], yrange=[-2.5, -1.0], justcontours=True, cntrcolors=sns.color_palette("colorblind")[2], cntrls="--", cntrlw=2.0, overplot=True, ) bovy_plot.scatterplot( data_wf[index_wf == ii, 7], data_wf[index_wf == ii, 8], weights=weights_wf[index_wf == ii], bins=21, xrange=[-1.75, -0.25], yrange=[-2.5, -1.0], justcontours=True, cntrcolors=sns.color_palette("colorblind")[0], cntrlw=2.5, overplot=True, ) if en > 0: plt.gca().yaxis.set_major_formatter(nullfmt) plt.tight_layout() plt.savefig( "figures/pal5post_examples.pdf", bbox_inches="tight", ) plt.close() ############################################################### # What about $q_\Phi$? bins = 47 plt.figure(figsize=(6, 4)) dum = bovy_plot.bovy_hist( np.sqrt(2.0 * fs[0].flatten() / fs[1].flatten()), histtype="step", lw=2.0, bins=bins, xlabel=r"$q_\mathrm{\Phi}$", xrange=[0.7, 1.25], normed=True, ) dum = bovy_plot.bovy_hist( np.sqrt(16.8 / 8.4 * data_wf[:, -2] / data_wf[:, -1]), weights=weights_wf, histtype="step", lw=2.0, bins=bins, overplot=True, xrange=[0.7, 1.25], normed=True, ) mq = np.sum( np.sqrt(16.8 / 8.4 * data_wf[:, -2] / data_wf[:, -1]) * weights_wf ) / np.sum(weights_wf) sq = np.sqrt( np.sum( (np.sqrt(16.8 / 8.4 * data_wf[:, -2] / data_wf[:, -1]) - mq) ** 2.0 * weights_wf ) / np.sum(weights_wf) ) print("From posterior samples: q = %.3f +/- %.3f" % (mq, sq)) Hq_post, xedges = np.histogram( np.sqrt(16.8 / 8.4 * data_wf[:, -2] / data_wf[:, -1]), weights=weights_wf, bins=bins, range=[0.7, 1.25], normed=True, ) Hq_prior, xedges = np.histogram( np.sqrt(2.0 * fs[0].flatten() / fs[1].flatten()), bins=bins, range=[0.7, 1.25], normed=True, ) qs = 0.5 * (xedges[:-1] + xedges[1:]) Hq_like = Hq_post / Hq_prior Hq_like[Hq_post == 0.0] = 0.0 mq = np.sum(qs * Hq_like) / np.sum(Hq_like) sq = np.sqrt(np.sum((qs - mq) ** 2.0 * Hq_like) / np.sum(Hq_like)) print("From likelihood of samples: q = %.3f +/- %.3f" % (mq, sq)) plt.savefig("figures/q_phi.pdf") plt.close() # It appears that $q_\Phi$ is the quantity that is the most strongly constrained by the Pal 5 data. ############################################################### # A sampling of tracks from the MCMC savefilename = "mwpot14-pal5-mcmcTracks.pkl" pmdecpar = 2.257 / 2.296 pmdecperp = -2.296 / 2.257 if os.path.exists(savefilename): with open(savefilename, "rb") as savefile: pal5_track_samples = pickle.load(savefile) forces = pickle.load(savefile) all_potparams = pickle.load(savefile) all_params = pickle.load(savefile) else: np.random.seed(1) ntracks = 21 multi = 8 pal5_track_samples = np.zeros((ntracks, 2, 6, pal5varyc[0].shape[1])) forces = np.zeros((ntracks, 2)) all_potparams = np.zeros((ntracks, 5)) all_params = np.zeros((ntracks, 7)) for ii in range(ntracks): # Pick a random potential from among the set, but leave 14 out pindx = 14 while pindx == 14: pindx = np.random.permutation(32)[0] # Load this potential fn = f"output/fitsigma/mwpot14-fitsigma-{pindx:02}.dat" with open(fn, "r") as savefile: line1 = savefile.readline() potparams = [float(s) for s in (line1.split(":")[1].split(","))] all_potparams[ii] = potparams # Now pick a random sample from this MCMC chain tnburn = mcmc_util.determine_nburn(fn) tdata = np.loadtxt(fn, comments="#", delimiter=",") tdata = tdata[tnburn::] tdata = tdata[np.random.permutation(len(tdata))[0]] all_params[ii] = tdata tvo = tdata[1] * REFV0 pot = mw_pot.setup_potential(potparams, tdata[0], False, False, REFR0, tvo) forces[ii, :] = pal5_util.force_pal5(pot, 23.46, REFR0, tvo)[:2] # Now compute the stream model for this setup dist = tdata[2] * 22.0 pmra = -2.296 + tdata[3] + tdata[4] pmdecpar = 2.257 / 2.296 pmdecperp = -2.296 / 2.257 pmdec = -2.257 + tdata[3] * pmdecpar + tdata[4] * pmdecperp vlos = -58.7 sigv = 0.4 * np.exp(tdata[5]) prog = Orbit( [229.018, -0.124, dist, pmra, pmdec, vlos], radec=True, ro=REFR0, vo=tvo, solarmotion=[-11.1, 24.0, 7.25], ) tsdf_trailing, tsdf_leading = pal5_util.setup_sdf( pot, prog, sigv, 10.0, REFR0, tvo, multi=multi, nTrackChunks=8, trailing_only=False, verbose=True, useTM=False, ) # Compute the track for jj, sdf in enumerate([tsdf_trailing, tsdf_leading]): trackRADec = bovy_coords.lb_to_radec( sdf._interpolatedObsTrackLB[:, 0], sdf._interpolatedObsTrackLB[:, 1], degree=True, ) trackpmRADec = bovy_coords.pmllpmbb_to_pmrapmdec( sdf._interpolatedObsTrackLB[:, 4], sdf._interpolatedObsTrackLB[:, 5], sdf._interpolatedObsTrackLB[:, 0], sdf._interpolatedObsTrackLB[:, 1], degree=True, ) # Store the track pal5_track_samples[ii, jj, 0] = trackRADec[:, 0] pal5_track_samples[ii, jj, 1] = trackRADec[:, 1] pal5_track_samples[ii, jj, 2] = sdf._interpolatedObsTrackLB[:, 2] pal5_track_samples[ii, jj, 3] = sdf._interpolatedObsTrackLB[:, 3] pal5_track_samples[ii, jj, 4] = trackpmRADec[:, 0] pal5_track_samples[ii, jj, 5] = trackpmRADec[:, 1] save_pickles( savefilename, pal5_track_samples, forces, all_potparams, all_params ) # -------------- bovy_plot.bovy_print( axes_labelsize=17.0, text_fontsize=12.0, xtick_labelsize=14.0, ytick_labelsize=14.0, ) plt.figure(figsize=(12, 8)) gs = gridspec.GridSpec(2, 2, wspace=0.225, hspace=0.1, right=0.94) ntracks = pal5_track_samples.shape[0] cmap = cm.plasma alpha = 0.7 for ii in range(ntracks): tc = cmap((forces[ii, 1] + 2.5) / 1.0) for jj in range(2): # RA, Dec plt.subplot(gs[0]) plt.plot( pal5_track_samples[ii, jj, 0], pal5_track_samples[ii, jj, 1], "-", color=tc, alpha=alpha, ) # RA, Vlos plt.subplot(gs[1]) plt.plot( pal5_track_samples[ii, jj, 0], pal5_track_samples[ii, jj, 3], "-", color=tc, alpha=alpha, ) # RA, Dist plt.subplot(gs[2]) plt.plot( pal5_track_samples[ii, jj, 0], pal5_track_samples[ii, jj, 2] - all_params[ii, 2] * 22.0, "-", color=tc, alpha=alpha, ) # RA, pm_parallel plt.subplot(gs[3]) plt.plot( pal5_track_samples[ii, jj, 0, : 500 + 500 * (1 - jj)], np.sqrt(1.0 + (2.257 / 2.296) ** 2.0) * ( (pal5_track_samples[ii, jj, 4, : 500 + 500 * (1 - jj)] + 2.296) * pmdecperp - (pal5_track_samples[ii, jj, 5, : 500 + 500 * (1 - jj)] + 2.257) ) / (pmdecpar - pmdecperp), "-", color=tc, alpha=alpha, ) plot_data_add_labels( p1=(gs[0],), p2=(gs[1],), noxlabel_dec=True, noxlabel_vlos=True ) plt.subplot(gs[2]) plt.xlim(250.0, 221.0) plt.ylim(-3.0, 1.5) bovy_plot._add_ticks() plt.xlabel(r"$\mathrm{RA}\,(\mathrm{degree})$") plt.ylabel(r"$\Delta\mathrm{Distance}\,(\mathrm{kpc})$") plt.subplot(gs[3]) plt.xlim(250.0, 221.0) plt.ylim(-0.5, 0.5) bovy_plot._add_ticks() plt.xlabel(r"$\mathrm{RA}\,(\mathrm{degree})$") plt.ylabel(r"$\Delta\mu_\parallel\,(\mathrm{mas\,yr}^{-1})$") # Colorbar gs2 = gridspec.GridSpec(2, 1, wspace=0.0, left=0.95, right=0.975) plt.subplot(gs2[:, -1]) sm = plt.cm.ScalarMappable(cmap=cmap, norm=plt.Normalize(vmin=-2.5, vmax=-1.5)) sm._A = [] CB1 = plt.colorbar(sm, orientation="vertical", cax=plt.gca()) CB1.set_label( r"$F_Z(\mathrm{Pal\ 5})\,(\mathrm{km\,s}^{-1}\,\mathrm{Myr}^{-1})$", fontsize=18.0, ) plt.savefig( "figures/pal5tracksamples.pdf", bbox_inches="tight", ) plt.close() ############################################################### # What about Kuepper et al. (2015)? # Can we recover the Kuepper et al. (2015) result as prior + $q_\Phi = # 0.94 \pm 0.05$ + $V_c(R_0)$ between 200 and 280 km/s? For simplicity # we will not vary $R_0$, which should not have a big impact. s = sample_kuepper_flattening_post(50000, 0.94, 0.05) plot_kuepper_samples(s) plt.savefig("figures/kuepper_samples.pdf") plt.close() # The constraint on the potential flattening gets you far, but there # is more going on (the constraint on the halo mass and scale # parameter appear to come completely from the $V_c(R_0)$ constraint). # Let's add the weak constraint on the sum of the forces, scaled to # Kuepper et al.'s best-fit acceleration (which is higher than ours): s = sample_kuepper_flatteningforce_post(50000, 0.94, 0.05, -0.83, 0.36) plot_kuepper_samples(s) plt.savefig("figures/kuepper_samples_flatF.pdf") plt.close() # This gets a tight relation between $M_\mathrm{halo}$ and the scale # parameter of the halo, but does not lead to a constraint on either # independently; the halo potential flattening constraint is that of # Kuepper et al. Based on this, it appears that the information that # ties down $M_\mathrm{halo}$ comes from the overdensities, which may # be spurious (Thomas et al. 2016) and whose use in dynamical modeling # is dubious anyway. # What is Kuepper et al.'s prior on $a_{\mathrm{Pal\ 5}}$? apal5s = [] ns = 100000 for ii in range(ns): Mh = np.random.uniform() * (10.0 - 0.001) + 0.001 a = np.random.uniform() * (100.0 - 0.1) + 0.1 q = np.random.uniform() * (1.8 - 0.2) + 0.2 pot = setup_potential_kuepper(Mh, a) FR, FZ = force_pal5_kuepper(pot, q) apal5s.append(np.sqrt(FR ** 2.0 + FZ ** 2.0)) apal5s = np.array(apal5s) plt.figure(figsize=(6, 4)) dum = bovy_plot.bovy_hist( apal5s, range=[0.0, 10.0], lw=2.0, bins=51, histtype="step", normed=True, ) plt.savefig("figures/kuepper_samples_prior.pdf") plt.close()