31from optparse
import OptionParser
36from igwn_ligolw
import dbtables
37from igwn_ligolw
import utils
40from lalburst
import git_version
41from lalburst
import SimBurstUtils
42from lalburst
import SnglBurstUtils
43import igwn_segments
as segments
46__author__ =
"Kipp Cannon <kipp.cannon@ligo.org>"
47__version__ =
"git id %s" % git_version.id
48__date__ = git_version.date
61 parser = OptionParser(
62 version =
"Name: %%prog\n%s" % git_version.verbose_msg
64 parser.add_option(
"--made-only", action =
"store_true", default =
False, help =
"Plot only injections that were made.")
65 parser.add_option(
"-b",
"--base", metavar =
"base", default =
"plotbinj_", help =
"Set the prefix for output filenames (default = \"plotbinj_\")")
66 parser.add_option(
"-f",
"--format", metavar =
"format", default =
"png", help =
"Set the output image format (default = \"png\")")
67 parser.add_option(
"--amplitude-func", metavar =
"hrsswave|hrssdet|E", default =
"hrsswave", help =
"Select the amplitude to show on the plots. \"hrsswave\" = the h_rss of the wave, \"hrssdet\" = the h_rss in the detector, \"E\" = the radiated energy over r^2.")
68 parser.add_option(
"--input-cache", metavar =
"filename", action =
"append", default = [], help =
"Get list of trigger files from this LAL cache file.")
69 parser.add_option(
"-l",
"--live-time-program", metavar =
"program", default =
"lalapps_power", help =
"Set the name, as it appears in the process table, of the program whose search summary entries define the search live time (default = \"lalapps_power\").")
70 parser.add_option(
"--plot", metavar =
"number", action =
"append", default =
None, help =
"Generate the given plot number (default = make all plots). Use \"none\" to disable plots.")
71 parser.add_option(
"--coinc-plot", metavar =
"number", action =
"append", default =
None, help =
"Generate the given coinc plot number (default = make all coinc plots). Use \"none\" to disable coinc 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 ==
"hrsswave":
77 options.amplitude_func =
lambda sim, instrument, offsetvector: sim.hrss
78 options.amplitude_lbl =
r"$h_{\mathrm{rss}}$"
79 elif options.amplitude_func ==
"hrssdet":
80 options.amplitude_func = SimBurstUtils.hrss_in_instrument
81 options.amplitude_lbl =
r"$h_{\mathrm{rss}}^{\mathrm{det}}$"
82 elif options.amplitude_func ==
"E":
83 options.amplitude_func =
lambda sim, instrument, offsetvector: sim.egw_over_rsquared
84 options.amplitude_lbl =
r"$M_{\odot} / \mathrm{pc}^{2}$"
86 raise ValueError(
"unrecognized --amplitude-func %s" % options.amplitude_func)
88 if options.plot
is None:
89 options.plot = range(10)
90 elif "none" in options.plot:
93 options.plot = map(int, options.plot)
94 if options.coinc_plot
is None:
95 options.coinc_plot = range(2)
96 elif "none" in options.coinc_plot:
97 options.coinc_plot = []
99 options.coinc_plot = map(int, options.coinc_plot)
101 filenames = filenames
or []
102 for cache
in options.input_cache:
104 print(
"reading '%s' ..." % cache, file=sys.stderr)
105 filenames += [CacheEntry(line).path
for line
in file(cache)]
107 return options, filenames
121 self.fig, self.
axes = SnglBurstUtils.make_burst_plot(
"GPS Time (s)",
"Frequency (Hz)")
133 for values
in contents.connection.cursor().execute(
"""
142 sngl_burst.event_id == sim_burst_map.event_id
145 sim_burst_map.simulation_id == sim_burst.simulation_id
146 AND sngl_burst.ifo == ?
150 """, (self.instrument,)):
151 sim = contents.sim_burst_table.row_from_cols(values)
153 if SimBurstUtils.injection_was_made(sim, contents.seglists, (self.
instrument,)):
155 peak = float(sim.time_at_instrument(self.
instrument))
164 if not options.made_only:
166 for seg
in ~self.
seglist & segments.segmentlist([segments.segment(self.
axes.get_xlim())]):
167 self.
axes.axvspan(float(seg[0]), float(seg[1]), facecolor =
"k", alpha = 0.2)
182 def __init__(self, instrument, amplitude_func, amplitude_lbl):
183 self.fig, self.
axes = SnglBurstUtils.make_burst_plot(
"Frequency (Hz)", amplitude_lbl)
195 offsetvectors = contents.time_slide_table.as_dict()
196 for values
in contents.connection.cursor().execute(
"""
205 sngl_burst.event_id == sim_burst_map.event_id
208 sim_burst_map.simulation_id == sim_burst.simulation_id
209 AND sngl_burst.ifo == ?
213 """, (self.instrument,)):
214 sim = contents.sim_burst_table.row_from_cols(values)
216 if SimBurstUtils.injection_was_made(sim, contents.seglists, (self.
instrument,)):
227 if not options.made_only:
245 self.fig, self.
axes = SnglBurstUtils.make_burst_plot(
"Number of Triggers Coincident with Injection",
"Count")
252 for nevents,
in contents.connection.cursor().execute(
"""
259 """, (contents.sb_definer_id,)):
261 while nevents + 1 >= len(self.
bins):
263 self.
bins[nevents] += 1
267 self.
axes.set_title(
"Triggers per Found Injection\n(%d Found Injections)" % self.
found)
280 def __init__(self, instrument, amplitude_func, amplitude_lbl):
281 self.fig, self.
axes = SnglBurstUtils.make_burst_plot(
r"Injected " + amplitude_lbl,
r"Recovered $h_{\mathrm{rss}}$")
283 self.fig.set_size_inches(8, 8)
293 offsetvectors = contents.time_slide_table.as_dict()
294 for values
in contents.connection.cursor().execute(
"""
297 sngl_burst.peak_frequency,
301 JOIN sim_burst_map ON (
302 sim_burst_map.simulation_id == sim_burst.simulation_id
305 sngl_burst.event_id == sim_burst_map.event_id
309 """, (self.instrument,)):
310 sim = contents.sim_burst_table.row_from_cols(values)
311 freq_rec, hrss_rec = values[-2:]
315 self.c.append(math.log(freq_rec))
318 self.
axes.scatter(self.
x, self.
y, c = self.
c, s = 16)
321 xmin, xmax =
min(self.
x),
max(self.
x)
322 ymin, ymax =
min(self.
y),
max(self.
y)
323 xmin = ymin =
min(xmin, ymin)
324 xmax = ymax =
max(xmax, ymax)
325 self.
axes.
plot([xmin, xmax], [ymin, ymax],
"k-")
326 self.
axes.set_xlim([xmin, xmax])
327 self.
axes.set_ylim([ymin, ymax])
328 self.
axes.set_title(
r"Recovered $h_{\mathrm{rss}}$ vs.\ Injected " + self.
amplitude_lbl +
" (%d Events Matching Injections)" % self.
matches)
332 def __init__(self, instrument, amplitude_func, amplitude_lbl):
333 self.fig, self.
axes = SnglBurstUtils.make_burst_plot(
r"$f_{\mathrm{injected}}$ (Hz)",
r"Recovered $h_{\mathrm{rss}}$ / Injected "+ amplitude_lbl)
335 self.fig.set_size_inches(8, 8)
345 offsetvectors = contents.time_slide_table.as_dict()
346 for values
in contents.connection.cursor().execute(
"""
349 sngl_burst.peak_frequency,
353 JOIN sim_burst_map ON (
354 sim_burst_map.simulation_id == sim_burst.simulation_id
357 sngl_burst.event_id == sim_burst_map.event_id
361 """, (self.instrument,)):
362 sim = contents.sim_burst_table.row_from_cols(values)
363 freq_rec, hrss_rec = values[-2:]
367 self.c.append(math.log(freq_rec))
370 self.
axes.scatter(self.
x, self.
y, c = self.
c, s = 16)
373 self.
axes.set_title(
r"Ratio of Recovered $h_{\mathrm{rss}}$ to Injected " + self.
amplitude_lbl +
r" vs.\ Frequency (%d Events Matching Injections)" % self.
matches)
377 def __init__(self, instrument, amplitude_func, amplitude_lbl):
378 self.fig, self.
axes = SnglBurstUtils.make_burst_plot(
r"$\Delta f_{\mathrm{recovered}}$ (Hz)",
r"Recovered $h_{\mathrm{rss}}$ / Injected " + amplitude_lbl)
380 self.fig.set_size_inches(8, 8)
390 offsetvectors = contents.time_slide_table.as_dict()
391 for values
in contents.connection.cursor().execute(
"""
394 sngl_burst.bandwidth,
395 sngl_burst.peak_frequency,
399 JOIN sim_burst_map ON (
400 sim_burst_map.simulation_id == sim_burst.simulation_id
403 sngl_burst.event_id == sim_burst_map.event_id
407 """, (self.instrument,)):
408 sim = contents.sim_burst_table.row_from_cols(values)
409 bandwidth, freq_rec, hrss_rec = values[-3:]
413 self.c.append(math.log(freq_rec))
416 self.
axes.scatter(self.
x, self.
y, c = self.
c, s = 16)
419 self.
axes.set_title(
r"Ratio of Recovered $h_{\mathrm{rss}}$ to Injected " + self.
amplitude_lbl +
r" vs.\ Recovered Bandwidth (%d Events Matching Injections)" % self.
matches)
433 self.fig, self.
axes = SnglBurstUtils.make_burst_plot(
r"$t_{\mathrm{recovered}} - t_{\mathrm{injected}}$ (s)",
"Triggers per Unit Offset")
438 bins = int(float(abs(interval)) / width) * 21
439 binning = rate.NDBins((rate.LinearBins(interval[0], interval[1], bins),))
447 for values
in contents.connection.cursor().execute(
"""
450 coinc_event.coinc_event_id
453 JOIN coinc_event_map ON (
454 coinc_event_map.coinc_event_id == coinc_event.coinc_event_id
457 coinc_event_map.table_name == 'sim_burst'
458 AND coinc_event_map.event_id == sim_burst.simulation_id
462 """, (contents.sb_definer_id,)):
463 sim = contents.sim_burst_table.row_from_cols(values)
464 coinc_event_id = values[-1]
465 sim_peak = sim.time_at_instrument(self.instrument)
467 bursts = tuple(SnglBurstUtils.coinc_sngl_bursts(contents, coinc_event_id))
470 dt = float(burst.peak - sim_peak)
477 coinc_dt += dt * burst.ms_snr
478 coinc_dt /= sum(burst.ms_snr
for burst
in bursts)
486 self.
axes.set_title(
"Trigger Peak Time - Injection Peak Time\n(%d Found Injections)" % self.
found)
488 filter = rate.gaussian_window(21)
489 rate.filter_array(self.
offsets.array, filter)
493 self.
axes.legend([
"%s residuals" % self.
instrument,
"SNR-weighted mean of residuals in all instruments"], loc =
"lower right")
507 self.fig, self.
axes = SnglBurstUtils.make_burst_plot(
r"$f_{\mathrm{recovered}} / f_{\mathrm{injected}}$",
"Event Number Density")
512 bins = int(float(abs(interval)) / width) * 21
513 binning = rate.NDBins((rate.LinearBins(interval[0], interval[1], bins),))
521 for coinc_event_id, sim_frequency
in contents.connection.cursor().execute(
"""
523 coinc_event.coinc_event_id,
527 JOIN coinc_event_map ON (
528 coinc_event_map.coinc_event_id == coinc_event.coinc_event_id
531 coinc_event_map.table_name == 'sim_burst'
532 AND sim_burst.simulation_id == coinc_event_map.event_id
535 coinc_event.coinc_def_id == ?
536 """, (contents.sb_definer_id,)):
538 bursts = tuple(SnglBurstUtils.coinc_sngl_bursts(contents, coinc_event_id))
541 df = math.log(burst.peak_frequency / sim_frequency, 10)
548 coinc_freq = sum(burst.peak_frequency * burst.ms_snr
for burst
in bursts) / sum(burst.ms_snr
for burst
in bursts)
549 df = math.log(coinc_freq / sim_frequency, 10)
557 self.
axes.set_title(
"Trigger Peak Frequency / Injection Centre Frequency\n(%d Found Injections)" % self.
found)
559 filter = rate.gaussian_window(21)
560 rate.filter_array(self.
offsets.array, filter)
564 self.
axes.legend([
"%s triggers" % self.
instrument,
"SNR-weighted mean of all matching triggers"], loc =
"lower right")
565 ymin, ymax = self.
axes.get_ylim()
566 if ymax / ymin > 1e6:
568 self.
axes.set_ylim((ymin, ymax))
582 self.fig, self.
axes = SnglBurstUtils.make_burst_plot(
r"$f_{\mathrm{injected}}$ (Hz)",
r"$f_{\mathrm{recovered}}$ (Hz)")
584 self.fig.set_size_inches(8, 8)
593 offsetvectors = contents.time_slide_table.as_dict()
594 for values
in contents.connection.cursor().execute(
"""
597 sngl_burst.peak_frequency,
601 JOIN sim_burst_map ON (
602 sim_burst_map.simulation_id == sim_burst.simulation_id
605 sngl_burst.event_id == sim_burst_map.event_id
609 """, (self.instrument,)):
610 sim = contents.sim_burst_table.row_from_cols(values)
611 freq_rec, hrss_rec = values[-2:]
618 self.
axes.scatter(self.
x, self.
y, c = self.
c, s = 16)
619 xmin, xmax =
min(self.
x),
max(self.
x)
620 ymin, ymax =
min(self.
y),
max(self.
y)
621 xmin = ymin =
min(xmin, ymin)
622 xmax = ymax =
max(xmax, ymax)
623 self.
axes.
plot([xmin, xmax], [ymin, ymax],
"k-")
624 self.
axes.set_xlim([xmin, xmax])
625 self.
axes.set_ylim([ymin, ymax])
626 self.
axes.set_title(
r"Recovered Frequency vs.\ Injected Frequency (%d Events Matching Injections)" % self.
matches)
631 self.fig, self.
axes = SnglBurstUtils.make_burst_plot(
r"$f_{\mathrm{injected}}$ (Hz)",
r"$f_{\mathrm{recovered}}$ (Hz)")
633 self.fig.set_size_inches(8, 8)
643 for values
in contents.connection.cursor().execute(
"""
646 multi_burst.central_freq,
647 multi_burst.amplitude
650 JOIN sim_coinc_map ON (
651 sim_coinc_map.simulation_id == sim_burst.simulation_id
653 JOIN coinc_event AS sim_coinc_event ON (
654 sim_coinc_event.coinc_event_id == sim_coinc_map.coinc_event_id
656 JOIN multi_burst ON (
657 multi_burst.coinc_event_id == sim_coinc_map.event_id
660 sim_coinc_event.coinc_def_id == ?
661 """, (contents.sce_definer_id,)):
662 sim = contents.sim_burst_table.row_from_cols(values)
663 freq_rec, hrss_rec = values[-2:]
667 self.c.append(math.log(hrss_rec / sim.hrss))
670 self.
axes.scatter(self.
x, self.
y, c = self.
c, s = 16)
671 xmin, xmax =
min(self.
x),
max(self.
x)
672 ymin, ymax =
min(self.
y),
max(self.
y)
673 xmin = ymin =
min(xmin, ymin)
674 xmax = ymax =
max(xmax, ymax)
675 self.
axes.
plot([xmin, xmax], [ymin, ymax],
"k-")
676 self.
axes.set_xlim([xmin, xmax])
677 self.
axes.set_ylim([ymin, ymax])
678 self.
axes.set_title(
r"Recovered Frequency vs.\ Injected Frequency (%d Events Matching Injections)" % self.
matches)
695def new_plots(instrument, amplitude_func, amplitude_lbl, plots):
699 SimBurstUtils.Efficiency_hrss_vs_freq((instrument,), amplitude_func, amplitude_lbl, 0.1),
708 return [l[i]
for i
in plots]
713 SimBurstUtils.Efficiency_hrss_vs_freq(instruments, amplitude_func, amplitude_lbl, 0.1),
716 return [l[i]
for i
in plots]
725if not options.plot
and not options.coinc_plot
or not filenames:
726 print(
"Nothing to do!", file=sys.stderr)
736coincplots =
new_coinc_plots((
"H1",
"H2",
"L1"), options.amplitude_func, options.amplitude_lbl, options.coinc_plot)
738for n, filename
in enumerate(utils.sort_files_by_size(filenames, options.verbose, reverse =
True)):
740 print(
"%d/%d: %s" % (n + 1, len(filenames), filename), file=sys.stderr)
741 working_filename = dbtables.get_connection_filename(filename, tmp_path = options.tmp_space, verbose = options.verbose)
742 database = SnglBurstUtils.CoincDatabase(sqlite3.connect(str(working_filename)), options.live_time_program)
744 SnglBurstUtils.summarize_coinc_database(database)
746 if database.coinc_table
is not None:
747 database.connection.cursor().execute(
"""
752 a.event_id AS simulation_id,
753 a.coinc_event_id AS coinc_event_id,
754 b.event_id AS event_id
757 JOIN coinc_event_map AS b ON (
758 a.table_name == 'sim_burst'
759 AND b.table_name ==
'sngl_burst'
760 AND b.coinc_event_id == a.coinc_event_id
763 for instrument
in database.instruments:
764 if instrument
not in plots:
765 plots[instrument] =
new_plots(instrument, options.amplitude_func, options.amplitude_lbl, options.plot)
766 for n, plot
in zip(options.plot, plots[instrument]):
768 print(
"adding to %s plot %d ..." % (instrument, n), file=sys.stderr)
769 plot.add_contents(database)
770 if options.coinc_plot:
771 database.connection.cursor().execute(
"""
776 a.event_id AS simulation_id,
777 a.coinc_event_id AS coinc_event_id,
778 b.event_id AS event_id
781 JOIN coinc_event_map AS b ON (
782 a.table_name == 'sim_burst'
783 AND b.table_name ==
'coinc_event'
784 AND b.coinc_event_id == a.coinc_event_id
787 for n, plot
in enumerate(coincplots):
789 print(
"adding to coinc plot %d ..." % options.coinc_plot[n], file=sys.stderr)
790 plot.add_contents(database)
791 database.connection.close()
792 dbtables.discard_connection_filename(filename, working_filename, verbose = options.verbose)
801 plots = [plot
for instrument
in plots.keys()
for plot
in plots[instrument]
if isinstance(plot, SimBurstUtils.Efficiency_hrss_vs_freq)]
804 minx =
min([
min(plot.injected_x)
for plot
in plots])
805 maxx =
max([
max(plot.injected_x)
for plot
in plots])
806 miny =
min([
min(plot.injected_y)
for plot
in plots])
807 maxy =
max([
max(plot.injected_y)
for plot
in plots])
808 return rate.NDBins((rate.LogarithmicBins(minx, maxx, 512), rate.LogarithmicBins(miny, maxy, 512)))
820for instrument
in plots:
822 format =
"%%s%s_%%0%dd.%%s" % (instrument, int(math.log10(
max(options.plot)
or 1)) + 1)
823 while len(plots[instrument]):
824 plot = plots[instrument].pop(0)
825 filename = format % (options.base, options.plot[n], options.format)
827 print(
"finishing %s plot %d ..." % (instrument, options.plot[n]), file=sys.stderr)
829 if isinstance(plot, SimBurstUtils.Efficiency_hrss_vs_freq):
830 plot.finish(binning = binning)
831 efficiencies.append(plot)
832 fig = SimBurstUtils.plot_Efficiency_hrss_vs_freq(plot)
836 except ValueError
as e:
837 print(
"can't finish %s plot %d: %s" % (instrument, options.plot[n], str(e)), file=sys.stderr)
840 print(
"writing %s ..." % filename, file=sys.stderr)
841 fig.savefig(filename)
850for n, plot
in enumerate(coincplots):
851 format =
"%%s%s_%%0%dd.%%s" % (
"coinc", int(math.log10(
max(options.coinc_plot)
or 1)) + 1)
852 filename = format % (options.base, options.coinc_plot[n], options.format)
854 print(
"finishing coinc plot %d ..." % options.coinc_plot[n], file=sys.stderr)
856 if isinstance(plot, SimBurstUtils.Efficiency_hrss_vs_freq):
857 plot.finish(binning = binning)
858 fig = SimBurstUtils.plot_Efficiency_hrss_vs_freq(plot)
862 except ValueError
as e:
863 print(
"can't finish coinc plot %d: %s" % (options.coinc_plot[n], str(e)), file=sys.stderr)
866 print(
"writing %s ..." % filename, file=sys.stderr)
867 fig.savefig(filename)
876 fig, axes = SnglBurstUtils.make_burst_plot(
"Frequency (Hz)",
r"$h_{\mathrm{rss}}$")
880 xcoords, ycoords = e.efficiency.centres()
881 zvals = e.efficiency.ratio()
883 for n, e
in enumerate(efficiencies[1:]):
885 other_xcoords, other_ycoords = e.efficiency.centres()
886 if (xcoords != other_xcoords).any()
or (ycoords != other_ycoords).any():
889 raise ValueError(
"binning mismatch")
890 zvals *= e.efficiency.ratio()
891 error /= len(efficiencies)
893 nfound = numpy.array([len(e.found_x)
for e
in efficiencies], dtype =
"double")
894 ninjected = numpy.array([len(e.injected_x)
for e
in efficiencies], dtype =
"double")
905 ninjected_guess = (ninjected / ninjected.max()).prod() * ninjected.min()
912 nfound_guess = (nfound / ninjected).prod() * ninjected_guess
914 ninjected_guess = int(round(ninjected_guess))
915 nfound_guess = int(round(nfound_guess))
917 instruments =
r" \& ".join(sorted(
"+".join(sorted(e.instruments))
for e
in efficiencies))
919 cset = axes.contour(xcoords, ycoords, numpy.transpose(zvals), (.1, .2, .3, .4, .5, .6, .7, .8, .9))
920 cset.clabel(inline =
True, fontsize = 5, fmt =
r"$%%g \pm %g$" % error, colors =
"k")
922 axes.set_title(
r"%s Estimated Injection Detection Efficiency ($\sim$%d of $\sim$%d Found)" % (instruments, nfound_guess, ninjected_guess))
929 print(
"computing theoretical coincident detection efficiency ...", file=sys.stderr)
931 filename =
"%scoincidence.png" % options.base
933 print(
"writing %s ..." % filename, file=sys.stderr)
934 fig.savefig(filename)
static double max(double a, double b)
static double min(double a, double b)
def add_contents(self, contents)
def __init__(self, instruments)
def add_contents(self, contents)
def __init__(self, instrument)
def add_contents(self, contents)
def __init__(self, instrument, interval, width)
def add_contents(self, contents)
def __init__(self, instrument, amplitude_func, amplitude_lbl)
def __init__(self, instrument, interval, width)
def add_contents(self, contents)
def __init__(self, instrument, amplitude_func)
def add_contents(self, contents)
def add_contents(self, contents)
def __init__(self, instrument)
def new_plots(instrument, amplitude_func, amplitude_lbl, plots)
def plot_multi_Efficiency_hrss_vs_freq(efficiencies)
def new_coinc_plots(instruments, amplitude_func, amplitude_lbl, plots)