diff --git a/ephemeris.py b/ephemeris.py new file mode 100644 index 0000000..eb10641 --- /dev/null +++ b/ephemeris.py @@ -0,0 +1,281 @@ +import numpy as np +from numpy.polynomial.polynomial import Polynomial +from astropy.table import Table +from astropy.time import Time +from astropy.coordinates.angles import Angle +from astropy.constants import c +import astropy.units as u +import de405 +import jplephem.ephem +import observability +import pprint + +deg2rad = np.pi/180. + + +class ELL1Ephemeris(dict): + """Empheris based on tempo .par file for PSR J0337""" + + def __init__(self, name='psrj1959.par'): + d, e, f = par2dict(name) + # make dictionary + dict.__init__(self, d) + self.err = e + self.fix = f + + def evaluate(self, par, mjd, t0par='TASC', integrate=False): + parpol = Polynomial((self[par], self.get(par+'DOT', 0.))) + if integrate: + parpol = parpol.integ() + dt = (mjd-self[t0par])*24.*3600. + return parpol(dt) + + def mean_anomaly(self, mjd): + return 2.*np.pi*self.evaluate('FB', mjd, integrate=True) + + def orbital_delay(self, mjd): + ma = self.mean_anomaly(mjd) + an = 2.*np.pi*self.evaluate('FB', mjd) + a1, e1, e2 = self['A1'], self['EPS1'], self['EPS2'] + dre = a1*(np.sin(ma)-0.5*(e1*np.cos(2*ma)-e2*np.sin(2*ma))) + drep = a1*np.cos(ma) + drepp = -a1*np.sin(ma) + d2bar = dre*(1-an*drep+(an*drep)**2+0.5*an**2*dre*drepp) + if 'M2' in self.keys(): + brace = 1.-self['SINI']*np.sin(ma) + d2bar += -2.*self['M2']*np.log(brace) + return d2bar + + def orbital_delay(self, mjd): + """Delay in s. Includes higher order terms and Shapiro delay.""" + ma = self.mean_anomaly(mjd) + an = 2.*np.pi*self.evaluate('FB', mjd) + a1, e1, e2 = self['A1'], self['EPS1'], self['EPS2'] + dre = a1*(np.sin(ma)-0.5*(e1*np.cos(2*ma)-e2*np.sin(2*ma))) + drep = a1*np.cos(ma) + drepp = -a1*np.sin(ma) + d2bar = dre*(1-an*drep+(an*drep)**2+0.5*an**2*dre*drepp) + if 'M2' in self.keys(): + brace = 1.-self['SINI']*np.sin(ma) + d2bar += -2.*self['M2']*np.log(brace) + return d2bar + + def radial_velocity(self, mjd): + """Radial velocity in lt-s/s. Higher-order terms ignored.""" + ma = self.mean_anomaly(mjd) + kcirc = 2.*np.pi*self['A1']*self.evaluate('FB', mjd) + e1, e2 = self['EPS1'], self['EPS2'] + vrad = kcirc*(np.cos(ma)+e1*np.sin(2*ma)+e2*np.cos(2*ma)) + return vrad + + def pos(self, mjd): + ra = self.evaluate('RAJ', mjd, 'POSEPOCH')*deg2rad + dec = self.evaluate('DECJ', mjd, 'POSEPOCH')*deg2rad + ca = np.cos(ra) + sa = np.sin(ra) + cd = np.cos(dec) + sd = np.sin(dec) + return np.array([ca*cd, sa*cd, sd]) + +def par2dict(name, substitutions={'F0': 'F', 'F1': 'FDOT', 'F2': 'FDOT2', + 'PMRA': 'RAJDOT', 'PMDEC': 'DECJDOT'}): + d = {}; e = {}; f = {} + with open(name, 'r') as parfile: + for lin in parfile: + parts = lin.split() + item = parts[0].upper() + item = substitutions.get(item, item) + assert 2 <= len(parts) <= 4 + try: + value = float(parts[1].lower().replace('d', 'e')) + d[item] = value + except ValueError: + d[item] = parts[1] + if len(parts) == 4: + f[item] = int(parts[2]) + e[item] = float(parts[3].lower().replace('d', 'e')) + # convert RA, DEC from strings (hh:mm:ss.sss, ddd:mm:ss.ss) to degrees + d['RAJ'] = Angle(d['RAJ'], u.hr).degrees + e['RAJ'] = e['RAJ']/15./3600. + d['DECJ'] = Angle(d['DECJ'], u.deg).degrees + e['DECJ'] = e['DECJ']/3600. + if 'RAJDOT' in d.keys() and 'DECJDOT' in d.keys(): + # convert to degrees/s + conv = (1.*u.mas/u.yr).to(u.deg/u.s).value + cosdec = np.cos((d['DECJ']*u.deg).to(u.rad).value) + d['RAJDOT'] *= conv/cosdec + e['RAJDOT'] *= conv/cosdec + d['DECJDOT'] *= conv + e['DECJDOT'] *= conv + + if 'FB' not in d.keys(): + pb = d.pop('PB') + d['FB'] = 1./(pb*24.*3600.) + e['FB'] = e.pop('PB')/pb*d['FB'] + f['FB'] = f.pop('PB') + if 'PBDOT' in d.keys(): + d['FBDOT'] = -d.pop('PBDOT')/pb*d['FB'] + e['FBDOT'] = e.pop('PBDOT')/pb*d['FB'] + f['FBDOT'] = f.pop('PBDOT') + return d, e, f + +class JPLEphemeris(jplephem.ephem.Ephemeris): + """JPLEphemeris, but including 'earth'""" + def position(self, name, tdb): + """Compute the position of `name` at time `tdb`. + + Run the `names()` method on this ephemeris to learn the values + it will accept for the `name` parameter, such as ``'mars'`` and + ``'earthmoon'``. The barycentric dynamical time `tdb` can be + either a normal number or a NumPy array of times, in which case + each of the three return values ``(x, y, z)`` will be an array. + + """ + if name == 'earth': + return self._interpolate_earth(tdb, False) + else: + return self._interpolate(name, tdb, False) + + def compute(self, name, tdb): + """Compute the position and velocity of `name` at time `tdb`. + + Run the `names()` method on this ephemeris to learn the values + it will accept for the `name` parameter, such as ``'mars'`` and + ``'earthmoon'``. The barycentric dynamical time `tdb` can be + either a normal number or a NumPy array of times, in which case + each of the six return values ``(x, y, z, dx, dy, dz)`` will be + an array. + """ + if name == 'earth': + return self._interpolate_earth(tdb, True) + else: + return self._interpolate(name, tdb, True) + + def _interpolate_earth(self, tdb, differentiate): + earthmoon_ssb = self._interpolate('earthmoon', tdb, differentiate) + moon_earth = self._interpolate('moon', tdb, differentiate) + # earth relative to Moon-Earth barycentre + # earth_share=1/(1+EMRAT), EMRAT=Earth/Moon mass ratio + return -moon_earth*self.earth_share + earthmoon_ssb + +if __name__ == '__main__': + eph1957 = ELL1Ephemeris('psrj1959.par') + jpleph = JPLEphemeris(de405) + mjd = Time('2013-05-16 23:45:00', scale='utc').mjd+np.linspace(0.,1.,24) + mjd = Time(mjd, format='mjd', scale='utc', + lon=(74*u.deg+02*u.arcmin+59.07*u.arcsec).to(u.deg).value, + lat=(19*u.deg+05*u.arcmin+47.46*u.arcsec).to(u.deg).value) + + + #frequency and period of pulsar(constants) + f_p=eph1957.evaluate('F',mjd.tdb.mjd,t0par='PEPOCH') + p_p=1./(f_p[0]) + + #period for every 1000 pulse in days + finish=1./24 + q=0 + while (q UT1) + # import sidereal + # # SHOULD TRANSFER TO UT1!! + # gmst = sidereal.gmst82(mjd.utc.jd1, mjd,utc.jd2) + + + if False: + # check with Fisher's ephemeris + import rf_ephem + rf_ephem.set_ephemeris_dir('/data/mhvk/packages/jplephem', 'DEc421') + rf_ephem.set_observer_coordinates(*xyz_gmrt) + rf_delay = rf_ephem.pulse_delay( + eph1957.evaluate('RAJ',mjd.tdb.mjd[0])/15., + eph1957.evaluate('DECJ',mjd.tdb.mjd[0]), + int(mjd.utc.mjd[0]), + mjd.utc.mjd[0]-int(mjd.utc.mjd[0]), + len(mjd), + (mjd.utc.mjd[1]-mjd.utc.mjd[0])*24.*3600.)['delay'] + rf_rv = rf_ephem.doppler_fraction( + eph1957.evaluate('RAJ',mjd.tdb.mjd[0])/15., + eph1957.evaluate('DECJ',mjd.tdb.mjd[0]), + int(mjd.utc.mjd[0]), + mjd.utc.mjd[0]-int(mjd.utc.mjd[0]), + len(mjd), + (mjd.utc.mjd[1]-mjd.utc.mjd[0])*24.*3600.)['frac'] + + import matplotlib.pylab as plt + plt.ion() + plt.plot(mjd.utc.mjd, delay-rf_delay-d_orb) + plt.plot(mjd.utc.mjd, (rv-rf_rv-v_orb)*c.to(u.km/u.s).value) + plt.draw() + plt.show()