def test_bad_par_file(self): """ Test correct exceptions raised for invalid parameter files. """ with pytest.raises(TypeError): # pass a float rather than a string _ = HeterodynedCWSimulator(par=4.5, det="H1") with pytest.raises(IOError): # pass non-existant file string _ = HeterodynedCWSimulator(par="blah.par", det="H1")
def test_dc_signal(self): """ Test creating signals from a triaxial source heterodyned so that the signal only varies due to the antenna response of the detector. """ for det in self.detectors: het = HeterodynedCWSimulator(par=self.comparison, det=det, times=self.timesfixed) model = het.model(freqfactor=2) assert len(model) == len(self.timesfixed) assert model.dtype == complex assert np.allclose(model, self.compare2f[det])
def test_offset_signal(self): """ Test signals generated with an offset of parameters using the LAL and TEMPO2 options. """ for det in self.detectors: # using LAL routines het = HeterodynedCWSimulator(par=self.comparison, det=det, times=self.timesvary) modellal = het.model(newpar=self.offset, freqfactor=2, updateSSB=True) # using TEMPO2 routines hettempo = HeterodynedCWSimulator(par=self.comparison, det=det, times=self.timesvary, usetempo2=True) modeltempo = hettempo.model(newpar=self.offset, freqfactor=2) assert len(modellal) == len(self.timesvary) assert len(modeltempo) == len(self.timesvary) # test mismatch between using LAL and TEMPO assert mismatch(modellal, modeltempo) < 5e-5 # test angle between models (we expected there to be a constant phase shift # between the TEMPO2 and LAL calculations due to binary system signals not # being referenced as expected) # NOTE: the test tolerances are higher that generally needed due to one # time stamp for H1 that is more significantly different than for the # other detectors - this is probably a Shapiro delay difference that has # particular effect on the line of site for this source and that detector phasediff = np.mod( np.angle(modellal, deg=True) - np.angle(modeltempo, deg=True), 360) assert np.std(phasediff) < 0.01 assert np.max(phasediff) - np.min(phasediff) < 0.1
def test_heterodyne(self): """ Test heterodyning on fake data. """ segments = [(self.fakedatastarts[i], self.fakedatastarts[i] + self.fakedataduration[i]) for i in range(len(self.fakedatastarts))] het = Heterodyne( pulsarfiles=self.fakeparfile, pulsars=["J0000+0000"], segmentlist=segments, framecache=self.fakedatadir, channel=self.fakedatachannels[0], ) with pytest.raises(TypeError): het.stride = "ksgdk" with pytest.raises(TypeError): het.stride = 4.5 with pytest.raises(ValueError): het.stride = -1 with pytest.raises(TypeError): het.filterknee = "lshdl" with pytest.raises(ValueError): het.filterknee = 0 with pytest.raises(TypeError): het.freqfactor = "ldkme" with pytest.raises(ValueError): het.freqfactor = -2.3 # test that output directory has defaulted to cwd assert os.path.split(list( het.outputfiles.values())[0])[0] == os.getcwd() # test setting an output directory outdir = os.path.join(self.fakedatadir, "heterodyne_output") het.outputfiles = outdir assert len(het.outputfiles) == 1 assert list(het.outputfiles.keys()) == ["J0000+0000"] assert list(het.outputfiles.values()) == [ os.path.join( outdir, het.label.format(psr="J0000+0000", gpsstart=None, gpsend=None, det="H1", freqfactor=2), ) ] with pytest.raises(ValueError): # attempt to include glitch evolution without setting includessb to True het.heterodyne(includeglitch=True) # perform first stage heterodyne het = heterodyne( starttime=segments[0][0], endtime=segments[-1][-1], pulsarfiles=self.fakeparfile, segmentlist=segments, framecache=self.fakedatadir, channel=self.fakedatachannels[0], freqfactor=2, stride=86400 // 2, output=outdir, resamplerate=1, ) # expected length (after cropping) uncroppedsegs = [ seg for seg in segments if (seg[1] - seg[0]) > het.crop ] length = (het.resamplerate * np.diff(uncroppedsegs).sum() - 2 * len(uncroppedsegs) * het.crop) # expected start time (after cropping) t0 = segments[0][0] + het.crop + 0.5 / het.resamplerate # expected end time (after croppping) tend = segments[-1][-1] - het.crop - 0.5 / het.resamplerate # check output for psr in ["J0000+0000", "J1111+1111", "J2222+2222"]: assert os.path.isfile(het.outputfiles[psr]) hetdata = HeterodynedData.read(het.outputfiles[psr]) assert len(hetdata) == length assert het.resamplerate == hetdata.dt.value assert t0 == hetdata.times.value[0] assert tend == hetdata.times.value[-1] assert het.detector == hetdata.detector # perform second stage of heterodyne with pytest.raises(TypeError): Heterodyne(heterodyneddata=0) fineoutdir = os.path.join(self.fakedatadir, "fine_heterodyne_output") # first heterodyne without SSB het2 = heterodyne( detector=self.fakedatadetectors[0], heterodyneddata=outdir, # pass previous output directory pulsarfiles=self.fakeparfile, freqfactor=2, resamplerate=1 / 60, includessb=False, output=fineoutdir, label="heterodyne_{psr}_{det}_{freqfactor}.hdf5", ) models = [] lengthnew = int( np.sum([ np.floor( ((seg[1] - seg[0]) - 2 * het2.crop) * het2.resamplerate) for seg in uncroppedsegs ])) for i, psr in enumerate(["J0000+0000", "J1111+1111", "J2222+2222"]): # load data hetdata = HeterodynedData.read(het2.outputfiles[psr]) assert het2.resamplerate == 1 / hetdata.dt.value assert len(hetdata) == lengthnew # set expected model sim = HeterodynedCWSimulator( hetdata.par, hetdata.detector, times=hetdata.times.value, earth_ephem=hetdata.ephemearth, sun_ephem=hetdata.ephemsun, ) # due to how the HeterodynedCWSimulator works we need to set # updateglphase = True for the glitching signal to generate a # signal without the glitch phase included! models.append( sim.model( freqfactor=hetdata.freq_factor, updateglphase=(True if psr == "J2222+2222" else False), )) # without inclusion of SSB model should not match assert np.any(relative_difference(hetdata.data, models[i]) > 5e-3) # now heterodyne with SSB del het2 het2 = heterodyne( detector=self.fakedatadetectors[0], heterodyneddata=outdir, # pass previous output directory pulsarfiles=self.fakeparfile, freqfactor=2, resamplerate=1 / 60, includessb=True, output=fineoutdir, label="heterodyne_{psr}_{det}_{freqfactor}.hdf5", overwrite=True, ) for i, psr in enumerate(["J0000+0000", "J1111+1111", "J2222+2222"]): # load data hetdata = HeterodynedData.read(het2.outputfiles[psr]) assert het2.resamplerate == 1 / hetdata.dt.value assert len(hetdata) == lengthnew # check output matches model to within 2% if psr == "J0000+0000": # isolated pulsar assert np.all( relative_difference(hetdata.data, models[i]) < 0.02) else: # without inclusion of BSB/glitch phase model should not match assert np.any( relative_difference(hetdata.data, models[i]) > 0.02) # now heterodyne with SSB and BSB del het2 het2 = heterodyne( detector=self.fakedatadetectors[0], heterodyneddata={ psr: het.outputfiles[psr] for psr in ["J0000+0000", "J1111+1111", "J2222+2222"] }, # test using dictionary pulsarfiles=self.fakeparfile, freqfactor=2, resamplerate=1 / 60, includessb=True, includebsb=True, output=fineoutdir, label="heterodyne_{psr}_{det}_{freqfactor}.hdf5", overwrite=True, ) for i, psr in enumerate(["J0000+0000", "J1111+1111", "J2222+2222"]): # load data hetdata = HeterodynedData.read(het2.outputfiles[psr]) assert het2.resamplerate == 1 / hetdata.dt.value assert len(hetdata) == lengthnew if psr in [ "J0000+0000", "J1111+1111", ]: # isolated and binary pulsar (non-glitching) assert np.all( relative_difference(hetdata.data, models[i]) < 0.02) else: # without inclusion glitch phase model should not match assert np.any( relative_difference(hetdata.data, models[i]) > 0.02) # now heterodyne with SSB, BSB and glitch phase del het2 het2 = heterodyne( detector=self.fakedatadetectors[0], heterodyneddata={ psr: het.outputfiles[psr] for psr in ["J0000+0000", "J1111+1111", "J2222+2222"] }, # test using dictionary pulsarfiles=self.fakeparfile, freqfactor=2, resamplerate=1 / 60, includessb=True, includebsb=True, includeglitch=True, output=fineoutdir, label="heterodyne_{psr}_{det}_{freqfactor}.hdf5", overwrite=True, ) for i, psr in enumerate(["J0000+0000", "J1111+1111", "J2222+2222"]): # load data hetdata = HeterodynedData.read(het2.outputfiles[psr]) assert het2.resamplerate == 1 / hetdata.dt.value assert len(hetdata) == lengthnew assert np.all(relative_difference(hetdata.data, models[i]) < 0.02)
def test_full_heterodyne_tempo2(self): """ Test heterodyning on fake data, performing the heterodyne in one step, using TEMPO2 for the phase calculation. """ segments = [(self.fakedatastarts[i], self.fakedatastarts[i] + self.fakedataduration[i]) for i in range(len(self.fakedatastarts))] # perform heterodyne in one step fulloutdir = os.path.join(self.fakedatadir, "full_heterodyne_output_tempo2") inputkwargs = dict( starttime=segments[0][0], endtime=segments[-1][-1], pulsarfiles=self.fakeparfile, segmentlist=segments, framecache=self.fakedatadir, channel=self.fakedatachannels[0], freqfactor=2, stride=86400 // 2, resamplerate=1 / 60, usetempo2=True, output=fulloutdir, label="heterodyne_{psr}_{det}_{freqfactor}.hdf5", ) het = heterodyne(**inputkwargs) # compare against model for i, psr in enumerate(["J0000+0000", "J1111+1111", "J2222+2222"]): # load data hetdata = HeterodynedData.read(het.outputfiles[psr]) assert het.resamplerate == 1 / hetdata.dt.value # check heterodyne_arguments were stored and retrieved correctly assert isinstance(hetdata.heterodyne_arguments, dict) for param in inputkwargs: if param == "pulsarfiles": assert inputkwargs[param][ i] == hetdata.heterodyne_arguments[param] assert hetdata.heterodyne_arguments["pulsars"] == psr else: assert inputkwargs[param] == hetdata.heterodyne_arguments[ param] # set expected model sim = HeterodynedCWSimulator( hetdata.par, hetdata.detector, times=hetdata.times.value, earth_ephem=hetdata.ephemearth, sun_ephem=hetdata.ephemsun, ) # due to how the HeterodynedCWSimulator works we need to set # updateglphase = True for the glitching signal to generate a # signal without the glitch phase included! model = sim.model( freqfactor=hetdata.freq_factor, updateglphase=(True if psr == "J2222+2222" else False), ) # increase tolerance for acceptance due to small outliers (still # equivalent at the ~2% level) if psr == "J0000+0000": assert np.all(relative_difference(hetdata.data, model) < 0.02) # check that the models match to within 1e-5 assert mismatch(hetdata.data, model) < 1e-5 # for binary signals the initial phase when using tempo2 will # be shifted, but check that the shift is approximately # constant (maximum variation within 1.5 degs and standard # deviation within 0.1 degs) phasedata = np.angle(hetdata.data, deg=True) phasemodel = np.angle(model, deg=True) phasediff = phasedata - phasemodel # add on 180 degs so that J0000+0000, which should have zero phase shift, # passes the tests (otherwise there are point around 0 and 360 degs) phasediff = np.mod(phasediff + 180, 360) assert np.std(phasediff) < 0.1 assert phasediff.max() - phasediff.min() < 1.5
def test_full_heterodyne(self): """ Test heterodyning on fake data, performing the heterodyne in one step. """ segments = [(self.fakedatastarts[i], self.fakedatastarts[i] + self.fakedataduration[i]) for i in range(len(self.fakedatastarts))] # perform heterodyne in one step fulloutdir = os.path.join(self.fakedatadir, "full_heterodyne_output") inputkwargs = dict( starttime=segments[0][0], endtime=segments[-1][-1], pulsarfiles=self.fakeparfile, segmentlist=segments, framecache=self.fakedatadir, channel=self.fakedatachannels[0], freqfactor=2, stride=86400 // 2, resamplerate=1 / 60, includessb=True, includebsb=True, includeglitch=True, output=fulloutdir, label="heterodyne_{psr}_{det}_{freqfactor}.hdf5", ) het = heterodyne(**inputkwargs) # compare against model for i, psr in enumerate(["J0000+0000", "J1111+1111", "J2222+2222"]): # load data hetdata = HeterodynedData.read(het.outputfiles[psr]) assert het.resamplerate == 1 / hetdata.dt.value # check heterodyne_arguments were stored and retrieved correctly assert isinstance(hetdata.heterodyne_arguments, dict) for param in inputkwargs: if param == "pulsarfiles": assert inputkwargs[param][ i] == hetdata.heterodyne_arguments[param] assert hetdata.heterodyne_arguments["pulsars"] == psr else: assert inputkwargs[param] == hetdata.heterodyne_arguments[ param] # set expected model sim = HeterodynedCWSimulator( hetdata.par, hetdata.detector, times=hetdata.times.value, earth_ephem=hetdata.ephemearth, sun_ephem=hetdata.ephemsun, ) # due to how the HeterodynedCWSimulator works we need to set # updateglphase = True for the glitching signal to generate a # signal without the glitch phase included! model = sim.model( freqfactor=hetdata.freq_factor, updateglphase=(True if psr == "J2222+2222" else False), ) # increase tolerance for acceptance due to small outliers (still # equivalent at the ~2% level) assert np.all(relative_difference(hetdata.data, model) < 0.02)