def test_physical_ephem_model(self): """Test physical ephemeris model""" if isinstance(self.psr, enterprise.pulsar.Tempo2Pulsar): # define signals with and without epoch TOAs eph1 = deterministic_signals.PhysicalEphemerisSignal( inc_saturn_orb=True) eph2 = deterministic_signals.PhysicalEphemerisSignal( inc_saturn_orb=True, use_epoch_toas=False) # initialize signals e1, e2 = eph1(self.psr), eph2(self.psr) # set parameters params = {'d_jupiter_mass': -8.561198198000628e-12, 'd_neptune_mass': 1.0251757860647059e-11, 'd_saturn_mass': 6.22114376130324e-12, 'd_uranus_mass': -2.1157536169469958e-10, 'frame_drift_rate': 2.874659280396648e-10, 'jup_orb_elements': np.array([0.04140015, -0.03422412, 0.01165894, -0.03525219, -0.00406852, 0.0421522]), 'sat_orb_elements': np.array([-0.39701798, -0.13322608, -0.05025925, 0.36331171, -0.17080321,0.25093799]) } # test against waveform and compare non-epoch and epoch TOA results d1 = e1.get_delay(params=params) d2 = e2.get_delay(params=params) jup_mjd, jup_orbelxyz, sat_mjd, sat_orbelxyz = ( utils.get_planet_orbital_elements()) d3 = utils.physical_ephem_delay( self.psr.toas, self.psr.planetssb, self.psr.pos_t, jup_mjd=jup_mjd, jup_orbelxyz=jup_orbelxyz, sat_mjd=sat_mjd, sat_orbelxyz=sat_orbelxyz, inc_jupiter_orb=True, inc_saturn_orb=True, **params) msg1 = 'Signal delay does not match function delay' assert np.allclose(d1, d3, rtol=1e-10), msg1 msg2 = 'epoch-TOA delay does not match full TOA delay' assert np.allclose(d1, d2, rtol=1e-10), msg2 # test against pre-computed wafeform eph_wf = np.load(datadir + '/phys_ephem_1855_test.npy') msg = 'Ephemeris delay does not match pre-computed values' assert np.allclose(d1, eph_wf, rtol=1e-10), msg # test PINT exception raising elif isinstance(self.psr, enterprise.pulsar.PintPulsar): with self.assertRaises(NotImplementedError) as context: eph1 = deterministic_signals.PhysicalEphemerisSignal( inc_saturn_orb=True) e1 = eph1(self.psr) msg = 'Physical Ephemeris model is not compatible with PINT ' msg += 'at this time.' self.assertEqual(msg, str(context.exception))
def test_physical_ephem_model_setIII(self): """Test physical ephemeris model""" # define signals with and without epoch TOAs eph1 = deterministic_signals.PhysicalEphemerisSignal( sat_orb_elements=True, model="setIII") eph2 = deterministic_signals.PhysicalEphemerisSignal( sat_orb_elements=True, use_epoch_toas=False, model="setIII") # initialize signals e1, e2 = eph1(self.psr), eph2(self.psr) # set parameters params = { "d_jupiter_mass": -8.561198198000628e-12, "d_neptune_mass": 1.0251757860647059e-11, "d_saturn_mass": 6.22114376130324e-12, "d_uranus_mass": -2.1157536169469958e-10, "frame_drift_rate": 2.874659280396648e-10, "jup_orb_elements": np.array([ 0.04140015, -0.03422412, 0.01165894, -0.03525219, -0.00406852, 0.0421522 ]), "sat_orb_elements": np.array([ -0.39701798, -0.13322608, -0.05025925, 0.36331171, -0.17080321, 0.25093799 ]), } # test against waveform and compare non-epoch and epoch TOA results d1 = e1.get_delay(params=params) d2 = e2.get_delay(params=params) (jup_mjd, jup_orbel, sat_orbel) = utils.get_planet_orbital_elements("setIII") d3 = utils.physical_ephem_delay( self.psr.toas, self.psr.planetssb, self.psr.pos_t, times=jup_mjd, jup_orbit=jup_orbel, sat_orbit=sat_orbel, **params, ) msg1 = "Signal delay does not match function delay" assert np.allclose(d1, d3, rtol=1e-10), msg1 msg2 = "epoch-TOA delay does not match full TOA delay" assert np.allclose(d1, d2, rtol=1e-10), msg2
def Dropout_PhysicalEphemerisSignal( frame_drift_rate=parameter.Uniform(-1e-9, 1e-9)('frame_drift_rate'), d_jupiter_mass=parameter.Normal(0, 1.54976690e-11)('d_jupiter_mass'), d_saturn_mass=parameter.Normal(0, 8.17306184e-12)('d_saturn_mass'), d_uranus_mass=parameter.Normal(0, 5.71923361e-11)('d_uranus_mass'), d_neptune_mass=parameter.Normal(0, 7.96103855e-11)('d_neptune_mass'), jup_orb_elements=parameter.Uniform(-0.05, 0.05, size=6)('jup_orb_elements'), sat_orb_elements=parameter.Uniform(-0.5, 0.5, size=6)('sat_orb_elements'), inc_jupiter_orb=True, inc_saturn_orb=False, use_epoch_toas=True, k_drop=parameter.Uniform(0.0, 1.0), k_threshold=0.5, name=''): """ Class factory for dropout physical ephemeris model signal.""" # turn off saturn orbital element parameters if not including in signal if not inc_saturn_orb: sat_orb_elements = np.zeros(6) # define waveform jup_mjd, jup_orbelxyz, sat_mjd, sat_orbelxyz = ( utils.get_planet_orbital_elements()) wf = dropout_physical_ephem_delay(frame_drift_rate=frame_drift_rate, d_jupiter_mass=d_jupiter_mass, d_saturn_mass=d_saturn_mass, d_uranus_mass=d_uranus_mass, d_neptune_mass=d_neptune_mass, jup_orb_elements=jup_orb_elements, sat_orb_elements=sat_orb_elements, inc_jupiter_orb=inc_jupiter_orb, jup_orbelxyz=jup_orbelxyz, jup_mjd=jup_mjd, inc_saturn_orb=inc_saturn_orb, sat_orbelxyz=sat_orbelxyz, sat_mjd=sat_mjd, k_drop=k_drop, k_threshold=k_threshold) BaseClass = deterministic_signals.Deterministic(wf, name=name) class Dropout_PhysicalEphemerisSignal(BaseClass): signal_name = 'phys_ephem' signal_id = 'phys_ephem_' + name if name else 'phys_ephem' def __init__(self, psr): # not available for PINT yet if isinstance(psr, enterprise.pulsar.PintPulsar): msg = 'Physical Ephemeris model is not compatible with PINT ' msg += 'at this time.' raise NotImplementedError(msg) super(Dropout_PhysicalEphemerisSignal, self).__init__(psr) if use_epoch_toas: # get quantization matrix and calculate daily average TOAs U, _ = utils.create_quantization_matrix(psr.toas, nmin=1) self.uinds = utils.quant2ind(U) avetoas = np.array([psr.toas[sc].mean() for sc in self.uinds]) self._wf[''].add_kwarg(toas=avetoas) # interpolate ssb planet position vectors to avetoas planetssb = np.zeros((len(avetoas), 9, 3)) for jj in range(9): planetssb[:, jj, :] = np.array([ np.interp(avetoas, psr.toas, psr.planetssb[:, jj, aa]) for aa in range(3) ]).T self._wf[''].add_kwarg(planetssb=planetssb) # Inteprolating the pulsar position vectors onto epoch TOAs pos_t = np.array([ np.interp(avetoas, psr.toas, psr.pos_t[:, aa]) for aa in range(3) ]).T self._wf[''].add_kwarg(pos_t=pos_t) # initialize delay self._delay = np.zeros(len(psr.toas)) @signal_base.cache_call('delay_params') def get_delay(self, params): delay = self._wf[''](params=params) if use_epoch_toas: for slc, val in zip(self.uinds, delay): self._delay[slc] = val return self._delay else: return delay return Dropout_PhysicalEphemerisSignal
def test_physical_ephem_model(self): """Test physical ephemeris model""" if isinstance(self.psr, enterprise.pulsar.Tempo2Pulsar): # define signals with and without epoch TOAs eph1 = deterministic_signals.PhysicalEphemerisSignal( sat_orb_elements=True, model="orbel") eph2 = deterministic_signals.PhysicalEphemerisSignal( sat_orb_elements=True, use_epoch_toas=False, model="orbel") # initialize signals e1, e2 = eph1(self.psr), eph2(self.psr) # set parameters params = { "d_jupiter_mass": -8.561198198000628e-12, "d_neptune_mass": 1.0251757860647059e-11, "d_saturn_mass": 6.22114376130324e-12, "d_uranus_mass": -2.1157536169469958e-10, "frame_drift_rate": 2.874659280396648e-10, "jup_orb_elements": np.array([ 0.04140015, -0.03422412, 0.01165894, -0.03525219, -0.00406852, 0.0421522 ]), "sat_orb_elements": np.array([ -0.39701798, -0.13322608, -0.05025925, 0.36331171, -0.17080321, 0.25093799 ]), } # test against waveform and compare non-epoch and epoch TOA results d1 = e1.get_delay(params=params) d2 = e2.get_delay(params=params) (jup_mjd, jup_orbel, sat_orbel) = utils.get_planet_orbital_elements("orbel") d3 = utils.physical_ephem_delay( self.psr.toas, self.psr.planetssb, self.psr.pos_t, times=jup_mjd, jup_orbit=jup_orbel, sat_orbit=sat_orbel, **params, ) msg1 = "Signal delay does not match function delay" assert np.allclose(d1, d3, rtol=1e-10), msg1 msg2 = "epoch-TOA delay does not match full TOA delay" assert np.allclose(d1, d2, rtol=1e-10), msg2 # test against pre-computed wafeform eph_wf = np.load(datadir + "/phys_ephem_1855_test.npy") msg = "Ephemeris delay does not match pre-computed values" assert np.allclose(d1, eph_wf, rtol=1e-10), msg # test PINT exception raising elif isinstance(self.psr, enterprise.pulsar.PintPulsar): with self.assertRaises(NotImplementedError) as context: eph1 = deterministic_signals.PhysicalEphemerisSignal( sat_orb_elements=True) e1 = eph1(self.psr) msg = "Physical Ephemeris model is not compatible with PINT " msg += "at this time." self.assertEqual(msg, str(context.exception))
def test_physical_ephem_model(self): """Tests physical ephemeris model (which is implemented as a deterministic signal) four ways: - computed directly with :func:`enterprise.signals.utils.physical_ephem_delay`; - computed with :meth:`enterprise.signals.deterministic_signals.PhysicalEphemerisSignal.get_delay` with `use_epoch_toas=True` (the default), which reduces computation by evaluating ephemeris corrections once per measurement epoch, and then interpolating to the full `toas` vector; - computed with :meth:`enterprise.signals.deterministic_signals.PhysicalEphemerisSignal.get_delay`, setting `use_epoch_toas=False`; - loaded from a golden copy. """ if isinstance(self.psr, enterprise.pulsar.Tempo2Pulsar): # define signals with and without epoch TOAs eph1 = deterministic_signals.PhysicalEphemerisSignal( sat_orb_elements=True, model="orbel") eph2 = deterministic_signals.PhysicalEphemerisSignal( sat_orb_elements=True, use_epoch_toas=False, model="orbel") # initialize signals e1, e2 = eph1(self.psr), eph2(self.psr) # set parameters params = { "d_jupiter_mass": -8.561198198000628e-12, "d_neptune_mass": 1.0251757860647059e-11, "d_saturn_mass": 6.22114376130324e-12, "d_uranus_mass": -2.1157536169469958e-10, "frame_drift_rate": 2.874659280396648e-10, "jup_orb_elements": np.array([ 0.04140015, -0.03422412, 0.01165894, -0.03525219, -0.00406852, 0.0421522 ]), "sat_orb_elements": np.array([ -0.39701798, -0.13322608, -0.05025925, 0.36331171, -0.17080321, 0.25093799 ]), } # test against waveform and compare non-epoch and epoch TOA results d1 = e1.get_delay(params=params) d2 = e2.get_delay(params=params) (jup_mjd, jup_orbel, sat_orbel) = utils.get_planet_orbital_elements("orbel") d3 = utils.physical_ephem_delay( self.psr.toas, self.psr.planetssb, self.psr.pos_t, times=jup_mjd, jup_orbit=jup_orbel, sat_orbit=sat_orbel, **params, ) msg1 = "Signal delay does not match function delay" assert np.allclose(d1, d3, rtol=1e-10), msg1 msg2 = "epoch-TOA delay does not match full TOA delay" assert np.allclose(d1, d2, rtol=1e-10), msg2 # test against pre-computed wafeform eph_wf = np.load(datadir + "/phys_ephem_1855_test.npy") msg = "Ephemeris delay does not match pre-computed values" assert np.allclose(d1, eph_wf, rtol=1e-10), msg
def PhysicalEphemerisSignal(frame_drift_rate=parameter.Uniform(-1e-9, 1e-9) ('frame_drift_rate'), d_mercury_mass=parameter.Normal( 0, 1.66 - 10)('d_mercury_mass'), d_venus_mass=parameter.Normal( 0, 2.45e-9)('d_venus_mass'), d_mars_mass=parameter.Normal( 0, 3.23e-10)('d_mars_mass'), d_jupiter_mass=parameter.Normal( 0, 1.54976690e-11)('d_jupiter_mass'), d_saturn_mass=parameter.Normal( 0, 8.17306184e-12)('d_saturn_mass'), d_uranus_mass=parameter.Normal( 0, 5.71923361e-11)('d_uranus_mass'), d_neptune_mass=parameter.Normal( 0, 7.96103855e-11)('d_neptune_mass'), jup_orb_elements=parameter.Uniform( -0.05, 0.05, size=6)('jup_orb_elements'), sat_orb_elements=parameter.Uniform( -0.5, 0.5, size=6)('sat_orb_elements'), model="setIII", use_epoch_toas=True, name=""): # noqa: E125,E501 """ Class factory for physical ephemeris model signal. This function implements a physically motivated ephemeris delay model. It is parameterized by an overall ecliptic-z frame drift rate, by the masses of gas giants, by the six orbital elements of Jupiter, and by the six orbital elements of Saturn. All these contributions can be disabled individually (Saturn orbit corrections are disabled by default). .. note:: This signal is only compatible with a tempo2 Pulsar object. The user can implement their own priors (e.g., by setting frame_drift_rate = parameter.Uniform(-1e-10,1e-10)('frame_drift_rate') but we have set reasonable defaults (see below). :param frame_drift_rate: ecliptic z-drift rate in units of rad/year referred to offset 1/1/2010. Default prior is Uniform(-1e-9, 1e-9). :param d_jupiter_mass: Mass deviation of Jupiter in solar masses. Default prior taken from IAU mass measurement uncertainty - Normal(0, 1.54976690e-11) :param d_saturn_mass: Mass deviation of Saturn in solar masses. Default prior taken from IAU mass measurement uncertainty - Normal(0, 8.17306184e-12) :param d_uranus_mass: Mass deviation of Uranus in solar masses. Default prior taken from IAU mass measurement uncertainty - Normal(0, 5.71923361e-11) :param d_neptune_mass: Mass deviation of Neptune in solar masses. Default prior taken from IAU mass measurement uncertainty - Normal(0, 7.96103855e-11) :param jup_orb_elements: Jupiter orbital-element perturbation coefficients. Default prior is Uniform(-0.05, 0.05) for each element, appropriate for standard SVD basis. :param sat_orb_elements: Saturn orbital-element perturbations coefficient. Default prior is Uniform(-0.5, 0.5) for each element, appropriate for standard SVD basis. :param model: Sets the vector basis used by Jupiter and Saturn orbital-element perturbations. Currently can be set to 'orbel', 'orbel-v2', 'setIII'. Default: 'setIII' :param use_epoch_toas: Use interpolation from epoch to full TOAs. This option reduces computational cost for large multi-channel TOA data sets. Default: True """ times, jup_orbit, sat_orbit = utils.get_planet_orbital_elements(model) wf = utils.physical_ephem_delay( frame_drift_rate=frame_drift_rate, d_mercury_mass=d_mercury_mass, d_venus_mass=d_venus_mass, d_mars_mass=d_mars_mass, d_jupiter_mass=d_jupiter_mass, d_saturn_mass=d_saturn_mass, d_uranus_mass=d_uranus_mass, d_neptune_mass=d_neptune_mass, jup_orb_elements=jup_orb_elements, sat_orb_elements=sat_orb_elements, times=times, jup_orbit=jup_orbit, sat_orbit=sat_orbit, ) BaseClass = Deterministic(wf, name=name) class PhysicalEphemerisSignal(BaseClass): signal_name = "phys_ephem" signal_id = "phys_ephem_" + name if name else "phys_ephem" def __init__(self, psr): # not available for PINT yet if isinstance(psr, pulsar.PintPulsar): msg = "Physical Ephemeris model is not compatible with PINT " msg += "at this time." raise NotImplementedError(msg) super(PhysicalEphemerisSignal, self).__init__(psr) if use_epoch_toas: # get quantization matrix and calculate daily average TOAs U, _ = utils.create_quantization_matrix(psr.toas, nmin=1) self._uinds = utils.quant2ind(U) avetoas = np.array([psr.toas[sc].mean() for sc in self._uinds]) self._avetoas = avetoas # interpolate ssb planet position vectors to avetoas planetssb = np.zeros((len(avetoas), 9, 3)) for jj in range(9): planetssb[:, jj, :] = np.array([ np.interp(avetoas, psr.toas, psr.planetssb[:, jj, aa]) for aa in range(3) ]).T self._planetssb = planetssb # Interpolating the pulsar position vectors onto epoch TOAs pos_t = np.array([ np.interp(avetoas, psr.toas, psr.pos_t[:, aa]) for aa in range(3) ]).T self._pos_t = pos_t # initialize delay self._delay = np.zeros(len(psr.toas)) # this defaults to all parameters @signal_base.cache_call("delay_params") def get_delay(self, params): if use_epoch_toas: delay = self._wf[""](toas=self._avetoas, planetssb=self._planetssb, pos_t=self._pos_t, params=params) for slc, val in zip(self._uinds, delay): self._delay[slc] = val return self._delay else: delay = self._wf[""](params=params) return delay return PhysicalEphemerisSignal
def PhysicalEphemerisSignal( frame_drift_rate=parameter.Uniform(-1e-9, 1e-9)('frame_drift_rate'), d_jupiter_mass=parameter.Normal(0, 1.54976690e-11)('d_jupiter_mass'), d_saturn_mass=parameter.Normal(0, 8.17306184e-12)('d_saturn_mass'), d_uranus_mass=parameter.Normal(0, 5.71923361e-11)('d_uranus_mass'), d_neptune_mass=parameter.Normal(0, 7.96103855e-11)('d_neptune_mass'), jup_orb_elements=parameter.Uniform(-0.05, 0.05, size=6)('jup_orb_elements'), sat_orb_elements=parameter.Uniform(-0.5, 0.5, size=6)('sat_orb_elements'), inc_jupiter_orb=True, inc_saturn_orb=False, use_epoch_toas=True, name=''): # noqa: E125,E501 """ Class factory for physical ephemeris model signal. This function implements a physically motivated ephemeris delay model. It is parameterized by an overall frame drift rate, masses of gas giants, 6 orbital elements of Jupiter (uses a PCA basis), and 6 orbital elements of Saturn (uses PCA basis). .. note:: This signal is only compatible with a tempo2 Pulsar object. The user can implement their own priors but we have set reasonable defaults. :param frame_drift_rate: ecliptic z-drift rate in units of rad/year referred to offset 1/1/2010. Default prior is Uniform(-1e-9, 1e-9). :param d_jupiter_mass: Mass deviation of jupiter in solar masses. Default prior taken from IAU mass measurement uncertainty - Normal(0, 1.54976690e-11) :param d_saturn_mass: Mass deviation of saturn in solar masses. Default prior taken from IAU mass measurement uncertainty - Normal(0, 8.17306184e-12) :param d_uranus_mass: Mass deviation of uranus in solar masses. Default prior taken from IAU mass measurement uncertainty - Normal(0, 5.71923361e-11) :param d_neptune_mass: Mass deviation of neptune in solar masses. Default prior taken from IAU mass measurement uncertainty - Normal(0, 7.96103855e-11) :param jup_orb_elements: Amplitudes of PCA basis of jupiter orbital elements including (1) semi-major axis (2) eccentricity (3) inclination (4) longitude of the ascending node (5) longitude of perihelion (6) mean longitude Default prior is Uniform(-0.05, 0.05) for each element. :param sat_orb_elements: Amplitudes of PCA basis of saturn orbital elements including (1) semi-major axis (2) eccentricity (3) inclination (4) longitude of the ascending node (5) longitude of perihelion (6) mean longitude Default prior is Uniform(-0.5, 0.5) for each element. :param inc_jupiter_orb: Boolean indicating whether or not to include jupiter's orbital elements as free parameters in model. Default: True :param inc_saturn_orb: Boolean indicating whether or not to include saturn's orbital elements as free parameters in model. Default: False :param use_epoch_toas: Use interpolation from epoch to full TOAs. This option reduces computational cost for large multi-channel TOA data sets. Default: True """ # turn off saturn orbital element parameters if not including in signal if not inc_saturn_orb: sat_orb_elements = np.zeros(6) # define waveform jup_mjd, jup_orbelxyz, sat_mjd, sat_orbelxyz = ( utils.get_planet_orbital_elements()) wf = utils.physical_ephem_delay(frame_drift_rate=frame_drift_rate, d_jupiter_mass=d_jupiter_mass, d_saturn_mass=d_saturn_mass, d_uranus_mass=d_uranus_mass, d_neptune_mass=d_neptune_mass, jup_orb_elements=jup_orb_elements, sat_orb_elements=sat_orb_elements, inc_jupiter_orb=inc_jupiter_orb, jup_orbelxyz=jup_orbelxyz, jup_mjd=jup_mjd, inc_saturn_orb=inc_saturn_orb, sat_orbelxyz=sat_orbelxyz, sat_mjd=sat_mjd) BaseClass = Deterministic(wf, name=name) class PhysicalEphemerisSignal(BaseClass): signal_name = 'phys_ephem' signal_id = 'phys_ephem_' + name if name else 'phys_ephem' def __init__(self, psr): # not available for PINT yet if isinstance(psr, pulsar.PintPulsar): msg = 'Physical Ephemeris model is not compatible with PINT ' msg += 'at this time.' raise NotImplementedError(msg) super(PhysicalEphemerisSignal, self).__init__(psr) if use_epoch_toas: # get quantization matrix and calculate daily average TOAs U, _ = utils.create_quantization_matrix(psr.toas, nmin=1) self._uinds = utils.quant2ind(U) avetoas = np.array([psr.toas[sc].mean() for sc in self._uinds]) self._avetoas = avetoas # interpolate ssb planet position vectors to avetoas planetssb = np.zeros((len(avetoas), 9, 3)) for jj in range(9): planetssb[:, jj, :] = np.array([ np.interp(avetoas, psr.toas, psr.planetssb[:, jj, aa]) for aa in range(3) ]).T self._planetssb = planetssb # Interpolating the pulsar position vectors onto epoch TOAs pos_t = np.array([ np.interp(avetoas, psr.toas, psr.pos_t[:, aa]) for aa in range(3) ]).T self._pos_t = pos_t # initialize delay self._delay = np.zeros(len(psr.toas)) @signal_base.cache_call('delay_params') def get_delay(self, params): if use_epoch_toas: delay = self._wf[''](toas=self._avetoas, planetssb=self._planetssb, pos_t=self._pos_t, params=params) for slc, val in zip(self._uinds, delay): self._delay[slc] = val return self._delay else: delay = self._wf[''](params=params) return delay return PhysicalEphemerisSignal
def PhysicalEphemerisSignal( frame_drift_rate=parameter.Uniform(-1e-9, 1e-9)('frame_drift_rate'), d_jupiter_mass=parameter.Normal(0, 1.54976690e-11)('d_jupiter_mass'), d_saturn_mass=parameter.Normal(0, 8.17306184e-12)('d_saturn_mass'), d_uranus_mass=parameter.Normal(0, 5.71923361e-11)('d_uranus_mass'), d_neptune_mass=parameter.Normal(0, 7.96103855e-11)('d_neptune_mass'), jup_orb_elements=parameter.Uniform(-0.05,0.05,size=6)('jup_orb_elements'), sat_orb_elements=parameter.Uniform(-0.5,0.5,size=6)('sat_orb_elements'), inc_jupiter_orb=True, inc_saturn_orb=False, use_epoch_toas=True, name=''): # noqa: E125,E501 """ Class factory for physical ephemeris model signal. This function implements a physically motivated ephemeris delay model. It is parameterized by an overall frame drift rate, masses of gas giants, 6 orbital elements of Jupiter (uses a PCA basis), and 6 orbital elements of Saturn (uses PCA basis). .. note:: This signal is only compatible with a tempo2 Pulsar object. The user can implement their own priors but we have set reasonable defaults. :param frame_drift_rate: ecliptic z-drift rate in units of rad/year referred to offset 1/1/2010. Default prior is Uniform(-1e-9, 1e-9). :param d_jupiter_mass: Mass deviation of jupiter in solar masses. Default prior taken from IAU mass measurement uncertainty - Normal(0, 1.54976690e-11) :param d_saturn_mass: Mass deviation of saturn in solar masses. Default prior taken from IAU mass measurement uncertainty - Normal(0, 8.17306184e-12) :param d_uranus_mass: Mass deviation of uranus in solar masses. Default prior taken from IAU mass measurement uncertainty - Normal(0, 5.71923361e-11) :param d_neptune_mass: Mass deviation of neptune in solar masses. Default prior taken from IAU mass measurement uncertainty - Normal(0, 7.96103855e-11) :param jup_orb_elements: Amplitudes of PCA basis of jupiter orbital elements including (1) semi-major axis (2) eccentricity (3) inclination (4) longitude of the ascending node (5) longitude of perihelion (6) mean longitude Default prior is Uniform(-0.05, 0.05) for each element. :param sat_orb_elements: Amplitudes of PCA basis of saturn orbital elements including (1) semi-major axis (2) eccentricity (3) inclination (4) longitude of the ascending node (5) longitude of perihelion (6) mean longitude Default prior is Uniform(-0.5, 0.5) for each element. :param inc_jupiter_orb: Boolean indicating whether or not to include jupiter's orbital elements as free parameters in model. Default: True :param inc_saturn_orb: Boolean indicating whether or not to include saturn's orbital elements as free parameters in model. Default: False :param use_epoch_toas: Use interprolation from epoch to full TOAs. This option reduces computational cost for large multi-channel TOA data sets. Default: True """ # turn off saturn orbital element parameters if not including in signal if not inc_saturn_orb: sat_orb_elements = np.zeros(6) # define waveform jup_mjd, jup_orbelxyz, sat_mjd, sat_orbelxyz = ( utils.get_planet_orbital_elements()) wf = utils.physical_ephem_delay(frame_drift_rate=frame_drift_rate, d_jupiter_mass=d_jupiter_mass, d_saturn_mass=d_saturn_mass, d_uranus_mass=d_uranus_mass, d_neptune_mass=d_neptune_mass, jup_orb_elements=jup_orb_elements, sat_orb_elements=sat_orb_elements, inc_jupiter_orb=inc_jupiter_orb, jup_orbelxyz=jup_orbelxyz, jup_mjd=jup_mjd, inc_saturn_orb=inc_saturn_orb, sat_orbelxyz=sat_orbelxyz, sat_mjd=sat_mjd) BaseClass = Deterministic(wf, name=name) class PhysicalEphemerisSignal(BaseClass): signal_name = 'phys_ephem' signal_id = 'phys_ephem_' + name if name else 'phys_ephem' def __init__(self, psr): # not available for PINT yet if isinstance(psr, enterprise.pulsar.PintPulsar): msg = 'Physical Ephemeris model is not compatible with PINT ' msg += 'at this time.' raise NotImplementedError(msg) super(PhysicalEphemerisSignal, self).__init__(psr) if use_epoch_toas: # get quantization matrix and calculate daily average TOAs U, _ = utils.create_quantization_matrix(psr.toas, nmin=1) self.uinds = utils.quant2ind(U) avetoas = np.array([psr.toas[sc].mean() for sc in self.uinds]) self._wf[''].add_kwarg(toas=avetoas) # interpolate ssb planet position vectors to avetoas planetssb = np.zeros((len(avetoas), 9, 3)) for jj in range(9): planetssb[:, jj, :] = np.array([ np.interp(avetoas, psr.toas, psr.planetssb[:,jj,aa]) for aa in range(3)]).T self._wf[''].add_kwarg(planetssb=planetssb) # Inteprolating the pulsar position vectors onto epoch TOAs pos_t = np.array([np.interp(avetoas, psr.toas, psr.pos_t[:,aa]) for aa in range(3)]).T self._wf[''].add_kwarg(pos_t=pos_t) # initialize delay self._delay = np.zeros(len(psr.toas)) @base.cache_call('delay_params') def get_delay(self, params): delay = self._wf[''](params=params) if use_epoch_toas: for slc, val in zip(self.uinds, delay): self._delay[slc] = val return self._delay else: return delay return PhysicalEphemerisSignal