Newer
Older
# Copyright (C) 2010--2014 Kipp Cannon, Chad Hanna
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
### A program to create some prior likelihood data to seed an offline analysis
#
# =============================================================================
#
# Preamble
#
# =============================================================================
#
from optparse import OptionParser
Chad Hanna
committed
import numpy
import scipy
Chad Hanna
committed
from lal import series
from ligo.lw import ligolw
from ligo.lw import lsctables
from ligo.lw import array as ligolw_array
from ligo.lw import param as ligolw_param
from ligo.lw import utils as ligolw_utils
from ligo.lw.utils import process as ligolw_process
from gstlal import far
chad.hanna
committed
from gstlal import svd_bank
Chad Hanna
committed
from gstlal import templates
chad.hanna
committed
@ligolw_array.use_in
@ligolw_param.use_in
@lsctables.use_in
class LIGOLWContentHandler(ligolw.LIGOLWContentHandler):
pass
__author__ = "Chad Hanna <chad.hanna@ligo.org>"
__version__ = "git id %s" % "" # FIXME
__date__ = "" # FIXME
#
# =============================================================================
#
# Command Line
#
# =============================================================================
#
def parse_command_line():
parser = OptionParser(
version = "Name: %%prog\n%s" % "" # FIXME
)
parser.add_option("-v", "--verbose", action = "store_true", help = "Be verbose.")
# FIXME: default must be identical to gstlal_inspiral's default
parser.add_option("--coincidence-threshold", metavar = "value", type = "float", default = 0.005, help = "Set the coincidence window in seconds (default = 0.005). The light-travel time between instruments will be added automatically in the coincidence test.")
# FIXME: default must be identical to gstlal_inspiral's default
parser.add_option("--min-instruments", metavar = "count", type = "int", default = 2, help = "Set the minimum number of instruments that must contribute triggers to form a candidate (default = 2).")
parser.add_option("--write-likelihood", metavar = "filename", help = "Write merged raw likelihood data to this file.")
parser.add_option("--instrument", action = "append", help = "Append to a list of instruments to create dist stats for. List must be whatever instruments you intend to analyze.")
parser.add_option("-p", "--background-prior", metavar = "N", default = 1, type = "float", help = "Include an exponential background prior with the maximum bin count = N, default 1")
Chad Hanna
committed
parser.add_option("--df", metavar = "N", default = 40, help = "set the degrees of freedom for the background chisq prior: default 40. You can also use template bandwidth to set this by setting it to 'bandwidth'")
chad.hanna
committed
parser.add_option("--svd-file", metavar = "filename", help = "The SVD file to read the template ids from")
parser.add_option("--mass-model-file", metavar = "filename", help = "The mass model file to read from (hdf5 format)")
Ryan Michael Magee
committed
parser.add_option("--dtdphi-file", metavar = "filename", help = "dtdphi snr ratio pdfs to read from (hdf5 format). Default passed by gstlal_inspiral_pipe, but not when run as a standalone program.")
Chad Hanna
committed
parser.add_option("--psd-xml", type = "string", help = "Specify a PSD to use for computing template bandwidth. Required if df is bandwidth")
options, filenames = parser.parse_args()
process_params = dict(options.__dict__)
if not options.instrument:
raise ValueError("must specify at least one --instrument")
options.instrument = set(options.instrument)
if options.min_instruments < 1:
raise ValueError("--min-instruments must be >= 1")
if options.min_instruments > len(options.instrument):
raise ValueError("--min-instruments is greater than the number of unique --instrument's")
if filenames:
raise ValueError("unrecognized arguments after options: %s" % " ".join(filenames))
Chad Hanna
committed
if options.df == "bandwidth" and options.psd_xml is None:
raise ValueError("Must specify psd xml file if using bandwidth to set degrees of freedom")
psd = {}
if options.psd_xml:
for ifo, p in series.read_psd_xmldoc(ligolw_utils.load_filename(options.psd_xml, verbose = options.verbose, contenthandler = series.PSDContentHandler)).items():
f = numpy.arange(len(p.data.data)) * p.deltaF
psd[ifo] = scipy.interpolate.interp1d(f, p.data.data)
chad.hanna
committed
template_ids = []
horizon_factors = {}
Chad Hanna
committed
bandwidths = []
chad.hanna
committed
for n, bank in enumerate(svd_bank.read_banks(options.svd_file, contenthandler = LIGOLWContentHandler, verbose = options.verbose)):
template_ids += [row.template_id for row in bank.sngl_inspiral_table]
Chad Hanna
committed
# FIXME don't hard code
if options.df == "bandwidth":
for ifo in psd:
bandwidths += [templates.bandwidth(row.mass1, row.mass2, row.spin1z, row.spin2z, f_min = 10.0, f_max = row.f_final, delta_f = 0.25, psd = psd[ifo])]
horizon_factors.update(bank.horizon_factors)
Chad Hanna
committed
if options.df == "bandwidth":
Chad Hanna
committed
# NOTE the 4000 is tuned by looking at real data distributions
options.df = int(4000. / min(bandwidths))
chad.hanna
committed
return options, process_params, filenames, template_ids, horizon_factors
#
# =============================================================================
#
# Main
#
# =============================================================================
#
#
# command line
#
options, process_params, filenames, template_ids, horizon_factors = parse_command_line()
#
# initialize output document (records process start time)
#
xmldoc = ligolw.Document()
xmldoc.appendChild(ligolw.LIGO_LW())
process = ligolw_process.register_to_xmldoc(xmldoc, u"gstlal_inspiral_create_prior_diststats", ifos = options.instrument, paramdict = process_params)
# create parameter distribution priors
Ryan Michael Magee
committed
rankingstat = far.RankingStat(template_ids = template_ids, instruments = options.instrument, delta_t = options.coincidence_threshold, min_instruments = options.min_instruments, population_model_file = options.mass_model_file, dtdphi_file = options.dtdphi_file, horizon_factors = horizon_factors)
if options.background_prior > 0:
Chad Hanna
committed
rankingstat.denominator.add_noise_model(number_of_events = options.background_prior, df = int(options.df))
# Add the numerator
rankingstat.numerator.add_signal_model()
#
# record results in output file
#
far.gen_likelihood_control_doc(xmldoc, rankingstat, None)
#
# done
#
ligolw_process.set_process_end_time(process)
ligolw_utils.write_filename(xmldoc, options.write_likelihood, gz = options.write_likelihood.endswith(".gz"), verbose = options.verbose)