def test_is_par_file(): """ Test failure of is_par_file. """ assert is_par_file("blah_blah_blah") is False # test par files that don't contain required attributes brokenpar = "broken.par" values = { "F": [100.0], "RAJ": 0.1, "DECJ": -0.1, "PSRJ": "J0101-0101", } for leavekey in list(values.keys()): keys = list(values.keys()) psr = PulsarParametersPy() for key in keys: if key != leavekey: psr[key] = values[key] psr.pp_to_par(brokenpar) assert is_par_file(brokenpar) is False os.remove(brokenpar)
def test_one(): par = PulsarParametersPy() par['F'] = [123.456789, -9.87654321e-12] # set frequency par['DELTAF'] = [0.0, 0.0] # frequency difference par['RAJ'] = lal.TranslateHMStoRAD('01:23:34.5') # set right ascension par['DECJ'] = lal.TranslateDMStoRAD('-45:01:23.4') # set declination pepoch = lal.TranslateStringMJDTTtoGPS('58000') par['PEPOCH'] = pepoch.gpsSeconds + 1e-9 * pepoch.gpsNanoSeconds par['H0'] = 5.6e-26 par['COSIOTA'] = -0.2 par['PSI'] = 0.4 par['PHI0'] = 2.3 freqfactor = 2. # set frequency factor for det in t1output.keys(): # convert into GPS times gpstimes = lalpulsar.CreateTimestampVector(len(t1output[det])) for i, time in enumerate(t1output[det][:, 0]): gpstimes.data[i] = lal.LIGOTimeGPS(time) detector = lalpulsar.GetSiteInfo(det) # set the response function look-up table dt = t1output[det][1, 0] - t1output[det][0, 0] # time step resp = lalpulsar.DetResponseLookupTable(t1output[det][0, 0], detector, par['RAJ'], par['DECJ'], 2880, dt) # get the heterodyned file SSB delay hetSSBdelay = lalpulsar.HeterodynedPulsarGetSSBDelay( par.PulsarParameters(), gpstimes, detector, edat, tdat, lalpulsar.TIMECORRECTION_TCB) fullsignal = lalpulsar.HeterodynedPulsarGetModel( par.PulsarParameters(), freqfactor, 1, 0, 0, gpstimes, hetSSBdelay, 0, None, 0, 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 - t1output[det][:, 1]) > 1e-34): return False elif np.any( np.abs(fullsignal.data.data.imag - t1output[det][:, 2]) > 1e-34): return False return True
def is_par_file(parfile): """ Check if a TEMPO-style pulsar parameter file is valid. Parameters ---------- parfile: str The path to a file. Returns ------- ispar: bool Returns True is if it is a valid parameter file. """ # check that the file is ASCII text (see, e.g., # https://stackoverflow.com/a/1446571/1862861) if os.path.isfile(parfile): msg = subprocess.Popen(["file", "--mime", "--dereference", parfile], stdout=subprocess.PIPE).communicate()[0] if "text/plain" in msg.decode(): psr = PulsarParametersPy(parfile) # file must contain a frequency, right ascension, declination and # pulsar name # file must contain right ascension and declination if (psr["F"] is None or (psr["RAJ"] is None and psr["RA"] is None) or (psr["DECJ"] is None and psr["DEC"] is None) or get_psr_name(psr) is None): return False return True return False
def test_three(harmonic): 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['C22'] = 5.6e-26 parhet['C21'] = 1.4e-25 parhet['COSIOTA'] = -0.2 parhet['PSI'] = 0.4 parhet['PHI21'] = 2.3 parhet['PHI22'] = 4.5 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['C22'] = 5.6e-26 parinj['C21'] = 1.4e-25 parinj['COSIOTA'] = -0.2 parinj['PSI'] = 0.4 parinj['PHI21'] = 2.3 parinj['PHI22'] = 4.5 det = 'H1' # the detector detector = lalpulsar.GetSiteInfo(det) freqfactor = float(harmonic) # set frequency factor # convert into GPS times gpstimes = lalpulsar.CreateTimestampVector(len(t3output[harmonic])) for i, time in enumerate(t3output[harmonic][:, 0]): gpstimes.data[i] = lal.LIGOTimeGPS(time) # set the response function look-up table dt = t3output[harmonic][1, 0] - t3output[harmonic][0, 0] # time step resp = lalpulsar.DetResponseLookupTable(t3output[harmonic][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) fullsignal = lalpulsar.HeterodynedPulsarGetModel( parinj.PulsarParameters(), parhet.PulsarParameters(), freqfactor, 1, 0, 0, gpstimes, hetSSBdelay, 1, None, 0, None, 0, None, 0, resp, edat, tdat, lalpulsar.TIMECORRECTION_TCB) # check output matches that from lalapps_pulsar_parameter_estimation_nested assert_allclose(fullsignal.data.data.real, t3output[harmonic][:, 1]) assert_allclose(fullsignal.data.data.imag, t3output[harmonic][:, 2])
def test_get_psr_name(): """ Test extraction of pulsar name. """ for item, name in zip( ["PSRJ", "PSRB", "PSR", "NAME"], ["J0123+1234", "B0124+12", "J0123+1234", "B0124+12"], ): psr = PulsarParametersPy() psr[item] = name assert get_psr_name(psr) == name
def _read_par(self, par): """ Read a TEMPO-style parameter file into a PulsarParameterPy object. """ if isinstance(par, PulsarParametersPy): return par if isinstance(par, string_types): try: return PulsarParametersPy(par) except IOError: raise IOError( "Could not read in parameter file: '{}'".format(par)) else: raise TypeError("The parameter file must be a string")
def parfiles(self, parfiles): pfs = {} if parfiles is not None: if isinstance(parfiles, dict): pfs = parfiles for psr in pfs: if not is_par_file(pfs[psr]): raise IOError( "{} is not a pulsar parameter file".format( pfs[psr])) elif isinstance(parfiles, str): if os.path.isdir(parfiles): if parfiles == os.path.join(self.basedir, "pulsars"): raise ValueError( "Parameter files directory must be different from " "'{}', which is reserved for the output directories" .format(parfiles)) for pf in os.listdir(parfiles): parfile = os.path.join(parfiles, pf) if is_par_file(parfile): psr = PulsarParametersPy(parfile) # add parfile to dictionary for name in ["PSRJ", "PSRB", "PSR", "NAME"]: if psr[name] is not None: pfs[psr[name]] = parfile else: raise ValueError("Path is not a valid directory") else: raise TypeError( "Must give directory or dictionary of pulsar parameter files" ) self._parfiles = pfs self.npulsars = len(self._parfiles) else: self._parfiles = None self.npulsars = None
def test_five(): par = PulsarParametersPy() par['F'] = [123.456789, -9.87654321e-12] # set frequency par['DELTAF'] = [0.0, 0.0] # frequency difference par['RAJ'] = lal.TranslateHMStoRAD('01:23:34.5') # set right ascension par['DECJ'] = lal.TranslateDMStoRAD('-45:01:23.4') # set declination pepoch = lal.TranslateStringMJDTTtoGPS('58000') par['PEPOCH'] = pepoch.gpsSeconds + 1e-9 * pepoch.gpsNanoSeconds par['HPLUS'] = 5.6e-26 par['HCROSS'] = 1.3e-26 par['HVECTORX'] = 1.4e-26 par['HVECTORY'] = 2.3e-26 par['HSCALARB'] = 4.5e-26 par['HSCALARL'] = 3.1e-26 par['PHI0TENSOR'] = 0.4 par['PSITENSOR'] = 1.2 par['PHI0SCALAR'] = 3.1 par['PSISCALAR'] = 0.2 par['PHI0VECTOR'] = 4.5 par['PSIVECTOR'] = 2.4 par['PHI0'] = 2.3 freqfactor = 2. # set frequency factor det = 'H1' # detector detector = lalpulsar.GetSiteInfo(det) gpstimes = lalpulsar.CreateTimestampVector(len(t5output)) for i, time in enumerate(t5output[:, 0]): gpstimes.data[i] = lal.LIGOTimeGPS(time) # set the response function look-up table dt = t5output[1, 0] - t5output[0, 0] # time step resp = lalpulsar.DetResponseLookupTable(t5output[0, 0], detector, par['RAJ'], par['DECJ'], 2880, dt) # get the heterodyned file SSB delay hetSSBdelay = lalpulsar.HeterodynedPulsarGetSSBDelay( par.PulsarParameters(), gpstimes, detector, edat, tdat, lalpulsar.TIMECORRECTION_TCB) fullsignal = lalpulsar.HeterodynedPulsarGetModel( par.PulsarParameters(), freqfactor, 1, 0, 1, # use non-GR modes gpstimes, hetSSBdelay, 0, None, 0, 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 - t5output[:, 1]) > 1e-34): return False elif np.any(np.abs(fullsignal.data.data.imag - t5output[:, 2]) > 1e-34): return False return True
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, data, priors, par=None, det=None, likelihood="studentst", numba=False): super().__init__(dict()) # initialise likelihood class # set the data if isinstance(data, HeterodynedData): # convert HeterodynedData to MultiHeterodynedData object if data.detector is None: raise ValueError("'data' must contain a named detector.") if data.par is None: raise ValueError( "'data' must contain a heterodyne parameter file.") self.data = MultiHeterodynedData(data) elif isinstance(data, MultiHeterodynedData): if None in data.pars: raise ValueError("A data set does not have an associated " "heterodyned parameter set.") self.data = data else: raise TypeError( "'data' must be a HeterodynedData or MultiHeterodynedData object." ) if not isinstance(priors, bilby.core.prior.PriorDict): raise TypeError("Prior must be a bilby PriorDict") else: self.priors = priors # set the likelihood function self.likelihood = likelihood self._noise_log_likelihood = -np.inf # initialise noise log likelihood self.numba = numba # check if prior includes (non-DeltaFunction) non-amplitude parameters, # i.e., will the phase evolution have to be included in the search, # or binary parameters self.include_phase = False self.include_binary = False self.include_glitch = False self.update_ssb = False for key in self.priors: if (key.upper() not in self.AMPLITUDE_PARAMS + self.BINARY_PARAMS + self.POSITIONAL_PARAMETERS) and not self._is_vector_param( key.upper()): raise ValueError( "Unknown parameter '{}' being used!".format(key)) if key.upper() not in self.AMPLITUDE_PARAMS: if self.priors[key].is_fixed: # check if it's the same value as the par files for het in self.data: if self._is_vector_param(key.upper()): name, idx = self._vector_param_name_index( key.upper()) checkval = het.par[name][idx] else: checkval = het.par[key.upper()] if checkval != self.priors[key].peak: self.include_phase = True if key.upper() in self.BINARY_PARAMS: self.include_binary = True elif key.upper() in self.POSITIONAL_PARAMETERS: self.update_ssb = True elif len(key) > 2: if key.upper()[0:2] == "GL": self.include_glitch = True break else: self.include_phase = True if key.upper() in self.BINARY_PARAMS: self.include_binary = True elif key.upper() in self.POSITIONAL_PARAMETERS: self.update_ssb = True elif len(key) > 2: if key.upper()[0:2] == "GL": self.include_glitch = True # check if any non-GR "amplitude" parameters are set self.nonGR = False for key in self.priors: if key.upper() in self.NONGR_AMPLITUDE_PARAM: self.nonGR = True # set up signal model classes self.models = [] self.basepars = [] for het in self.data: self.models.append( HeterodynedCWSimulator( het.par, het.detector, het.times, earth_ephem=het.ephemearth, sun_ephem=het.ephemsun, )) # copy of heterodyned parameters newpar = PulsarParametersPy() for item in het.par.items(): newpar[item[0]] = item[1] self.basepars.append(newpar) # if phase evolution is not in the model set the pre-summed products # of the data and antenna patterns if not self.include_phase: self.dot_products()
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 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_parse_parfile(self): """ Test parsing of a pulsar '.par' parameter file. """ # set data times = np.linspace(1000000000.0, 1000086340.0, 1440) data = np.random.normal( 0.0, 1e-25, size=1440) + 1j * np.random.normal(0.0, 1e-25, size=1440) # set detector det = "H1" parcontent = """\ PSRJ J0123+3456 RAJ 01:23:45.6789 DECJ 34:56:54.321 F0 567.89 F1 -1.2e-12 PEPOCH 56789 H0 9.87e-26 COSIOTA 0.3 PSI 1.1 PHI0 2.4 """ # try passing a none str or PulsarParameterPy object parfile = 1 with pytest.raises(TypeError): HeterodynedData(data, times=times, detector=det, par=parfile) parfile = "J0123+3456.par" # try reading parfile that doesn't exists with pytest.raises(IOError): HeterodynedData(data, times=times, detector=det, par=parfile) # add content to the par file with open(parfile, "w") as fp: fp.write(parcontent) het = HeterodynedData(data, times=times, detector=det, par=parfile) assert isinstance(het.par, PulsarParametersPy) assert len(het.par["F"]) == 2 assert (het.par["F"][0] == 567.89) and (het.par["F"][1] == -1.2e-12) assert ((het.par["H0"] == 9.87e-26) and (het.par["COSIOTA"] == 0.3) and (het.par["PSI"] == 1.1) and (het.par["PHI0"] == 2.4)) assert het.par["RAJ"] == lal.TranslateHMStoRAD("01:23:45.6789") assert het.par["DECJ"] == lal.TranslateDMStoRAD("34:56:54.321") pepoch = lal.TranslateStringMJDTTtoGPS("56789") assert het.par["PEPOCH"] == (pepoch.gpsSeconds + 1e-9 * pepoch.gpsNanoSeconds) # pass parameters as PulsarParametersPy object del het par = PulsarParametersPy(parfile) het = HeterodynedData(data, times=times, detector=det, par=par) assert isinstance(het.par, PulsarParametersPy) assert len(het.par["F"]) == len(par["F"]) assert (het.par["F"][0] == par["F"][0]) and (het.par["F"][1] == par["F"][1]) assert ((het.par["H0"] == par["H0"]) and (het.par["COSIOTA"] == par["COSIOTA"]) and (het.par["PSI"] == par["PSI"]) and (het.par["PHI0"] == par["PHI0"])) assert het.par["RAJ"] == par["RAJ"] assert het.par["DECJ"] == par["DECJ"] assert het.par["PEPOCH"] == par["PEPOCH"] os.remove(parfile)
def create_pulsars(self): """ Create the pulsar parameter files based on the supplied distributions. """ # pulsar parameter/injection file directory self.pulsardir = os.path.join(self.basedir, "pulsars") self.makedirs(self.pulsardir) self.pulsars = {} self.priors = {} for i in range(self.npulsars): # generate fake pulsar parameters if self.posdist is not None: skyloc = self.posdist.sample() if self._posdist_type in ["galactocentric", "galactic"]: # transform coordinates if required gpos = ( Galactocentric( x=skyloc["x"] * u.kpc, y=skyloc["y"] * u.kpc, z=skyloc["z"] * u.kpc, ) if self._posdist_type == "galactocentric" else Galactic( l=skyloc["l"] * u.rad, # noqa: E741 b=skyloc["b"] * u.rad, distance=skyloc["dist"] * u.kpc, )) eqpos = gpos.transform_to(ICRS) skyloc["ra"] = eqpos.ra.rad skyloc["dec"] = eqpos.dec.rad skyloc["dist"] = eqpos.distance.value if self.fdist is not None: freq = self.fdist.sample() # generate orientation parameters orientation = self.oridist.sample() if self.parfiles is None: pulsar = PulsarParametersPy() pulsar["RAJ"] = skyloc["ra"] pulsar["DECJ"] = skyloc["dec"] pulsar["DIST"] = (skyloc["dist"] * u.kpc).to("m").value # set pulsar name from sky position rastr = "".join( pulsar.convert_to_tempo_units( "RAJ", pulsar["RAJ"]).split(":")[:2]) decstr = "".join( pulsar.convert_to_tempo_units( "DECJ", pulsar["DECJ"]).split(":")[:2]) decstr = decstr if decstr[0] == "-" else ("+" + decstr) pname = "J{}{}".format(rastr, decstr) pnameorig = str(pname) # copy of original name counter = 1 while pname in self.pulsars: anum = int_to_alpha(counter) pname = pnameorig + anum counter += 1 pulsar["PSRJ"] = pname pulsar["F"] = [freq] for param in ["psi", "iota", "phi0"]: pulsar[param.upper()] = orientation[param] # output file name pfile = os.path.join(self.pulsardir, "{}.par".format(pname)) injfile = pfile self.priors[pname] = self.prior else: pfile = list(self.parfiles.values())[i] pulsar = PulsarParametersPy(pfile) pname = list(self.parfiles.keys())[i] injfile = os.path.join(self.pulsardir, "{}.par".format(pname)) if pulsar["DIST"] is None or (self.overwrite and "dist" in skyloc): # add distance if not present in parameter file pulsar["DIST"] = (skyloc["dist"] * u.kpc).to("m").value for param in ["psi", "iota", "phi0"]: # add orientation values if not present in parameter file if pulsar[param.upper()] is None or (self.overwrite and param in orientation): pulsar[param.upper()] = orientation[param] if isinstance(self.prior, dict) and pname in self.prior: # there are individual pulsar priors self.priors[pname] = self.prior[pname] else: self.priors[pname] = self.prior # check whether to add distance uncertainties to priors if self.distance_err is not None: dist = None if isinstance(self.distance_err, float): # set truncated Gaussian prior dist = bilby.core.prior.TruncatedGaussian( pulsar["DIST"], self.distance_err * pulsar["DIST"], 0.0, np.inf, name="dist", ) elif pname in self.distance_err: if isinstance(self.distance_err[pname], float): dist = bilby.core.prior.TruncatedGaussian( pulsar["DIST"], self.distance_err[pname] * pulsar["DIST"], 0.0, np.inf, name="dist", ) elif isinstance(self.distance_err[pname], bilby.core.prior.Prior): dist = self.distance_err[pname] if dist is not None and "dist" not in self.priors[pname]: # only add distance if not already specified self.priors[pname]["dist"] = dist # set amplitude value amp = self.ampdist.sample() if self.ampdist is not None else None if self.ampdist.name == "q22" and (pulsar["Q22"] is None or self.overwrite): pulsar["Q22"] = amp elif self.ampdist.name == "h0" and (pulsar["H0"] is None or self.overwrite): pulsar["H0"] = amp elif (self.ampdist.name.lower() in [ "epsilon", "ell", "ellipticity" ]) and (pulsar["Q22"] is None or self.overwrite): # convert ellipticity to Q22 using fiducial moment of inertia pulsar["Q22"] = ellipticity_to_q22(amp) with open(injfile, "w") as fp: fp.write(str(pulsar)) self.pulsars[pname] = {} self.pulsars[pname]["file"] = pfile self.pulsars[pname]["injection_file"] = injfile self.pulsars[pname]["parameters"] = pulsar
def setup_class(cls): # create dummy frame cache files cls.dummydir = "testing_frame_cache" os.makedirs(cls.dummydir, exist_ok=True) cls.dummy_cache_files = [] for i in range(0, 5): dummyfile = os.path.join(cls.dummydir, "frame_cache_{0:01d}.cache".format(i)) cls.dummy_cache_files.append(dummyfile) with open(dummyfile, "w") as fp: fp.write("blah\n") # create some fake data frames using lalapps_Makefakedata_v5 mfd = shutil.which("lalapps_Makefakedata_v5") cls.fakedatadir = "testing_fake_frame_cache" cls.fakedatadetectors = ["H1", "L1"] cls.fakedatachannels = [ "{}:FAKE_DATA".format(det) for det in cls.fakedatadetectors ] cls.fakedatastarts = [1000000000, 1000000000 + 86400 * 2] cls.fakedataduration = 86400 os.makedirs(cls.fakedatadir, exist_ok=True) cls.fakedatabandwidth = 8 # Hz sqrtSn = 1e-29 # noise amplitude spectral density cls.fakedataname = "FAKEDATA" # Create two pulsars to inject: one isolated and one binary cls.fakepulsarpar = [] # requirements for Makefakedata pulsar input files isolatedstr = """\ Alpha = {alpha} Delta = {delta} Freq = {f0} f1dot = {f1} f2dot = {f2} refTime = {pepoch} h0 = {h0} cosi = {cosi} psi = {psi} phi0 = {phi0} """ binarystr = """\ orbitasini = {asini} orbitPeriod = {period} orbitTp = {Tp} orbitArgp = {argp} orbitEcc = {ecc} """ transientstr = """\ transientWindowType = {wintype} transientStartTime = {tstart} transientTau = {tau} """ # FIRST PULSAR (ISOLATED) f0 = 6.9456 / 2.0 # source rotation frequency (Hz) f1 = -9.87654e-11 / 2.0 # source rotational frequency derivative (Hz/s) f2 = 2.34134e-18 / 2.0 # second frequency derivative (Hz/s^2) alpha = 0.0 # source right ascension (rads) delta = 0.5 # source declination (rads) pepoch = 1000000000 # frequency epoch (GPS) # GW parameters h0 = 3.0e-24 # GW amplitude phi0 = 1.0 # GW initial phase (rads) cosiota = 0.1 # cosine of inclination angle psi = 0.5 # GW polarisation angle (rads) mfddic = { "alpha": alpha, "delta": delta, "f0": 2 * f0, "f1": 2 * f1, "f2": 2 * f2, "pepoch": pepoch, "h0": h0, "cosi": cosiota, "psi": psi, "phi0": phi0, } cls.fakepulsarpar.append(PulsarParametersPy()) cls.fakepulsarpar[0]["PSRJ"] = "J0000+0000" cls.fakepulsarpar[0]["H0"] = h0 cls.fakepulsarpar[0]["PHI0"] = phi0 / 2.0 cls.fakepulsarpar[0]["PSI"] = psi cls.fakepulsarpar[0]["COSIOTA"] = cosiota cls.fakepulsarpar[0]["F"] = [f0, f1, f2] cls.fakepulsarpar[0]["RAJ"] = alpha cls.fakepulsarpar[0]["DECJ"] = delta cls.fakepulsarpar[0]["PEPOCH"] = pepoch cls.fakepulsarpar[0]["EPHEM"] = "DE405" cls.fakepulsarpar[0]["UNITS"] = "TDB" cls.fakepardir = "testing_fake_par_dir" os.makedirs(cls.fakepardir, exist_ok=True) cls.fakeparfile = [] cls.fakeparfile.append(os.path.join(cls.fakepardir, "J0000+0000.par")) cls.fakepulsarpar[0].pp_to_par(cls.fakeparfile[-1]) injfile = os.path.join(cls.fakepardir, "inj.dat") with open(injfile, "w") as fp: fp.write("[Pulsar 1]\n") fp.write(isolatedstr.format(**mfddic)) fp.write("\n") # SECOND PULSAR (BINARY SYSTEM) f0 = 3.8654321 / 2.0 # source rotation frequency (Hz) f1 = 9.87654e-13 / 2.0 # source rotational frequency derivative (Hz/s) f2 = -1.34134e-20 / 2.0 # second frequency derivative (Hz/s^2) alpha = 1.3 # source right ascension (rads) delta = -0.4 # source declination (rads) pepoch = 1000086400 # frequency epoch (GPS) # GW parameters h0 = 7.5e-25 # GW amplitude phi0 = 0.7 # GW initial phase (rads) cosiota = 0.6 # cosine of inclination angle psi = 1.1 # GW polarisation angle (rads) # binary parameters asini = 1.4 # projected semi-major axis (ls) period = 0.1 * 86400 # orbital period (s) Tp = 999992083 # time of periastron (GPS) argp = 0.0 # argument of perisatron (rad) ecc = 0.09 # the orbital eccentricity mfddic = { "alpha": alpha, "delta": delta, "f0": 2 * f0, "f1": 2 * f1, "f2": 2 * f2, "pepoch": pepoch, "h0": h0, "cosi": cosiota, "psi": psi, "phi0": phi0, } mfdbindic = { "asini": asini, "Tp": Tp, "period": period, "argp": argp, "ecc": ecc, } cls.fakepulsarpar.append(PulsarParametersPy()) cls.fakepulsarpar[1]["PSRJ"] = "J1111+1111" cls.fakepulsarpar[1]["H0"] = h0 cls.fakepulsarpar[1]["PHI0"] = phi0 / 2.0 cls.fakepulsarpar[1]["PSI"] = psi cls.fakepulsarpar[1]["COSIOTA"] = cosiota cls.fakepulsarpar[1]["F"] = [f0, f1, f2] cls.fakepulsarpar[1]["RAJ"] = alpha cls.fakepulsarpar[1]["DECJ"] = delta cls.fakepulsarpar[1]["PEPOCH"] = pepoch cls.fakepulsarpar[1]["BINARY"] = "BT" cls.fakepulsarpar[1]["E"] = ecc cls.fakepulsarpar[1]["A1"] = asini cls.fakepulsarpar[1]["T0"] = Tp cls.fakepulsarpar[1]["OM"] = argp cls.fakepulsarpar[1]["PB"] = period cls.fakepulsarpar[1]["EPHEM"] = "DE405" cls.fakepulsarpar[1]["UNITS"] = "TDB" cls.fakeparfile.append(os.path.join(cls.fakepardir, "J1111+1111.par")) cls.fakepulsarpar[1].pp_to_par(cls.fakeparfile[-1]) with open(injfile, "a") as fp: fp.write("[Pulsar 2]\n") fp.write(isolatedstr.format(**mfddic)) fp.write(binarystr.format(**mfdbindic)) fp.write("\n") # THIRD PULSAR (GLITCHING PULSAR) f0 = 5.3654321 / 2.0 # source rotation frequency (Hz) f1 = -4.57654e-10 / 2.0 # source rotational frequency derivative (Hz/s) f2 = 1.34134e-18 / 2.0 # second frequency derivative (Hz/s^2) alpha = 4.6 # source right ascension (rads) delta = -0.9 # source declination (rads) pepoch = 1000000000 + 1.5 * 86400 # frequency epoch (GPS) # glitch parameters df0 = 0.0001 # EM glitch frequency jump df1 = 1.2e-11 # EM glitch frequency derivative jump df2 = -4.5e-19 # EM glitch frequency second derivative jump dphi = 1.1 # EM glitch phase offset glepoch = pepoch # glitch epoch # GW parameters h0 = 8.7e-25 # GW amplitude phi0 = 0.142 # GW initial phase (rads) cosiota = -0.3 # cosine of inclination angle psi = 0.52 # GW polarisation angle (rads) # binary parameters asini = 2.9 # projected semi-major axis (ls) period = 0.3 * 86400 # orbital period (s) Tp = 999995083 # time of periastron (GPS) argp = 0.5 # argument of perisatron (rad) ecc = 0.09 # the orbital eccentricity # for MFD I need to create this as two transient pulsars using a # rectangular window cutting before and after the glitch mfddic = { "alpha": alpha, "delta": delta, "f0": 2 * f0, "f1": 2 * f1, "f2": 2 * f2, "pepoch": pepoch, "h0": h0, "cosi": cosiota, "psi": psi, "phi0": phi0, } mfdbindic = { "asini": asini, "Tp": Tp, "period": period, "argp": argp, "ecc": ecc, } mfdtransientdic = { "wintype": "rect", "tstart": cls.fakedatastarts[0], "tau": 86400, } # signal before the glitch with open(injfile, "a") as fp: fp.write("[Pulsar 3]\n") fp.write(isolatedstr.format(**mfddic)) fp.write(binarystr.format(**mfdbindic)) fp.write(transientstr.format(**mfdtransientdic)) fp.write("\n") mfddic["f0"] = 2 * (f0 + df0) mfddic["f1"] = 2 * (f1 + df1) mfddic["f2"] = 2 * (f2 + df2) mfddic["phi0"] = phi0 + 2 * dphi mfdtransientdic["tstart"] = cls.fakedatastarts[1] # signal after the glitch with open(injfile, "a") as fp: fp.write("[Pulsar 4]\n") fp.write(isolatedstr.format(**mfddic)) fp.write(binarystr.format(**mfdbindic)) fp.write(transientstr.format(**mfdtransientdic)) cls.fakepulsarpar.append(PulsarParametersPy()) cls.fakepulsarpar[2]["PSRJ"] = "J2222+2222" cls.fakepulsarpar[2]["H0"] = h0 cls.fakepulsarpar[2]["PHI0"] = phi0 / 2.0 cls.fakepulsarpar[2]["PSI"] = psi cls.fakepulsarpar[2]["COSIOTA"] = cosiota cls.fakepulsarpar[2]["F"] = [f0, f1, f2] cls.fakepulsarpar[2]["RAJ"] = alpha cls.fakepulsarpar[2]["DECJ"] = delta cls.fakepulsarpar[2]["PEPOCH"] = pepoch cls.fakepulsarpar[2]["BINARY"] = "BT" cls.fakepulsarpar[2]["E"] = ecc cls.fakepulsarpar[2]["A1"] = asini cls.fakepulsarpar[2]["T0"] = Tp cls.fakepulsarpar[2]["OM"] = argp cls.fakepulsarpar[2]["PB"] = period cls.fakepulsarpar[2]["EPHEM"] = "DE405" cls.fakepulsarpar[2]["UNITS"] = "TDB" cls.fakepulsarpar[2]["GLEP"] = [glepoch] cls.fakepulsarpar[2]["GLF0"] = [df0] cls.fakepulsarpar[2]["GLF1"] = [df1] cls.fakepulsarpar[2]["GLF2"] = [df2] cls.fakepulsarpar[2]["GLPH"] = [dphi / (2 * np.pi)] cls.fakeparfile.append(os.path.join(cls.fakepardir, "J2222+2222.par")) cls.fakepulsarpar[2].pp_to_par(cls.fakeparfile[-1]) # set ephemeris files efile = download_file(DOWNLOAD_URL.format("earth00-40-DE405.dat.gz"), cache=True) sfile = download_file(DOWNLOAD_URL.format("sun00-40-DE405.dat.gz"), cache=True) for datastart in cls.fakedatastarts: for i in range(len(cls.fakedatachannels)): cmds = [ "-F", cls.fakedatadir, "--outFrChannels={}".format(cls.fakedatachannels[i]), "-I", cls.fakedatadetectors[i], "--sqrtSX={0:.1e}".format(sqrtSn), "-G", str(datastart), "--duration={}".format(cls.fakedataduration), "--Band={}".format(cls.fakedatabandwidth), "--fmin", "0", '--injectionSources="{}"'.format(injfile), "--outLabel={}".format(cls.fakedataname), '--ephemEarth="{}"'.format(efile), '--ephemSun="{}"'.format(sfile), ] # run makefakedata sp.run([mfd] + cmds) # create dummy segment file cls.dummysegments = [(1000000000, 1000000600), (1000000800, 1000000900)] cls.dummysegmentfile = os.path.join(cls.fakedatadir, "fakesegments.txt") with open(cls.dummysegmentfile, "w") as fp: for segs in cls.dummysegments: fp.write("{} {}\n".format(segs[0], segs[1]))