Source code for ixpeobssim.srcmodel.tdelays

#!/usr/bin/env python
#
# Copyright (C) 2015, the ixpeobssim team.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

"""
Module containing functions and classes to manage time delays
"""

from __future__ import print_function, division

import numpy
import astropy.constants as const

from ixpeobssim.srcmodel.ephemeris import get_earth_barycentric_ephemeris, get_eccentric_anomaly
from ixpeobssim.utils.time_ import met_to_mjd, mjd_to_met
from ixpeobssim.core.spline import xInterpolatedUnivariateSpline

# pylint: disable=invalid-name, too-many-arguments, too-many-locals

"""
Time delays in the Solar System
"""

[docs] def roemers_f(t_, **kwargs): """Roemer delays formula referred to Solar System Barycenter. Warning ------- IXPE satellite ephemeris not implemented yet. Args ---- t_ : float Terrestrial time in MET **kwargs : ra : Right ascension of the source dec : Declination of the source Returns ------- array float Return the earth barycentric vector """ earth_vector = get_earth_barycentric_ephemeris(t_) c_ = const.c.value # vacuum speed of light # source coordinates lat = numpy.deg2rad(kwargs['ra']) lon = numpy.deg2rad(kwargs['dec']) # source point unit vector from SSB s_ = numpy.array([numpy.cos(lat)*numpy.cos(lon), numpy.cos(lat)*numpy.sin(lon), numpy.sin(lat)]) # delay is the scalar product between earth SSB vector and source position func = - (1. / c_) * numpy.dot(earth_vector, s_) return func
[docs] def einsteins_f(t_, **kwargs): """Einstein delays formula referred to Solar System Barycenter. Warning ------- First implementation of satellite location, temporarily avoided. """ # Here we put an order of magnitude for IXPE orbit radius #tt_ = Time(met_to_mjd(t_), format='mjd', scale='tt', # location=(0.*u.deg, 0.*u.deg, 5.4e5*u.meter)) #tdb_ = mjd_to_met(tt_.tdb.value) #func = tdb_ - t_ func = 0. return func
[docs] def shapiros_f(t_, **kwargs): """Shapiro delays formula referred to Solar System Barycenter. Warning ------- Not implemented yet. """ func = 0. return func
[docs] def alls_f(t_, **kwargs): """All delays referred to Solar System Barycenter. """ func = roemers_f(t_, **kwargs) + \ einsteins_f(t_, **kwargs) + \ shapiros_f(t_, **kwargs) return func
""" Time delays in the Binary System """
[docs] def roemerb_f(t_, eph, **kwargs): """Roemer delays formula referred to Binary System. Warning ------- IXPE satellite ephemeris not implemented yet. Args ---- t_ : float Terrestrial time in MET eph : xOrbitalEphemeris object **kwargs : ra : Right ascension of the source dec : Declination of the source Returns ------- array float Return the earth barycentric vector """ if eph.model == 'ELL1': # Roemer delay argument phi dt = (t_ - eph.t_orbital) phi = 2. * numpy.pi * eph.omega_orb(dt) * dt # Here, I use the ELL1 model to apply Roemer delay to the TOAs/times vector func = eph.axis_proj * (numpy.sin(phi) + \ eph.eps1 * 0.5 * numpy.sin(2 * phi) - \ eph.eps2 * 0.5 * numpy.cos(2 * phi)) return func # Here we solve Kepler Equation for Roemer binary delays # Eccentric anomaly from K.E. Solution U_ = get_eccentric_anomaly(t_, eph) # Longitude of periastron in radians OM_ = numpy.deg2rad(eph.lon_periast) func = eph.axis_proj * (numpy.cos(U_) - eph.ecc) * numpy.sin(OM_) + \ eph.axis_proj * numpy.sin(U_) * numpy.sqrt(1 - eph.ecc**2) * numpy.sin(OM_) return func
[docs] def einsteinb_f(t_, **kwargs): """Einstein delays formula referred to Binary System. Warning ------- Not implemented yet. """ func = 0. return func
[docs] def shapirob_f(t_, **kwargs): """Shapiro delays formula referred to Binary System. Warning ------- Not implemented yet. """ func = 0. return func
[docs] def allb_f(t_, eph, **kwargs): """All delays referred to Binary System. """ func = roemerb_f(t_, eph, **kwargs) + \ einsteinb_f(t_, **kwargs) + \ shapirob_f(t_, **kwargs) return func
""" Dictionary for delays in Solar System (SSB) """ SSB = {'roemer': roemers_f, 'einstein': einsteins_f, 'shapiro': shapiros_f, 'all': alls_f} """ Dictionary for delays in Binary System (BS) """ BS = {'roemer': roemerb_f, 'einstein': einsteinb_f, 'shapiro': shapirob_f, 'all': allb_f}
[docs] class xTDelays: """Convenience class encapsulating times handling. Default time in input is in mjd unit, both mjd and met time scale are managed. Args ---- mjdvalue : array float array of time values in MJD unit metvalue : array float array of time values in MET unit unit : string time unit in MET or MJD name : string name of the model """ def __init__(self, mjdvalue, name='', unit='MJD'): """Constructor. """ assert unit.upper() in ('MET', 'MJD') self.mjdvalue = numpy.sort(mjdvalue) self.metvalue = mjd_to_met(self.mjdvalue) if unit in ('met', 'MET'): self.metvalue = self.mjdvalue self.mjdvalue = met_to_mjd(self.mjdvalue) self.unit = unit self.name = name
[docs] def mjd_min(self): """Return the minimum in mjd unit. """ return self.mjdvalue[0]
[docs] def mjd_max(self): """Return the maximum in mjd unit. """ return self.mjdvalue[-1]
[docs] def met_min(self): """Return the minimum in met unit. """ return self.metvalue[0]
[docs] def met_max(self): """Return the maximum in met unit. """ return self.metvalue[-1]
def __len__(self): """Return the lenght of the array. """ return len(self.mjdvalue) def __str__(self): """String formatting. """ return 'xTDelays = %s s, ref = %s, name = %s' % (self.mjdvalue, self.unit, self.name)
[docs] def apply_delay(self, ephemeris, ra, dec, delay='all', binary=False): """Return barycentered times, given an ephemeris and the source coordinates. Args ---- ephemeris : xOrbitalEphemeris object ra : float Right ascension of the source dec : float Declination of the source delay : string define the delay function to use: roemer, einstein, shapiro or all binary : Boolean When true time delay is applied in the binary system, when false in the solar system """ delta = SSB[delay](self.metvalue, ra=ra, dec=dec) if binary: delta += BS[delay](self.metvalue, ephemeris, ra=ra, dec=dec) self.__init__(self.metvalue + delta, unit='met', name='%s_DELAY' % self.name) return self.metvalue
[docs] def apply_decorr(self, ephemeris, ra, dec, samples=500, delay='all', binary=False): """Return delay effected times. Args ---- samples : int Number of samples per period """ # We need enough samples for each periodicity if hasattr(ephemeris, 'model'): num_periods = (self.met_max() - self.met_min()) / ephemeris.p_orbital if num_periods > 1: samples = int(samples * num_periods) t_ = numpy.linspace(self.met_min(), self.met_max() * 1.1, samples) delta = xInterpolatedUnivariateSpline(t_, t_) delta += xInterpolatedUnivariateSpline(t_, SSB[delay](t_, ra=ra, dec=dec)) if binary: delta += xInterpolatedUnivariateSpline(t_, BS[delay](t_, ephemeris, ra=ra, dec=dec)) metvalue = delta.inverse()(self.metvalue) self.__init__(metvalue, unit='met', name='%s_DECORR' % self.name) return self.metvalue