29from __future__
import print_function
33from optparse
import OptionParser
38from igwn_ligolw
import dbtables
39from igwn_ligolw
import utils
as ligolw_utils
42from lalburst
import git_version
43from lalburst
import SimBurstUtils
44from lalburst
import SnglBurstUtils
45import igwn_segments
as segments
48__author__ =
"Kipp Cannon <kipp.cannon@ligo.org>"
49__version__ =
"git id %s" % git_version.id
50__date__ = git_version.date
63 parser = OptionParser(
64 version =
"Name: %%prog\n%s" % git_version.verbose_msg
66 parser.add_option(
"-b",
"--base", metavar =
"base", default =
"string_plotbinj_", help =
"Set the prefix for output filenames (default = \"string_plotbinj_\").")
67 parser.add_option(
"-f",
"--format", metavar =
"format", action =
"append", default = [], help =
"Set the output image format (default = \"png\"). Option can be given multiple times to generate plots in multiple formats.")
68 parser.add_option(
"--amplitude-func", metavar =
"det|wave", default =
"det", help =
"Select the amplitude to show on the plots. \"det\" = the amplitude expected in the detector, \"wave\" = the amplitude of the wave (default = \"det\").")
69 parser.add_option(
"--input-cache", metavar =
"filename", action =
"append", default = [], help =
"Get list of files from this LAL cache.")
70 parser.add_option(
"-l",
"--live-time-program", metavar =
"program", default =
"StringSearch", help =
"Set the name of the program, as it appears in the process table, whose search summary entries define the search live time (default = \"StringSearch\").")
71 parser.add_option(
"--plot", metavar =
"number", action =
"append", default =
None, help =
"Generate the given plot number (default = make all plots).")
72 parser.add_option(
"-t",
"--tmp-space", metavar =
"path", help =
"Path to a directory suitable for use as a work area while manipulating the database file. The database file will be worked on in this directory, and then moved to the final location when complete. This option is intended to improve performance when running in a networked environment, where there might be a local disk with higher bandwidth than is available to the filesystem on which the final output will reside.")
73 parser.add_option(
"-v",
"--verbose", action =
"store_true", help =
"Be verbose.")
74 options, filenames = parser.parse_args()
76 if options.amplitude_func ==
"wave":
77 options.amplitude_func =
lambda sim, instrument, offsetvector: sim.amplitude
78 options.amplitude_lbl =
r"$A^{\mathrm{wave}}$"
79 elif options.amplitude_func ==
"det":
80 options.amplitude_func = SimBurstUtils.string_amplitude_in_instrument
81 options.amplitude_lbl =
r"$A^{\mathrm{det}}$"
83 raise ValueError(
"unrecognized --amplitude-func %s" % options.amplitude_func)
85 if not options.format:
86 options.format = [
"png"]
88 if options.plot
is not None:
91 options.plot = sorted(set(map(int, options.plot)))
93 filenames = filenames
or []
94 for cache
in options.input_cache:
96 print(
"reading '%s' ..." % cache, file=sys.stderr)
97 filenames += [CacheEntry(line).path
for line
in file(cache)]
99 raise ValueError(
"Nothing to do!")
101 return options, filenames
119 for nevents,
in contents.connection.cursor().execute(
"""
126 """, (contents.sb_definer_id,)):
128 while nevents + 1 >= len(self.
bins):
130 self.
bins[nevents] += 1
133 fig, axes = SnglBurstUtils.make_burst_plot(
"Number of Triggers Coincident with Injection",
"Count")
135 axes.plot(range(len(self.
bins)), self.
bins,
"ko-")
136 axes.set_title(
"Triggers per Found Injection\n(%d Found Injections)" % self.
found)
164 offsetvectors = contents.time_slide_table.as_dict()
165 for values
in contents.connection.cursor().execute(
"""
172 JOIN sim_burst_map AS map ON (
173 map.simulation_id == sim_burst.simulation_id
176 sngl_burst.event_id == map.event_id
179 sim = contents.sim_burst_table.row_from_cols(values)
180 instrument, amplitude_rec = values[-2:]
182 data = self.
data[instrument]
184 data = self.
data[instrument] = self.
Data()
186 data.x.append(abs(self.
amplitude_func(sim, instrument, offsetvectors[sim.time_slide_id])))
187 data.y.append(abs(amplitude_rec))
188 data.c.append(math.log(sim.frequency))
191 for instrument, data
in sorted(self.
data.items()):
192 fig, axes = SnglBurstUtils.make_burst_plot(
"Injected %s" % self.
amplitude_lbl,
r"Recovered $A$")
194 fig.set_size_inches(8, 8)
195 axes.scatter(data.x, data.y, c = data.c, s = 16)
198 xmin, xmax =
min(data.x),
max(data.x)
199 ymin, ymax =
min(data.y),
max(data.y)
200 xmin = ymin =
min(xmin, ymin)
201 xmax = ymax =
max(xmax, ymax)
202 axes.plot([xmin, xmax], [ymin, ymax],
"k-")
203 axes.set_xlim([xmin, xmax])
204 axes.set_ylim([ymin, ymax])
205 axes.set_title(
r"Recovered $A$ vs.\ Injected %s in %s (%d Recovered Injections)" % (self.
amplitude_lbl, instrument, data.found))
226 bins = int(float(abs(interval)) / width) * 21
227 self.
binning = rate.NDBins((rate.LinearBins(interval[0], interval[1], bins),))
231 offsetvectors = contents.time_slide_table.as_dict()
232 for values
in contents.connection.cursor().execute(
"""
237 sngl_burst.peak_time, sngl_burst.peak_time_ns
240 JOIN sim_burst_map AS map ON (
241 map.simulation_id == sim_burst.simulation_id
244 sngl_burst.event_id == map.event_id
247 sim = contents.sim_burst_table.row_from_cols(values)
248 instrument = values[-4]
249 burst_snr = values[-3]
250 burst_peak = dbtables.lsctables.LIGOTimeGPS(*values[-2:])
251 sim_peak = sim.time_at_instrument(instrument, offsetvectors[sim.time_slide_id])
254 data = self.
data[instrument]
260 data.offsets.count[float(burst_peak - sim_peak),] += 1.0
266 for instrument, data
in sorted(self.
data.items()):
267 fig, axes = SnglBurstUtils.make_burst_plot(
r"$t_{\mathrm{recovered}} - t_{\mathrm{injected}}$ (s)",
"Triggers per Unit Offset")
269 axes.set_title(
"Trigger Peak Time - Injection Peak Time in %s\n(%d Found Injections)" % (instrument, data.found))
271 rate.filter_array(data.offsets.array, rate.gaussian_window(21))
272 axes.plot(data.offsets.centres()[0], data.offsets.at_centres(),
"k")
306 for simulation_id, sim_frequency, instrument, burst_frequency, burst_snr
in contents.connection.cursor().execute(
"""
308 sim_burst.simulation_id,
311 -- central_freq = (f_cut + f_bankstart) / 2
312 -- bandwidth = f_cut - f_bankstart
313 -- therefore f_cut = ...
314 sngl_burst.central_freq + sngl_burst.bandwidth / 2,
318 JOIN sim_burst_map AS map ON (
319 map.simulation_id == sim_burst.simulation_id
322 sngl_burst.event_id == map.event_id
325 simulation_ids.setdefault(instrument, set()).add(simulation_id)
327 dataA = self.
dataA[instrument]
328 dataB = self.
dataB[instrument]
333 dataA.x.append(burst_snr)
334 dataA.y.append((burst_frequency - sim_frequency) / sim_frequency)
336 dataB.x.append(sim_frequency)
337 dataB.y.append(burst_frequency)
338 dataB.c.append(math.log(burst_snr))
342 for instrument, simulation_ids
in simulation_ids.items():
343 self.
dataA[instrument].found += len(simulation_ids)
344 self.
dataB[instrument].found += len(simulation_ids)
347 for instrument, data
in sorted(self.
dataA.items()):
348 fig, axes = SnglBurstUtils.make_burst_plot(
r"SNR in %s" % instrument,
r"$(f_{\mathrm{recovered}} - f_{\mathrm{injected}})/ f_{\mathrm{injected}}$")
350 axes.set_title(
"Cut-off Frequency Residual vs.\\ SNR in %s\n(%d Found Injections)" % (instrument, data.found))
352 axes.plot(data.x, data.y,
"k+")
356 for instrument, data
in sorted(self.
dataB.items()):
357 fig, axes = SnglBurstUtils.make_burst_plot(
r"$f_{\mathrm{injected}}$ (Hz)",
r"$f_{\mathrm{recovered}}$ (Hz)")
359 fig.set_size_inches(8, 8)
360 axes.scatter(data.x, data.y, c = data.c, s = 16)
361 xmin, xmax =
min(data.x),
max(data.x)
362 ymin, ymax =
min(data.y),
max(data.y)
363 xmin = ymin =
min(xmin, ymin)
364 xmax = ymax =
max(xmax, ymax)
365 axes.plot([xmin, xmax], [ymin, ymax],
"k-")
366 axes.set_xlim([xmin, xmax])
367 axes.set_ylim([ymin, ymax])
368 axes.set_title(
r"Recovered Cut-off Frequency vs.\ Injected Cut-off Frequency in %s\\(%d Injections; red = high recovered SNR, blue = low recovered SNR)" % (instrument, data.found))
394 for instrument, chi2, chi2dof, snr, is_injection
in contents.connection.cursor().execute(
"""
398 sngl_burst.chisq_dof,
400 sngl_burst.event_id IN (
402 coinc_event_map.event_id
405 JOIN coinc_event ON (
406 coinc_event.coinc_event_id == coinc_event_map.coinc_event_id
409 coinc_event_map.table_name == 'sngl_burst'
410 AND coinc_event.coinc_def_id == ?
414 """, (contents.sb_definer_id,)):
417 self.
data[instrument].injections_x.append(snr)
418 self.
data[instrument].injections_y.append(chi2 / chi2dof)
421 self.
data[instrument].injections_x.append(snr)
422 self.
data[instrument].injections_y.append(chi2 / chi2dof)
425 self.
data[instrument].noninjections_x.append(snr)
426 self.
data[instrument].noninjections_y.append(chi2 / chi2dof)
429 self.
data[instrument].noninjections_x.append(snr)
430 self.
data[instrument].noninjections_y.append(chi2 / chi2dof)
433 for instrument, data
in sorted(self.
data.items()):
434 fig, axes = SnglBurstUtils.make_burst_plot(
r"SNR",
r"$\chi^{2} / \mathrm{DOF}$")
436 axes.set_title(
"$\\chi^{2} / \\mathrm{DOF}$ vs.\\ SNR in %s" % instrument)
438 axes.plot(data.injections_x, data.injections_y,
"r+")
439 axes.plot(data.noninjections_x, data.noninjections_y,
"k+")
474if options.plot
is not None:
475 plots = [plots[i]
for i
in options.plot]
483for n, filename
in enumerate(ligolw_utils.sort_files_by_size(filenames, options.verbose, reverse =
True)):
485 print(
"%d/%d: %s" % (n + 1, len(filenames), filename), file=sys.stderr)
486 working_filename = dbtables.get_connection_filename(filename, tmp_path = options.tmp_space, verbose = options.verbose)
487 database = SnglBurstUtils.CoincDatabase(sqlite3.connect(str(working_filename)), options.live_time_program, search =
"StringCusp")
489 SnglBurstUtils.summarize_coinc_database(database)
490 is_injection_db =
"sim_burst" in dbtables.get_table_names(database.connection)
492 database.connection.cursor().execute(
"""
493CREATE TEMPORARY TABLE
497 a.event_id AS simulation_id,
498 a.coinc_event_id AS coinc_event_id,
499 b.event_id AS event_id
502 JOIN coinc_event ON (
503 coinc_event.coinc_event_id == a.coinc_event_id
505 JOIN coinc_event_map AS b ON (
506 b.table_name == 'sngl_burst'
507 AND b.coinc_event_id == a.coinc_event_id
510 a.table_name ==
'sim_burst'
511 AND coinc_event.coinc_def_id == ?
512 """, (database.sb_definer_id,))
513 for n, requires_injection_db, plot in plots:
514 if requires_injection_db
and not is_injection_db:
517 print(
"adding to plot group %d ..." % n, file=sys.stderr)
518 plot.add_contents(database)
519 database.connection.close()
520 dbtables.discard_connection_filename(filename, working_filename, verbose = options.verbose)
528format =
"%%s%%0%dd%%s.%%s" % (int(math.log10(len(plots)
or 1)) + 1)
530 n, requires_injection_db, plot = plots.pop(0)
532 print(
"finishing plot group %d ..." % n, file=sys.stderr)
535 except ValueError
as e:
536 print(
"can't finish plot group %d: %s" % (n, str(e)), file=sys.stderr)
538 for f, fig
in enumerate(figs):
539 for extension
in options.format:
540 filename = format % (options.base, n, chr(97 + f), extension)
542 print(
"writing %s ..." % filename, file=sys.stderr)
543 fig.savefig(filename)
def add_contents(self, contents)
def add_contents(self, contents)
def __init__(self, binning)
def __init__(self, interval, width)
def add_contents(self, contents)
def add_contents(self, contents)
def __init__(self, amplitude_func, amplitude_lbl)
def add_contents(self, contents)