gstlal-inspiral  0.4.2
 All Classes Namespaces Files Functions Variables Pages
gstlal_inspiral_calc_rank_pdfs
1 #!/usr/bin/env python
2 #
3 # Copyright (C) 2010--2014 Kipp Cannon, Chad Hanna
4 #
5 # This program is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the
7 # Free Software Foundation; either version 2 of the License, or (at your
8 # option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 # Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License along
16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 
19 ## @file
20 # A program to compute the noise probability distributions of likehood ratios for inspiral triggers
21 #
22 # ### Command line interface
23 #
24 # + `--likelihood-cache` [filename]: Also load the likelihood ratio data files listsed in this LAL cache. See lalapps_path2cache for information on how to produce a LAL cache file.
25 # + `--verbose`: Be verbose.
26 # + `--ranking-stat-samples` [N] (int): Construct ranking statistic histograms by drawing this many samples from the ranking statistic generator (default = 1000000).
27 # + `--output` [filename]: Write merged raw likelihood data and likelihood ratio histograms to this LIGO Light-Weight XML file.
28 
29 #
30 # =============================================================================
31 #
32 # Preamble
33 #
34 # =============================================================================
35 #
36 
37 
38 from optparse import OptionParser
39 import sys
40 
41 
42 from glue import iterutils
43 from glue.lal import CacheEntry
44 from glue.ligolw import ligolw
45 from glue.ligolw import utils as ligolw_utils
46 from glue.ligolw.utils import process as ligolw_process
47 from glue.ligolw.utils import search_summary as ligolw_search_summary
48 from glue import segments
49 from gstlal import far
50 
51 
52 __author__ = "Kipp Cannon <kipp.cannon@ligo.org>"
53 __version__ = "git id %s" % "" # FIXME
54 __date__ = "" # FIXME
55 
56 
57 #
58 # =============================================================================
59 #
60 # Command Line
61 #
62 # =============================================================================
63 #
64 
65 
66 def parse_command_line():
67  parser = OptionParser(
68  version = "Name: %%prog\n%s" % "" # FIXME
69  )
70  parser.add_option("--likelihood-cache", metavar = "filename", help = "Also load the likelihood ratio data files listsed in this LAL cache. See lalapps_path2cache for information on how to produce a LAL cache file.")
71  parser.add_option("-v", "--verbose", action = "store_true", help = "Be verbose.")
72  parser.add_option("--ranking-stat-samples", metavar = "N", default = 10000000, type = "int", help = "Construct ranking statistic histograms by drawing this many samples from the ranking statistic generator (default = 10000000).")
73  parser.add_option("--samples-file", metavar = "filename", action = "append", help = "Load the results of previous sampler runs from this file, and add the samples we generate to it. Can be given multiple times.")
74  parser.add_option("--samples-cache", metavar = "filename", help = "Load the results of previous sampler runs from the files listed in this LAL cache. See lalapps_path2cache for information on how to produce a LAL cache file.")
75  parser.add_option("--output", metavar = "filename", help = "Write merged raw likelihood data and likelihood ratio histograms to this LIGO Light-Weight XML file.")
76  options, urls = parser.parse_args()
77 
78  paramdict = options.__dict__.copy()
79 
80  if options.likelihood_cache is not None:
81  urls += [CacheEntry(line).url for line in open(options.likelihood_cache)]
82  if not urls:
83  raise ValueError("must provide some likelihood files")
84 
85  if options.samples_file is None:
86  options.samples_file = []
87  if options.samples_cache is not None:
88  options.samples_file += [CacheEntry(line).url for line in open(options.samples_cache)]
89 
90  if options.output is None:
91  raise ValueError("must set --output")
92 
93  return options, urls, paramdict
94 
95 
96 #
97 # =============================================================================
98 #
99 # Main
100 #
101 # =============================================================================
102 #
103 
104 
105 #
106 # command line
107 #
108 
109 
110 options, urls, paramdict = parse_command_line()
111 
112 
113 #
114 # load parameter distribution data and, optionally, samples from previous
115 # runs
116 #
117 
118 
119 old_ranking_data = None
120 for n, filename in enumerate(options.samples_file, start = 1):
121  if options.verbose:
122  print >>sys.stderr, "%d/%d:" % (n, len(options.samples_file)),
123  xmldoc = ligolw_utils.load_url(filename, contenthandler = far.ThincaCoincParamsDistributions.LIGOLWContentHandler, verbose = options.verbose)
124  ignored, this_ranking_data, ignored = far.parse_likelihood_control_doc(xmldoc)
125  xmldoc.unlink()
126  if this_ranking_data is None:
127  raise ValueError("%s does not contain ranking statistic distribution data" % filename)
128  if old_ranking_data is None:
129  old_ranking_data = this_ranking_data
130  else:
131  old_ranking_data += this_ranking_data
132 
133 coincparamsdistributions = None
134 seglists = segments.segmentlistdict()
135 for n, likelihood_url in enumerate(urls, start = 1):
136  if options.verbose:
137  print >>sys.stderr, "%d/%d:" % (n, len(urls)),
138  xmldoc = ligolw_utils.load_url(likelihood_url, contenthandler = far.ThincaCoincParamsDistributions.LIGOLWContentHandler, verbose = options.verbose)
139  this_coincparamsdistributions, ignored, this_seglists = far.parse_likelihood_control_doc(xmldoc)
140  xmldoc.unlink()
141  if this_coincparamsdistributions is None:
142  raise ValueError("%s does not contain parameter distribution data" % likelihood_url)
143  if coincparamsdistributions is None:
144  coincparamsdistributions = this_coincparamsdistributions
145  else:
146  coincparamsdistributions += this_coincparamsdistributions
147  seglists |= this_seglists
148 
149 if options.verbose:
150  print >>sys.stderr, "total livetime:\n\t%s" % ",\n\t".join("%s = %s s" % (instrument, str(abs(segs))) for instrument, segs in seglists.items())
151 
152 # Compute the probability of instruments given signal
153 coincparamsdistributions.populate_prob_of_instruments_given_signal(segs = seglists, n = 1.0, verbose = options.verbose)
154 
155 # Compute the intrument combination counts
156 coincparamsdistributions.add_instrument_combination_counts(segs = seglists, verbose = options.verbose)
157 
158 
159 #
160 # rebuild event parameter PDFs (+= method has not constructed these
161 # correctly)
162 #
163 
164 
165 coincparamsdistributions.finish(verbose = options.verbose)
166 if old_ranking_data is not None:
167  old_ranking_data.finish(verbose = options.verbose)
168 
169 
170 #
171 # take a moment to make sure we have SNR PDFs for all instrument
172 # combinations so that we don't end up doing this inside the sampling
173 # threads
174 #
175 
176 
177 all_instrument_combos = [instruments for n in range(2, len(seglists) + 1) for instruments in iterutils.choices(seglists.keys(), n)]
178 for horizon_distances in coincparamsdistributions.horizon_history.all():
179  for instruments in all_instrument_combos:
180  coincparamsdistributions.get_snr_joint_pdf(instruments, horizon_distances, verbose = options.verbose)
181 
182 
183 #
184 # generate likelihood ratio histograms
185 #
186 
187 
188 ranking_data = far.RankingData(coincparamsdistributions, instruments = seglists.keys(), nsamples = options.ranking_stat_samples, verbose = options.verbose)
189 if old_ranking_data is not None:
190  ranking_data += old_ranking_data
191 
192 
193 #
194 # Write the parameter and ranking statistic distribution data to a file
195 #
196 
197 
198 xmldoc = ligolw.Document()
199 xmldoc.appendChild(ligolw.LIGO_LW())
200 process = ligolw_process.register_to_xmldoc(xmldoc, u"gstlal_inspiral_calc_rank_pdfs", paramdict = paramdict)
201 search_summary = ligolw_search_summary.append_search_summary(xmldoc, process, ifos = seglists.keys(), inseg = seglists.extent_all(), outseg = seglists.extent_all())
202 far.gen_likelihood_control_doc(xmldoc, process, coincparamsdistributions, ranking_data, seglists)
203 ligolw_process.set_process_end_time(process)
204 ligolw_utils.write_filename(xmldoc, options.output, gz = (options.output or "stdout").endswith(".gz"), verbose = options.verbose)