def __init__(self, par, det, times=None, earth_ephem=None, sun_ephem=None, time_corr=None, ephem='DE405', units='TCB', t0=None, dt=None): """ A class to simulate strain data for a continuous gravitational-wave signal after the data has been heterodyned, i.e., after multiplying the data by a complex phase vector. This uses the Equations 7 and 8 from @cite Pitkin2017 accessed via the XLALHeterodynedPulsarGetModel() function. @param par: a TEMPO-style text file, or a PulsarParametersPy() structure, containing the parameters for the source, in particular the phase parameters at which the data is "heterodyned". @param det: the name of a detector. @param times: an array of GPS times at which to calculate the heterodyned strain. @param t0: a time epoch in GPS seconds at which to calculate the detector response function. If not given and @b times is set, then the first value of @b times will be used. @param dt: the time steps (in seconds) in the data over which to average the detector response. If not given and @b times is set, the the time difference between the first two values in @b times will be used. @param earth_ephem: a file containing the Earth ephemeris information. If not set then a default file will be used. @param sun_ephem: a file containing the Earth ephemeris information. If not set then a default file will be used. @param time_corr: a file containing information on the time system corrections for, e.g., the TCB or TDB system. If not set then a default file will be used. @param ephem: The solar system ephemeris system to use for the Earth and Sun ephemeris, i.e., @c 'DE200', @c 'DE405', @c 'DE421', or @c 'DE430'. By default the @c 'EPHEM' value from the supplied @b par will be used, but if not found, and if this value is not set, it will default to @c 'DE405'. @param units: The time system used, i.e., @c 'TDB' or @c 'TCB'. By default the @c 'UNITS' value from the @b par will be used, but if not found, and if this value is not set, it will (like TEMPO2) default to @c 'TCB'. """ self.__hetpar = self._read_par(par) self.detector = det self.times = times # set default ephemeris strings self.__earthstr = "earth00-40-{}.dat.gz" self.__sunstr = "sun00-40-{}.dat.gz" self.__timecorrstr = "{}_2000-2040.dat.gz" # mapping between time units and time correction file prefix self.__units_map = {"TCB": "te405", "TDB": "tdb"} self.ephem = ephem self.units = units # initialise the solar system ephemeris files self.__edat, self.__tdat = self._initialise_ephemeris( earth_ephem, sun_ephem, time_corr) # set the "heterodyne" SSB time delay if self.times is not None: self.__hetSSBdelay = lalpulsar.HeterodynedPulsarGetSSBDelay( self.hetpar.PulsarParameters(), self.gpstimes, self.detector, self.__edat, self.__tdat, self.__units_type) else: self.__hetSSBdelay = None # set the "heterodyne" BSB time delay if self.times is not None and self.hetpar["BINARY"] is not None: self.__hetBSBdelay = lalpulsar.HeterodynedPulsarGetBSBDelay( self.hetpar.PulsarParameters(), self.gpstimes, self.__hetSSBdelay, self.__edat) else: self.__hetBSBdelay = None # set the "heterodyne" glitch phase if self.times is not None and self.hetpar["GLEP"] is not None: self.__hetglitchphase = lalpulsar.HeterodynedPulsarGetGlitchPhase( self.hetpar.PulsarParameters(), self.gpstimes, self.__hetSSBdelay, self.__hetBSBdelay) else: self.__hetglitchphase = None # set the "heterodyne" FITWAVES phase if self.times is not None and self.hetpar[ "WAVESIN"] is not None and self.hetpar["WAVECOS"] is not None: self.__hetfitwavesphase = lalpulsar.HeterodynedPulsarGetFITWAVESPhase( self.hetpar.PulsarParameters(), self.gpstimes, self.__hetSSBdelay, self.hetpar["F0"]) else: self.__hetfitwavesphase = None # set the response function if self.times is None and t0 is None: raise ValueError("Must supply either 'times' or 't0' to calculate " "the response function") else: self.__t0 = t0 if t0 is not None else self.times[0] if dt is None and self.times is None: raise ValueError("Must supply either 'times' or 'dt' to calculate " "the response function") else: if self.times is not None and dt is None: if len(self.times) == 1: raise ValueError("Must supply a 'dt' value") else: self.__dt = self.times[1] - self.times[0] else: self.__dt = dt ra = self.hetpar["RA"] if self.hetpar["RAJ"] is None else self.hetpar[ "RAJ"] dec = self.hetpar[ "DEC"] if self.hetpar["DECJ"] is None else self.hetpar["DECJ"] if ra is None or dec is None: raise ValueError("Right ascension and/or declination have not " "been set!") self.__resp = lalpulsar.DetResponseLookupTable(self.__t0, self.detector, ra, dec, 2880, self.__dt)
def test_four(): parhet = PulsarParametersPy() parhet['F'] = [123.4567, -9.876e-12] # set frequency parhet['RAJ'] = lal.TranslateHMStoRAD('01:23:34.6') # set right ascension parhet['DECJ'] = lal.TranslateDMStoRAD('-45:01:23.5') # set declination pepoch = lal.TranslateStringMJDTTtoGPS('58000') parhet['PEPOCH'] = pepoch.gpsSeconds + 1e-9 * pepoch.gpsNanoSeconds parhet['H0'] = 5.6e-26 parhet['COSIOTA'] = -0.2 parhet['PSI'] = 0.4 parhet['PHI0'] = 2.3 parhet['BINARY'] = 'BT' T0 = lal.TranslateStringMJDTTtoGPS('58121.3') parhet['T0'] = T0.gpsSeconds + 1e-9 * T0.gpsNanoSeconds parhet['OM'] = np.deg2rad(2.2) parhet['A1'] = 8.9 parhet['PB'] = 0.54 * 86400. parhet['ECC'] = 0.0001 parinj = PulsarParametersPy() parinj['F'] = [123.456789, -9.87654321e-12] # set frequency parinj['DELTAF'] = parinj['F'] - parhet['F'] # frequency difference parinj['RAJ'] = lal.TranslateHMStoRAD('01:23:34.5') # set right ascension parinj['DECJ'] = lal.TranslateDMStoRAD('-45:01:23.4') # set declination pepoch = lal.TranslateStringMJDTTtoGPS('58000') parinj['PEPOCH'] = pepoch.gpsSeconds + 1e-9 * pepoch.gpsNanoSeconds parinj['H0'] = 5.6e-26 parinj['COSIOTA'] = -0.2 parinj['PSI'] = 0.4 parinj['PHI0'] = 2.3 parinj['BINARY'] = 'BT' T0 = lal.TranslateStringMJDTTtoGPS('58121.3') parinj['T0'] = T0.gpsSeconds + 1e-9 * T0.gpsNanoSeconds parinj['OM'] = np.deg2rad(1.2) parinj['A1'] = 8.9 parinj['PB'] = 0.54 * 86400. parinj['ECC'] = 0.0001 freqfactor = 2. # set frequency factor det = 'H1' # the detector # convert into GPS times gpstimes = lalpulsar.CreateTimestampVector(len(t4output)) for i, time in enumerate(t4output[:, 0]): gpstimes.data[i] = lal.LIGOTimeGPS(time) detector = lalpulsar.GetSiteInfo(det) # set the response function look-up table dt = t4output[1, 0] - t4output[0, 0] # time step resp = lalpulsar.DetResponseLookupTable(t4output[0, 0], detector, parhet['RAJ'], parhet['DECJ'], 2880, dt) # get the heterodyned file SSB delay hetSSBdelay = lalpulsar.HeterodynedPulsarGetSSBDelay( parhet.PulsarParameters(), gpstimes, detector, edat, tdat, lalpulsar.TIMECORRECTION_TCB) # get the heterodyned file BSB delay hetBSBdelay = lalpulsar.HeterodynedPulsarGetBSBDelay( parhet.PulsarParameters(), gpstimes, hetSSBdelay, edat) fullsignal = lalpulsar.HeterodynedPulsarGetModel( parinj.PulsarParameters(), freqfactor, 1, # phase is varying between par files 0, # not using ROQ 0, # not using non-tensorial modes gpstimes, hetSSBdelay, 1, # the SSB delay should be updated compared to hetSSBdelay hetBSBdelay, 1, # the BSB delay should be updated compared to hetBSBdelay resp, edat, tdat, lalpulsar.TIMECORRECTION_TCB) # check output matches that from lalapps_pulsar_parameter_estimation_nested if np.any(np.abs(fullsignal.data.data.real - t4output[:, 1]) > 1e-33): return False elif np.any(np.abs(fullsignal.data.data.imag - t4output[:, 2]) > 1e-33): return False else: return True
def __init__( self, par, det, times=None, earth_ephem=None, sun_ephem=None, time_corr=None, ephem="DE405", units="TCB", usetempo2=False, t0=None, dt=None, ): """ A class to simulate strain data for a continuous gravitational-wave signal after the data has been heterodyned, i.e., after multiplying the data by a complex phase vector. This uses the Equations 7 and 8 from [1]_ accessed via the ``XLALHeterodynedPulsarGetModel()`` function. Parameters ---------- par: str, PulsarParameters A Tempo-style text file, or a :class:`~cwinpy.parfile.PulsarParameters` object, containing the parameters for the source, in particular the phase parameters at which the data is "heterodyned". det: str The name of a gravitational-wave detector. times: array_like An array of GPS times at which to calculate the heterodyned strain. t0: float A time epoch in GPS seconds at which to calculate the detector response function. If not given and ``times`` is set, then the first value of ``times`` will be used. dt: int, float The time steps (in seconds) in the data over which to average the detector response. If not given and ``times`` is set, then the time difference between the first two values in ``times`` will be used. earth_ephem: str A file containing the LALSuite-style Earth ephemeris information. If not set then a default file will be used. sun_ephem: str A file containing the LALSuite-style Sun ephemeris information. If not set then a default file will be used. time_corr: str A file containing the LALSuite-style information on the time system corrections for, e.g., the TCB or TDB system. If not set then a default file will be used. ephem: str The solar system ephemeris system to use for the Earth and Sun ephemeris, i.e., ``"DE200"``, ``"DE405"``, ``"DE421"``, or ``"DE430"``. By default the ``EPHEM`` value from the supplied ``par`` will be used, but if not found, and if this value is not set, it will default to ``"DE405"``. units: str The time system used, i.e., ``"TDB"`` or ``"TCB"``. By default the ``UNITS`` value from the ``par`` will be used, but if not found, and if this value is not set, it will (like TEMPO2) default to ``"TCB"``. usetempo2: bool Set to True to use TEMPO2, via libstempo, for calculating the phase of the signal. To use libstempo must be installed. If using TEMPO2 the Earth, Sun and time ephemerides, and the ``ephem`` and ``units`` arguments are not required. Information on the correct ephemeris will all be calculated internally by TEMPO2 using the information from the pulsar parameter file. """ self.usetempo2 = check_for_tempo2() if usetempo2 else False if usetempo2 and not self.usetempo2: raise ImportError( "TEMPO2 is not available, so the usetempo2 option cannot be used" ) self.__hetpar, self.__parfile = self._read_par(par) self.detector = det self.times = times if not self.usetempo2: self.ephem = ephem self.units = units # initialise the solar system ephemeris files self.__edat, self.__tdat = initialise_ephemeris( ephem=self.ephem, units=self.units, earthfile=earth_ephem, sunfile=sun_ephem, timefile=time_corr, ) # set the "heterodyne" SSB time delay if self.times is not None: self.__hetSSBdelay = lalpulsar.HeterodynedPulsarGetSSBDelay( self.hetpar.PulsarParameters(), self.gpstimes, self.detector, self.__edat, self.__tdat, self.__units_type, ) else: self.__hetSSBdelay = None # set the "heterodyne" BSB time delay if self.times is not None and self.hetpar["BINARY"] is not None: self.__hetBSBdelay = lalpulsar.HeterodynedPulsarGetBSBDelay( self.hetpar.PulsarParameters(), self.gpstimes, self.__hetSSBdelay, self.__edat, ) else: self.__hetBSBdelay = None # set the "heterodyne" glitch phase if self.times is not None and self.hetpar["GLEP"] is not None: self.__hetglitchphase = lalpulsar.HeterodynedPulsarGetGlitchPhase( self.hetpar.PulsarParameters(), self.gpstimes, self.__hetSSBdelay, self.__hetBSBdelay, ) else: self.__hetglitchphase = None # set the "heterodyne" FITWAVES phase if ( self.times is not None and self.hetpar["WAVESIN"] is not None and self.hetpar["WAVECOS"] is not None ): self.__hetfitwavesphase = lalpulsar.HeterodynedPulsarGetFITWAVESPhase( self.hetpar.PulsarParameters(), self.gpstimes, self.__hetSSBdelay, self.hetpar["F0"], ) else: self.__hetfitwavesphase = None # set the response function if self.times is None and t0 is None: raise ValueError( "Must supply either 'times' or 't0' to calculate " "the response function" ) else: self.__t0 = float(t0) if t0 is not None else float(self.times[0]) if dt is None and self.times is None: raise ValueError( "Must supply either 'times' or 'dt' to calculate " "the response function" ) else: if self.times is not None and dt is None: if len(self.times) == 1: raise ValueError("Must supply a 'dt' value") else: self.__dt = float(self.times[1] - self.times[0]) else: self.__dt = float(dt) ra = self.hetpar["RA"] if self.hetpar["RAJ"] is None else self.hetpar["RAJ"] dec = self.hetpar["DEC"] if self.hetpar["DECJ"] is None else self.hetpar["DECJ"] if ra is None or dec is None: raise ValueError("Right ascension and/or declination have not " "been set!") self.__resp = lalpulsar.DetResponseLookupTable( self.__t0, self.detector, ra, dec, 2880, self.__dt )