def test_six(): 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 parinj = PulsarParametersPy() parinj['F'] = [123.456789, -9.87654321e-12] # set frequency 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['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.0 parinj['ECC'] = 0.0001 parinj['GLF0'] = [5.4e-6, 3.4e-7] parinj['GLF1'] = [-3.2e-13, -1.2e-14] parinj['GLF0D'] = [1.2e-5, -0.4e-6] parinj['GLTD'] = [0.31 * 86400, 0.45 * 86400] parinj['GLPH'] = [0.3, 0.7] glph1 = lal.TranslateStringMJDTTtoGPS('55818.08161090822') glph2 = lal.TranslateStringMJDTTtoGPS('55818.08276831563') parinj['GLEP'] = [ glph1.gpsSeconds + 1e-9 * glph1.gpsNanoSeconds, glph2.gpsSeconds + 1e-9 * glph2.gpsNanoSeconds ] freqfactor = 2. # set frequency factor det = 'H1' # the detector # convert into GPS times gpstimes = lalpulsar.CreateTimestampVector(len(t6output)) for i, time in enumerate(np.linspace(1000000000.0, 1000000540.0, 10)): gpstimes.data[i] = lal.LIGOTimeGPS(time) detector = lalpulsar.GetSiteInfo(det) # replicate coarse heterodyne in which no SSB/BSB delay is applied hetSSBdelay = lal.CreateREAL8Vector(len(t6output)) hetBSBdelay = lal.CreateREAL8Vector(len(t6output)) for i in range(len(t6output)): hetSSBdelay.data[i] = 0.0 hetBSBdelay.data[i] = 0.0 # get the heterodyne glitch phase (which should be zero) glphase = lalpulsar.HeterodynedPulsarGetGlitchPhase( parhet.PulsarParameters(), gpstimes, hetSSBdelay, hetBSBdelay) fullphase = lalpulsar.HeterodynedPulsarPhaseDifference( parinj.PulsarParameters(), parhet.PulsarParameters(), gpstimes, freqfactor, hetSSBdelay, 1, # the SSB delay should be updated compared to hetSSBdelay hetBSBdelay, 1, # the BSB delay should be updated compared to hetBSBdelay glphase, 1, # the glitch phase should be updated compared to glphase None, 0, detector, edat, tdat, lalpulsar.TIMECORRECTION_TCB) # check output matches that from lalapps_heterodyne_pulsar assert_allclose(2.0 * np.pi * np.fmod(fullphase.data, 1.), t6output, rtol=1e-4)
def test_seven(): parhet = PulsarParametersPy() parhet['F'] = [153.4567, -2.876e-11] # set frequency parhet['RAJ'] = lal.TranslateHMStoRAD('04:23:34.6') # set right ascension parhet['DECJ'] = lal.TranslateDMStoRAD('-05:01:23.5') # set declination pepoch = lal.TranslateStringMJDTTtoGPS('55810') parhet['PEPOCH'] = pepoch.gpsSeconds + 1e-9 * pepoch.gpsNanoSeconds parinj = PulsarParametersPy() parinj['F'] = [153.456789, -2.87654321e-11] # set frequency parinj['RAJ'] = lal.TranslateHMStoRAD('04:23:34.5') # set right ascension parinj['DECJ'] = lal.TranslateDMStoRAD('-05:01:23.4') # set declination pepoch = lal.TranslateStringMJDTTtoGPS('55810') parinj['PEPOCH'] = pepoch.gpsSeconds + 1e-9 * pepoch.gpsNanoSeconds parinj['BINARY'] = 'BT' T0 = lal.TranslateStringMJDTTtoGPS('58121.3') parinj['T0'] = T0.gpsSeconds + 1e-9 * T0.gpsNanoSeconds parinj['OM'] = np.deg2rad(7.2) parinj['A1'] = 14.9 parinj['PB'] = 1.03 * 86400.0 parinj['ECC'] = 0.0002 parinj['GLF0'] = [7.4e-6, 3.4e-7] parinj['GLF1'] = [-3.2e-12, -1.2e-14] parinj['GLF0D'] = [1.2e-5, -0.4e-6] parinj['GLTD'] = [0.41 * 86400, 1.45 * 86400] parinj['GLPH'] = [0.3, 0.91] glep1 = lal.TranslateStringMJDTTtoGPS('55818.08161090822') glep2 = lal.TranslateStringMJDTTtoGPS('55818.08276831563') parinj['GLEP'] = [ glep1.gpsSeconds + 1e-9 * glep1.gpsNanoSeconds, glep2.gpsSeconds + 1e-9 * glep2.gpsNanoSeconds ] waveep = lal.TranslateStringMJDTTtoGPS('55818.0') parinj['WAVEEPOCH'] = waveep.gpsSeconds + 1e-9 * waveep.gpsNanoSeconds parinj['WAVE_OM'] = 0.005 parinj['WAVESIN'] = [0.098, 0.078, -0.03] parinj['WAVECOS'] = [0.056, -0.071, -0.12] freqfactor = 2. # set frequency factor det = 'H1' # the detector # convert into GPS times gpstimes = lalpulsar.CreateTimestampVector(len(t7output)) for i, time in enumerate(np.linspace(1000000000.0, 1000000540.0, 10)): gpstimes.data[i] = lal.LIGOTimeGPS(time) detector = lalpulsar.GetSiteInfo(det) # replicate coarse heterodyne in which no SSB/BSB delay is applied hetSSBdelay = lal.CreateREAL8Vector(len(t6output)) hetBSBdelay = lal.CreateREAL8Vector(len(t6output)) for i in range(len(t6output)): hetSSBdelay.data[i] = 0.0 hetBSBdelay.data[i] = 0.0 # get the heterodyne glitch phase (which should be zero) glphase = lalpulsar.HeterodynedPulsarGetGlitchPhase( parhet.PulsarParameters(), gpstimes, hetSSBdelay, hetBSBdelay) assert_equal(glphase.data, np.zeros(len(t7output))) # get the FITWAVES phase (which should be zero) fwphase = lalpulsar.HeterodynedPulsarGetFITWAVESPhase( parhet.PulsarParameters(), gpstimes, hetSSBdelay, parhet["F0"]) assert_equal(fwphase.data, np.zeros(len(t7output))) fullphase = lalpulsar.HeterodynedPulsarPhaseDifference( parinj.PulsarParameters(), parhet.PulsarParameters(), gpstimes, freqfactor, hetSSBdelay, 1, # the SSB delay should be updated compared to hetSSBdelay hetBSBdelay, 1, # the BSB delay should be updated compared to hetBSBdelay glphase, 1, # the glitch phase should be updated compared to glphase fwphase, 1, # the FITWAVES phase should be updated compare to fwphase detector, edat, tdat, lalpulsar.TIMECORRECTION_TCB) # check output matches that from lalapps_heterodyne_pulsar assert_allclose(2.0 * np.pi * np.fmod(fullphase.data, 1.), t7output, rtol=1e-3)
def model( self, newpar=None, updateSSB=False, updateBSB=False, updateglphase=False, updatefitwaves=False, freqfactor=2.0, outputampcoeffs=False, roq=False, ): """ Compute the heterodyned strain model using ``XLALHeterodynedPulsarGetModel()``. Parameters ---------- newpar: str, PulsarParameters A text parameter file, or :class:`~cwinpy.parfile.PulsarParameters` object, containing a set of parameter at which to calculate the strain model. If this is ``None`` then the "heterodyne" parameters are used. updateSSB: bool Set to ``True`` to update the solar system barycentring time delays compared to those used in heterodyning, i.e., if the ``newpar`` contains updated positional parameters. updateBSB: bool Set to ``True`` to update the binary system barycentring time delays compared to those used in heterodying, i.e., if the ``newpar`` contains updated binary system parameters updateglphase: bool Set to ``True`` to update the pulsar glitch evolution compared to that used in heterodyning, i.e., if the ``newpar`` contains updated glitch parameters. updatefitwaves: bool Set to ``True`` to update the pulsar FITWAVES phase evolution (used to model strong red timing noise) compared to that used in heterodyning. freqfactor: int, float The factor by which the frequency evolution is multiplied for the source model. This defaults to 2 for emission from the :math:`l=m=2` quadrupole mode. outputampcoeffs: bool If ``False`` (default) then the full complex time series of the signal (calculated at the time steps used when initialising the object) will be output. If ``True`` only two complex amplitudes (six for non-GR sources) will be output for use when a pre-summed signal model is being used - this should only be used if phase parameters are not being updated. roq: bool A boolean value to set to ``True`` if requiring the output for a ROQ model (NOT YET IMPLEMENTED). Returns ------- strain: array_like A complex array containing the strain data """ if newpar is not None: parupdate, parfile = self._read_par(newpar) else: parupdate = self.hetpar # get signal amplitude model self.__nonGR = self._check_nonGR(parupdate) compstrain = lalpulsar.HeterodynedPulsarGetAmplitudeModel( parupdate.PulsarParameters(), freqfactor, int(not outputampcoeffs), int(roq), self.__nonGR, self.gpstimes, self.resp, ) if (not outputampcoeffs and newpar is None) or roq or outputampcoeffs: return compstrain.data.data else: from .heterodyne.fastheterodyne import fast_heterodyne if not self.usetempo2: # use LAL function for phase calculation origpar = self.hetpar if updateSSB: # if updating SSB other delays *must* also be updated if # required updateBSB = True if parupdate["BINARY"] is not None else updateBSB updateglphase = ( True if parupdate["GLEP"] is not None else updateglphase ) updatefitwaves = ( True if parupdate["WAVEEPOCH"] is not None else updatefitwaves ) elif updateBSB: # if updating BSB the glitch phase must be updated if required updateglphase = ( True if parupdate["GLEP"] is not None else updateglphase ) phase = lalpulsar.HeterodynedPulsarPhaseDifference( parupdate.PulsarParameters(), origpar.PulsarParameters(), self.gpstimes, freqfactor, self.ssbdelay, int( updateSSB ), # the SSB delay should be updated compared to hetSSBdelay self.bsbdelay, int( updateBSB ), # the BSB delay should be updated compared to hetBSBdelay self.glitchphase, int(updateglphase), self.fitwavesphase, int(updatefitwaves), self.resp.det, self.__edat, self.__tdat, self.__units_type, ) self._phasediff = -phase.data.astype(float) else: # use TEMPO2 for phase calculation import sys from astropy.time import Time from libstempo import tempopulsar # convert times to MJD mjdtimes = Time(self.times, format="gps", scale="utc").mjd toaerr = 1e-15 # add tiny error value to stop errors with MuteStream(stream=sys.stdout): psrorig = tempopulsar( parfile=self.parfile, toas=mjdtimes, toaerrs=toaerr, observatory=TEMPO2_GW_ALIASES[self.__detector_name], dofit=False, obsfreq=0.0, # set to 0 so as not to calculate DM delay ) # get phase residuals # NOTE: referencing this to a site and epoch may not be # necessary, but we'll do it as a precaution phaseorig = psrorig.phaseresiduals( removemean="refphs", site="@", epoch=psrorig["PEPOCH"].val, ) with MuteStream(stream=sys.stdout): psrnew = tempopulsar( parfile=parfile, toas=mjdtimes, toaerrs=toaerr, observatory=TEMPO2_GW_ALIASES[self.__detector_name], dofit=False, obsfreq=0.0, # set to 0 so as not to calculate DM delay ) # get phase residuals phasenew = psrnew.phaseresiduals( removemean="refphs", site="@", epoch=psrorig["PEPOCH"].val, ) # get phase difference self._phasediff = freqfactor * (phaseorig - phasenew).astype(float) # re-heterodyne with phase difference return fast_heterodyne(compstrain.data.data, self.phasediff)