Skip to content
Snippets Groups Projects
Commit e20d4a9a authored by Gregory Ashton's avatar Gregory Ashton
Browse files

Improvements to the template estimation (V, Vsky, Vpe)

1) Moves the actual estimation to external function since it is not
contingent on using the MCMC methods etc
2) Change notation to V, Vsky and Vpe
3) Fix some table outputs (Tcoh was forcing integer)
4) Rename of names -> detector_names
5) Adds tests
6) Writes a simpler table if the sky is not searched over
parent 17ea6923
Branches
Tags
No related merge requests found
...@@ -125,6 +125,71 @@ def read_par(label, outdir): ...@@ -125,6 +125,71 @@ def read_par(label, outdir):
return d return d
def get_V_estimate(
nsegs, tref, minStartTime, maxStartTime, DeltaOmega, DeltaFs,
fiducial_freq, detector_names, earth_ephem, sun_ephem):
""" Returns V, Vsky, Vpe estimated from the super-sky metric
Parameters
----------
nsegs: int
Number of semi-coherent segments
tref: int
Reference time in GPS seconds
minStartTime, maxStartTime: int
Minimum and maximum SFT timestamps
DeltaOmega: float
Solid angle of the sky-patch
DeltaFs: array
Array of [DeltaF0, DeltaF1, ...], length determines the number of
spin-down terms.
fiducial_freq: float
Fidicual frequency
detector_names: array
Array of detectors to average over
earth_ephem, sun_ephem: st
Paths to the ephemeris files
"""
spindowns = len(DeltaFs) - 1
tboundaries = np.linspace(minStartTime, maxStartTime, nsegs+1)
ref_time = lal.LIGOTimeGPS(tref)
segments = lal.SegListCreate()
for j in range(len(tboundaries)-1):
seg = lal.SegCreate(lal.LIGOTimeGPS(tboundaries[j]),
lal.LIGOTimeGPS(tboundaries[j+1]),
j)
lal.SegListAppend(segments, seg)
detNames = lal.CreateStringVector(*detector_names)
detectors = lalpulsar.MultiLALDetector()
lalpulsar.ParseMultiLALDetector(detectors, detNames)
detector_weights = None
detector_motion = (lalpulsar.DETMOTION_SPIN
+ lalpulsar.DETMOTION_ORBIT)
ephemeris = lalpulsar.InitBarycenter(earth_ephem, sun_ephem)
try:
SSkyMetric = lalpulsar.ComputeSuperskyMetrics(
spindowns, ref_time, segments, fiducial_freq, detectors,
detector_weights, detector_motion, ephemeris)
except RuntimeError as e:
logging.debug('Encountered run-time error {}'.format(e))
return None, None, None
sqrtdetG_SKY = np.sqrt(np.linalg.det(
SSkyMetric.semi_rssky_metric.data[:2, :2]))
sqrtdetG_PE = np.sqrt(np.linalg.det(
SSkyMetric.semi_rssky_metric.data[2:, 2:]))
Vsky = .5*sqrtdetG_SKY*DeltaOmega
Vpe = sqrtdetG_PE * np.prod(DeltaFs)
if Vsky == 0:
Vsky = 1
if Vpe == 0:
Vpe = 1
return (Vsky * Vpe, Vsky, Vpe)
class BaseSearchClass(object): class BaseSearchClass(object):
""" The base search class, provides general functions """ """ The base search class, provides general functions """
...@@ -291,8 +356,8 @@ class ComputeFstat(object): ...@@ -291,8 +356,8 @@ class ComputeFstat(object):
logging.info('Loading data matching pattern {}'.format( logging.info('Loading data matching pattern {}'.format(
self.sftfilepath)) self.sftfilepath))
SFTCatalog = lalpulsar.SFTdataFind(self.sftfilepath, constraints) SFTCatalog = lalpulsar.SFTdataFind(self.sftfilepath, constraints)
names = list(set([d.header.name for d in SFTCatalog.data])) detector_names = list(set([d.header.name for d in SFTCatalog.data]))
self.names = names self.detector_names = detector_names
SFT_timestamps = [d.header.epoch for d in SFTCatalog.data] SFT_timestamps = [d.header.epoch for d in SFTCatalog.data]
try: try:
from bashplotlib.histogram import plot_hist from bashplotlib.histogram import plot_hist
...@@ -300,10 +365,10 @@ class ComputeFstat(object): ...@@ -300,10 +365,10 @@ class ComputeFstat(object):
plot_hist(SFT_timestamps, height=5, bincount=50) plot_hist(SFT_timestamps, height=5, bincount=50)
except IOError: except IOError:
pass pass
if len(names) == 0: if len(detector_names) == 0:
raise ValueError('No data loaded.') raise ValueError('No data loaded.')
logging.info('Loaded {} data files from detectors {}'.format( logging.info('Loaded {} data files from detectors {}'.format(
len(SFT_timestamps), names)) len(SFT_timestamps), detector_names))
logging.info('Data spans from {} ({}) to {} ({})'.format( logging.info('Data spans from {} ({}) to {} ({})'.format(
int(SFT_timestamps[0]), int(SFT_timestamps[0]),
subprocess.check_output('lalapps_tconvert {}'.format( subprocess.check_output('lalapps_tconvert {}'.format(
...@@ -2009,74 +2074,39 @@ class MCMCFollowUpSearch(MCMCSemiCoherentSearch): ...@@ -2009,74 +2074,39 @@ class MCMCFollowUpSearch(MCMCSemiCoherentSearch):
if prior[key]['type'] == 'unif': if prior[key]['type'] == 'unif':
return .5*(prior[key]['upper'] + prior[key]['lower']) return .5*(prior[key]['upper'] + prior[key]['lower'])
def get_number_of_templates_estimate(self, nsegs): def init_V_estimate_parameters(self):
""" Returns V, Vsky, Vf estimated from the super-sky metric """
if args.no_template_counting:
return 'N/A'
tboundaries = np.linspace(self.minStartTime, self.maxStartTime,
nsegs+1)
if 'Alpha' in self.theta_keys: if 'Alpha' in self.theta_keys:
DeltaAlpha = self.get_width_from_prior(self.theta_prior, 'Alpha') DeltaAlpha = self.get_width_from_prior(self.theta_prior, 'Alpha')
DeltaDelta = self.get_width_from_prior(self.theta_prior, 'Delta') DeltaDelta = self.get_width_from_prior(self.theta_prior, 'Delta')
DeltaMid = self.get_mid_from_prior(self.theta_prior, 'Delta') DeltaMid = self.get_mid_from_prior(self.theta_prior, 'Delta')
DeltaOmega = np.sin(DeltaMid) * DeltaDelta * DeltaAlpha DeltaOmega = np.sin(DeltaMid) * DeltaDelta * DeltaAlpha
else:
DeltaOmega = 0
if 'F0' in self.theta_keys: if 'F0' in self.theta_keys:
DeltaF0 = self.get_width_from_prior(self.theta_prior, 'F0') DeltaF0 = self.get_width_from_prior(self.theta_prior, 'F0')
else: else:
DeltaF0 = 1 raise ValueError('You are searching over F0?')
DeltaFs = [DeltaF0]
if 'F1' in self.theta_keys: if 'F1' in self.theta_keys:
DeltaF1 = self.get_width_from_prior(self.theta_prior, 'F1') DeltaF1 = self.get_width_from_prior(self.theta_prior, 'F1')
spindowns = 1 DeltaFs.append(DeltaF1)
else: if 'F2' in self.theta_keys:
DeltaF1 = 1 DeltaF2 = self.get_width_from_prior(self.theta_prior, 'F2')
spindowns = 0 DeltaFs.append(DeltaF2)
ref_time = lal.LIGOTimeGPS(self.tref)
segments = lal.SegListCreate()
for j in range(len(tboundaries)-1):
seg = lal.SegCreate(lal.LIGOTimeGPS(tboundaries[j]),
lal.LIGOTimeGPS(tboundaries[j+1]),
j)
lal.SegListAppend(segments, seg)
if type(self.theta_prior['F0']) == dict: if type(self.theta_prior['F0']) == dict:
fiducial_freq = self.get_mid_from_prior(self.theta_prior, 'F0') fiducial_freq = self.get_mid_from_prior(self.theta_prior, 'F0')
else: else:
fiducial_freq = self.theta_prior['F0'] fiducial_freq = self.theta_prior['F0']
detector_names = self.search.names
detNames = lal.CreateStringVector(*detector_names)
detectors = lalpulsar.MultiLALDetector()
lalpulsar.ParseMultiLALDetector(detectors, detNames)
detector_weights = None
detector_motion = (lalpulsar.DETMOTION_SPIN
+ lalpulsar.DETMOTION_ORBIT)
ephemeris = lalpulsar.InitBarycenter(self.earth_ephem,
self.sun_ephem)
try:
SSkyMetric = lalpulsar.ComputeSuperskyMetrics(
spindowns, ref_time, segments, fiducial_freq, detectors,
detector_weights, detector_motion, ephemeris)
except RuntimeError as e:
print e
return 'N/A'
sqrtdetG_SKY = np.sqrt(np.linalg.det( return fiducial_freq, DeltaOmega, DeltaFs
SSkyMetric.semi_rssky_metric.data[:2, :2]))
sqrtdetG_F = np.sqrt(np.linalg.det(
SSkyMetric.semi_rssky_metric.data[2:, 2:]))
if 'Alpha' in self.theta_keys:
return (.5*sqrtdetG_SKY*sqrtdetG_F*DeltaOmega*DeltaF1*DeltaF0,
.5*sqrtdetG_SKY*DeltaOmega,
sqrtdetG_F*DeltaF1*DeltaF0)
else:
return (sqrtdetG_F*DeltaF1*DeltaF0,
'N/A',
sqrtdetG_F*DeltaF1*DeltaF0)
def init_run_setup(self, run_setup, log_table=True, gen_tex_table=True): def init_run_setup(self, run_setup, log_table=True, gen_tex_table=True):
logging.info('Calculating the number of templates for this setup..') logging.info('Calculating the number of templates for this setup..')
number_of_templates = [] Vs = []
Vskys = []
Vpes = []
fiducial_freq, DeltaOmega, DeltaFs = self.init_V_estimate_parameters()
for i, rs in enumerate(run_setup): for i, rs in enumerate(run_setup):
rs = list(rs) rs = list(rs)
if len(rs) == 2: if len(rs) == 2:
...@@ -2084,49 +2114,72 @@ class MCMCFollowUpSearch(MCMCSemiCoherentSearch): ...@@ -2084,49 +2114,72 @@ class MCMCFollowUpSearch(MCMCSemiCoherentSearch):
if np.shape(rs[0]) == (): if np.shape(rs[0]) == ():
rs[0] = (rs[0], 0) rs[0] = (rs[0], 0)
run_setup[i] = rs run_setup[i] = rs
number_of_templates.append(
self.get_number_of_templates_estimate(rs[1])) V, Vsky, Vpe = get_V_estimate(
rs[1], self.tref, self.minStartTime, self.maxStartTime,
DeltaOmega, DeltaFs, fiducial_freq, self.search.detector_names,
self.earth_ephem, self.sun_ephem)
Vs.append(V)
Vskys.append(Vsky)
Vpes.append(Vpe)
if log_table: if log_table:
logging.info('Using run-setup as follow:') logging.info('Using run-setup as follow:')
logging.info('Stage | nburn | nprod | nsegs | Tcoh | resetp0 |' logging.info('Stage | nburn | nprod | nsegs | Tcoh d | resetp0 |'
'# templates = # sky x # Freq') '# templates = # sky x # Freq')
for i, rs in enumerate(run_setup): for i, rs in enumerate(run_setup):
Tcoh = (self.maxStartTime - self.minStartTime) / rs[1] / 86400 Tcoh = (self.maxStartTime - self.minStartTime) / rs[1] / 86400
if number_of_templates[i] == 'N/A': if Vs[i] is None:
vtext = number_of_templates[i] vtext = 'N/A'
elif 'N/A' in number_of_templates[i]:
vtext = '{:1.0e} = {} x {:1.0e}'.format(
*number_of_templates[i])
else: else:
vtext = '{:1.0e} = {:1.0e} x {:1.0e}'.format( vtext = '{:1.0e} = {:1.0e} x {:1.0e}'.format(
*number_of_templates[i]) Vs[i], Vskys[i], Vpes[i])
logging.info('{} | {} | {} | {} | {} | {} | {}'.format( logging.info('{} | {} | {} | {} | {} | {} | {}'.format(
str(i).ljust(5), str(rs[0][0]).ljust(5), str(i).ljust(5), str(rs[0][0]).ljust(5),
str(rs[0][1]).ljust(5), str(rs[1]).ljust(5), str(rs[0][1]).ljust(5), str(rs[1]).ljust(5),
'{:1.2f}'.format(Tcoh).ljust(4), str(rs[2]).ljust(7), vtext)) '{:6.1f}'.format(Tcoh), str(rs[2]).ljust(7),
vtext))
if gen_tex_table: if gen_tex_table:
filename = '{}/{}_run_setup.tex'.format(self.outdir, self.label) filename = '{}/{}_run_setup.tex'.format(self.outdir, self.label)
if DeltaOmega > 0:
with open(filename, 'w+') as f: with open(filename, 'w+') as f:
f.write(r'\begin{tabular}{c|cccccc}' + '\n') f.write(r'\begin{tabular}{c|cccccc}' + '\n')
f.write(r'Stage & $\Nseg$ & $\Tcoh^{\rm days}$ &' f.write(r'Stage & $\Nseg$ & $\Tcoh^{\rm days}$ &'
r'$\Nsteps$ & $\V$ & $\Vsky$ & $\Vf$ \\ \hline' r'$\Nsteps$ & $\V$ & $\Vsky$ & $\Vpe$ \\ \hline'
'\n') '\n')
for i, rs in enumerate(run_setup): for i, rs in enumerate(run_setup):
Tcoh = (self.maxStartTime - self.minStartTime) / rs[1] / 86400 Tcoh = float(self.maxStartTime - self.minStartTime)/rs[1]/86400
line = r'{} & {} & {} & {} & {} & {} & {} \\' + '\n' line = r'{} & {} & {} & {} & {} & {} & {} \\' + '\n'
if number_of_templates[i] == 'N/A': if Vs[i] is None:
V = Vsky = Vf = 'N/A' Vs[i] = Vskys[i] = Vpes[i] = 'N/A'
if rs[0][-1] == 0:
nsteps = rs[0][0]
else: else:
V, Vsky, Vf = number_of_templates[i] nsteps = '{},{}'.format(*rs[0])
line = line.format(i, rs[1], Tcoh, nsteps,
texify_float(Vs[i]),
texify_float(Vskys[i]),
texify_float(Vpes[i]))
f.write(line)
f.write(r'\end{tabular}' + '\n')
else:
with open(filename, 'w+') as f:
f.write(r'\begin{tabular}{c|cccc}' + '\n')
f.write(r'Stage & $\Nseg$ & $\Tcoh^{\rm days}$ &'
r'$\Nsteps$ & $\Vpe$ \\ \hline'
'\n')
for i, rs in enumerate(run_setup):
Tcoh = float(self.maxStartTime - self.minStartTime)/rs[1]/86400
line = r'{} & {} & {} & {} & {} \\' + '\n'
if Vs[i] is None:
Vs[i] = Vskys[i] = Vpes[i] = 'N/A'
if rs[0][-1] == 0: if rs[0][-1] == 0:
nsteps = rs[0][0] nsteps = rs[0][0]
else: else:
nsteps = '{},{}'.format(*rs[0]) nsteps = '{},{}'.format(*rs[0])
line = line.format(i, rs[1], Tcoh, nsteps, line = line.format(i, rs[1], Tcoh, nsteps,
texify_float(V), texify_float(Vsky), texify_float(Vpes[i]))
texify_float(Vf))
f.write(line) f.write(line)
f.write(r'\end{tabular}' + '\n') f.write(r'\end{tabular}' + '\n')
......
...@@ -194,6 +194,42 @@ class TestMCMCSearch(Test): ...@@ -194,6 +194,42 @@ class TestMCMCSearch(Test):
FS > predicted_FS or np.abs((FS-predicted_FS))/predicted_FS < 0.3) FS > predicted_FS or np.abs((FS-predicted_FS))/predicted_FS < 0.3)
class TestAuxillaryFunctions(Test):
nsegs = 10
minStartTime = 1e9
maxStartTime = minStartTime + 100 * 86400
tref = .5*(minStartTime + maxStartTime)
DeltaOmega = 1e-2
DeltaFs = [1e-4, 1e-14]
fiducial_freq = 100
detector_names = ['H1', 'L1']
earth_ephem = pyfstat.earth_ephem
sun_ephem = pyfstat.sun_ephem
def test_get_V_estimate_sky_F0_F1(self):
out = pyfstat.get_V_estimate(
self.nsegs, self.tref, self.minStartTime, self.maxStartTime,
self.DeltaOmega, self.DeltaFs, self.fiducial_freq,
self.detector_names, self.earth_ephem, self.sun_ephem)
V, Vsky, Vpe = out
self.assertTrue(V == Vsky * Vpe)
self.__class__.Vpe_COMPUTED_WITH_SKY = Vpe
def test_get_V_estimate_F0_F1(self):
out = pyfstat.get_V_estimate(
self.nsegs, self.tref, self.minStartTime, self.maxStartTime,
self.DeltaOmega, self.DeltaFs, self.fiducial_freq,
self.detector_names, self.earth_ephem, self.sun_ephem)
V, Vsky, Vpe = out
self.assertTrue(V == Vsky * Vpe)
self.__class__.Vpe_COMPUTED_WITHOUT_SKY = Vpe
def test_the_equivalence_of_Vpe(self):
"""Tests if the Vpe computed with and without the sky are equal """
self.assertEqual(self.__class__.Vpe_COMPUTED_WITHOUT_SKY,
self.__class__.Vpe_COMPUTED_WITH_SKY)
if __name__ == '__main__': if __name__ == '__main__':
outdir = 'TestData' outdir = 'TestData'
if os.path.isdir(outdir): if os.path.isdir(outdir):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment