30String cusp search final output rendering tool.
34from __future__
import print_function
42from optparse
import OptionParser
44from matplotlib
import patches
49from scipy
import interpolate
50from scipy
import optimize
56from igwn_ligolw
import dbtables
57from igwn_ligolw.utils
import process
as ligolwprocess
61from lalburst
import git_version
62from lalburst
import packing
63from lalburst
import SimBurstUtils
64from lalburst
import SnglBurstUtils
65from lalburst
import stringutils
66import igwn_segments
as segments
67from igwn_segments
import utils
as segmentsUtils
70SnglBurstUtils.matplotlib.rcParams.update({
73 "axes.titlesize": 10.0,
74 "axes.labelsize": 10.0,
75 "xtick.labelsize": 8.0,
76 "ytick.labelsize": 8.0,
77 "legend.fontsize": 8.0,
82__author__ =
"Kipp Cannon <kipp.cannon@ligo.org>"
83__version__ =
"git id %s" % git_version.id
84__date__ = git_version.date
87copyreg.pickle(lal.LIGOTimeGPS,
lambda gps: (lal.LIGOTimeGPS, (gps.gpsSeconds, gps.gpsNanoSeconds)))
100 parser = OptionParser(
101 version =
"Name: %%prog\n%s" % git_version.verbose_msg,
102 usage =
"%prog [options] [file ...]",
103 description =
"%prog performs the final, summary, stages of the upper-limit string cusp search. Input consists of a list of all sqlite format database files produced by all injection and non-injection runs of the analysis pipeline. The file names can be given on the command line and/or provided in a LAL cache file."
105 parser.add_option(
"--cal-uncertainty", metavar =
"fraction", type =
"float", help =
"Set the fractional uncertainty in amplitude due to calibration uncertainty (eg. 0.08). This option is required, use 0 to disable calibration uncertainty.")
106 parser.add_option(
"--injections-bin-size", metavar =
"bins", type =
"float", default = 16.7, help =
"Set bin width for injection efficiency curves (default = 16.7).")
107 parser.add_option(
"-c",
"--input-cache", metavar =
"filename", action =
"append", help =
"Also process the files named in this LAL cache. See lalapps_path2cache for information on how to produce a LAL cache file. This option can be given multiple times.")
108 parser.add_option(
"--import-dump", metavar =
"filename", action =
"append", help =
"Import additional rate vs. threshold or efficiency data from this dump file. Dump files are one of the data products produced by this program. Whether the file provides rate vs. threshold data or efficiency data will be determined automatically. This option can be given multiple times")
109 parser.add_option(
"--image-formats", metavar =
"ext[,ext,...]", default =
"png,pdf", help =
"Set list of graphics formats to produce by providing a comma-delimited list of the filename extensions (default = \"png,pdf\").")
110 parser.add_option(
"-p",
"--live-time-program", metavar =
"program", default =
"StringSearch", help =
"Set the name, as it appears in the process table, of the program whose search summary entries define the search live time (default = StringSearch).")
111 parser.add_option(
"-o",
"--open-box", action =
"store_true", help =
"Perform open-box analysis. In a closed-box analysis (the default), information about the events seen at zero-lag is concealed: the rate vs. threshold plot only shows the rate of events seen in the background, the detection threshold used to measure the efficiency curves is obtained from n-th loudest background event where n is (the integer closest to) the ratio of background livetime to zero-lag livetime, and messages to stdout and stderr that contain information about event counts at zero-lag are silenced.")
112 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.")
113 parser.add_option(
"--vetoes-name", metavar =
"name", help =
"Set the name of the segment lists to use as vetoes (default = do not apply vetoes).")
114 parser.add_option(
"--detection-threshold", metavar =
"log likelihood ratio", type =
"float", help =
"Override the detection threshold. Only injection files will be processed, and the efficiency curve measured.")
115 parser.add_option(
"--record-background", metavar =
"N", type =
"int", default = 10000000, help =
"Set the number of background log likelihood ratios to hold in memory for producing the rate vs. threshold plot (default = 10000000).")
116 parser.add_option(
"--record-candidates", metavar =
"N", type =
"int", default = 100, help =
"Set the number of highest-ranked zero-lag candidates to dump to the candidate file (default = 100).")
117 parser.add_option(
"--threads", metavar =
"N", type =
"int", default = 1, help =
"Set the maximum number of parallel threads to use for processing files (default = 1). Contention for the global Python interpreter lock will throttle the true number that can run. The number of threads will be automatically adjusted downwards if the number requested exceeds the number of input files.")
118 parser.add_option(
"-v",
"--verbose", action =
"store_true", help =
"Be verbose.")
119 options, filenames = parser.parse_args()
121 if options.cal_uncertainty
is None:
122 raise ValueError(
"must set --cal-uncertainty (use 0 to ignore calibration uncertainty)")
124 options.image_formats = options.image_formats.split(
",")
126 if options.input_cache:
127 filenames += [CacheEntry(line).path
for input_cache
in options.input_cache
for line
in file(input_cache)]
129 if options.threads < 1:
130 raise ValueError(
"--threads must be >= 1")
132 return options, filenames
146 if len(background_x):
147 minX, maxX =
min(
min(zero_lag_x),
min(background_x)),
max(
max(zero_lag_x),
max(background_x))
148 minY, maxY =
min(
min(zero_lag_y),
min(background_y)),
max(
max(zero_lag_y),
max(background_y))
150 minX, maxX =
min(zero_lag_x),
max(zero_lag_x)
151 minY, maxY =
min(zero_lag_y),
max(zero_lag_y)
155 minX, maxX =
min(background_x),
max(background_x)
156 minY, maxY =
min(background_y),
max(background_y)
161 if len(background_x):
162 maxY =
max(zero_lag_y[bisect.bisect_left(zero_lag_x, minX)], background_y[bisect.bisect_left(background_x, minX)])
164 maxY = zero_lag_y[bisect.bisect_left(zero_lag_x, minX)]
166 maxY = background_y[bisect.bisect_left(background_x, minX)]
168 return minX, maxX, minY, maxY
172 if x > background_x[-1]:
174 return background_y[bisect.bisect_left(background_x, x)]
186 mask = numpy.arange(len(x))[::-1]
187 mask = (mask < 10000) | ((mask < 100000) & (mask % 10 == 0)) | (mask % 100 == 0)
189 return x.compress(mask), y.compress(mask), yerr.compress(mask)
193 def __init__(self, open_box, record_background, record_candidates):
221 zero_lag_time_slides, background_time_slides = SnglBurstUtils.get_time_slides(contents.connection)
222 assert len(zero_lag_time_slides) == 1
228 seglists = contents.seglists - contents.vetoseglists
229 self.
zero_lag_time += stringutils.time_slides_livetime(seglists, zero_lag_time_slides.values(), 2, clip = contents.coincidence_segments)
230 self.
background_time += stringutils.time_slides_livetime(seglists, background_time_slides.values(), 2, clip = contents.coincidence_segments)
231 if set((
"H1",
"H2")).issubset(set(contents.seglists)):
234 self.
zero_lag_time -= stringutils.time_slides_livetime_for_instrument_combo(seglists, zero_lag_time_slides.values(), (
"H1",
"H2"), clip = contents.coincidence_segments)
235 self.
background_time -= stringutils.time_slides_livetime_for_instrument_combo(seglists, background_time_slides.values(), (
"H1",
"H2"), clip = contents.coincidence_segments)
241 for ln_likelihood_ratio, instruments, coinc_event_id, peak_time, is_background
in contents.connection.cursor().execute(
"""
243 coinc_event.likelihood,
244 coinc_event.instruments,
245 coinc_event.coinc_event_id,
248 AVG(sngl_burst.peak_time) + 1e-9 * AVG(sngl_burst.peak_time_ns)
251 JOIN coinc_event_map ON (
252 coinc_event_map.coinc_event_id == coinc_event.coinc_event_id
253 AND coinc_event_map.table_name == 'sngl_burst'
254 AND coinc_event_map.event_id == sngl_burst.event_id
263 time_slide.time_slide_id == coinc_event.time_slide_id
264 AND time_slide.offset != 0
269 coinc_event.coinc_def_id == ?
270 """, (contents.bb_definer_id,)):
273 record = (ln_likelihood_ratio, contents.filename, coinc_event_id, dbtables.lsctables.instrumentsproperty.get(instruments), peak_time)
274 if ln_likelihood_ratio
is None:
282 heapq.heappush(self.
background, ln_likelihood_ratio)
284 heapq.heappushpop(self.
background, ln_likelihood_ratio)
291 self.
zero_lag.append(ln_likelihood_ratio)
306 f =
file(
"string_most_significant_background.txt",
"w")
307 print(
"Highest-Ranked Background Events", file=f)
308 print(
"================================", file=f)
311 print(
"%s in %s:" % (str(coinc_event_id), filename), file=f)
312 print(
"Recovered in: %s" %
", ".join(sorted(instruments
or [])), file=f)
313 print(
"Mean peak time: %.16g s GPS" % peak_time, file=f)
314 print(
"\\log \\Lambda: %.16g" % ln_likelihood_ratio, file=f)
316 f =
file(
"string_candidates.txt",
"w")
317 print(
"Highest-Ranked Zero-Lag Events", file=f)
318 print(
"==============================", file=f)
320 for ln_likelihood_ratio, filename, coinc_event_id, instruments, peak_time
in self.
candidates:
322 print(
"%s in %s:" % (str(coinc_event_id), filename), file=f)
323 print(
"Recovered in: %s" %
", ".join(sorted(instruments
or [])), file=f)
324 print(
"Mean peak time: %.16g s GPS" % peak_time, file=f)
325 print(
"\\log \\Lambda: %.16g" % ln_likelihood_ratio, file=f)
328 print(
"List suppressed: box is closed", file=f)
337 background_x = numpy.array(self.
background, dtype =
"double")
346 background_yerr = numpy.sqrt(background_y)
349 zero_lag_y = numpy.arange(len(self.
zero_lag), 0.0, -1.0, dtype =
"double")
352 zero_lag_residual = numpy.zeros((len(self.
zero_lag),), dtype =
"double")
353 for i
in xrange(len(self.
zero_lag)):
355 zero_lag_residual[i] = (zero_lag_y[i] - n) / math.sqrt(n)
381 numpy.savetxt(
'string_rate_background.txt',numpy.transpose((background_x,background_y,background_yerr)))
387 ratefig, axes = SnglBurstUtils.make_burst_plot(
r"Ranking Statistic Threshold, $\log \Lambda$",
"Event Rate (Hz)", width = 108.0)
389 axes.set_position([0.125, 0.15, 0.83, 0.75])
390 axes.xaxis.grid(
True, which =
"major,minor")
391 axes.yaxis.grid(
True, which =
"major,minor")
393 axes.set_title(
r"Event Rate vs.\ Ranking Statistic Threshold")
395 axes.set_title(
r"Event Rate vs.\ Ranking Statistic Threshold (Closed Box)")
402 poly_x = numpy.concatenate((background_x, background_x[::-1]))
403 poly_y = numpy.concatenate((background_y + 1 * background_yerr, (background_y - 1 * background_yerr)[::-1]))
404 axes.add_patch(patches.Polygon(zip(poly_x, numpy.clip(poly_y, minY, maxY)), edgecolor =
"k", facecolor =
"k", alpha = 0.3))
405 line1, = axes.semilogy(background_x.repeat(2)[:-1], background_y.repeat(2)[1:], color =
"k", linestyle =
"--")
407 line2, = axes.semilogy(self.
zero_lag.repeat(2)[:-1], zero_lag_y.repeat(2)[1:], color =
"k", linestyle =
"-", linewidth = 2)
408 axes.legend((line1, line2), (
r"Expected background",
r"Zero-lag"), loc =
"lower left")
410 axes.legend((line1,), (
r"Expected background",), loc =
"lower left")
412 axes.set_xlim((minX, maxX))
413 axes.set_ylim((minY, maxY))
419 residualfig, axes = SnglBurstUtils.make_burst_plot(
r"Ranking Statistic Threshold, $\log \Lambda$",
r"Event Count Residual / $\sqrt{N}$", width = 108.0)
420 axes.set_position([0.125, 0.15, 0.83, 0.75])
421 axes.xaxis.grid(
True, which =
"major,minor")
422 axes.yaxis.grid(
True, which =
"major,minor")
424 axes.set_title(
r"Event Count Residual vs.\ Ranking Statistic Threshold")
426 axes.set_title(
r"Event Count Residual vs.\ Ranking Statistic Threshold (Closed Box)")
428 axes.add_patch(patches.Polygon(((minX, -1), (maxX, -1), (maxX, +1), (minX, +1)), edgecolor =
"k", facecolor =
"k", alpha = 0.3))
430 line1, = axes.plot(self.
zero_lag, zero_lag_residual, color =
"k", linestyle =
"-", linewidth = 2)
432 axes.set_xlim((minX, maxX))
438 return ratefig, residualfig
452 From the x and y arrays, compute the slope at the x co-ordinates
453 using a first-order finite difference approximation.
455 slope = numpy.zeros((len(x),), dtype =
"double")
456 slope[0] = (y[1] - y[0]) / (x[1] - x[0])
457 for i
in xrange(1, len(x) - 1):
458 slope[i] = (y[i + 1] - y[i - 1]) / (x[i + 1] - x[i - 1])
459 slope[-1] = (y[-1] - y[-2]) / (x[-1] - x[-2])
466 upper = numpy.zeros((len(yerr),), dtype =
"double")
467 for i
in xrange(len(yerr)):
468 upper[i] =
max(z[
max(i - deltax, 0) :
min(i + deltax, len(z))])
475 lower = numpy.zeros((len(yerr),), dtype =
"double")
476 for i
in xrange(len(yerr)):
477 lower[i] =
min(z[
max(i - deltax, 0) :
min(i + deltax, len(z))])
482 print(
"# A e D[e]", file=fileobj)
483 for A, e, De
in zip(bins.centres()[0], eff, yerr):
484 print(
"%.16g %.16g %.16g" % (A, e, De), file=fileobj)
487def render_data_from_bins(dump_file, axes, efficiency_num, efficiency_den, cal_uncertainty, filter_width, colour = "k", erroralpha = 0.3, linestyle = "-"):
490 (x,) = efficiency_den.centres()
491 x_factor_per_sample = efficiency_den.bins[0].delta
497 eff = efficiency_num.array / efficiency_den.array
498 dydx =
slope(numpy.arange(len(x), dtype =
"double"), eff)
499 yerr = numpy.sqrt(eff * (1. - eff) / efficiency_den.array)
500 xerr = numpy.array([filter_width / 2.] * len(yerr))
507 net_yerr = numpy.sqrt((xerr * dydx)**2. + yerr**2. + (cal_uncertainty / x_factor_per_sample * dydx)**2.)
511 net_xerr = net_yerr / dydx * x_factor_per_sample
517 patch = patches.Polygon(zip(numpy.concatenate((x, x[::-1])), numpy.concatenate((eff +
upper_err(eff, yerr, filter_width / 2.), (eff -
lower_err(eff, yerr, filter_width / 2.))[::-1]))), edgecolor = colour, facecolor = colour, alpha = erroralpha)
518 axes.add_patch(patch)
519 line, = axes.plot(x, eff, colour + linestyle)
522 A50 = optimize.bisect(interpolate.interp1d(x, eff - 0.5), x[0], x[-1], xtol = 1e-40)
523 A50_err = interpolate.interp1d(x, net_xerr)(A50)
529 num_injections = efficiency_den.array.sum()
530 num_samples = len(efficiency_den.array)
531 print(
"Bins were %g samples wide, ideal would have been %g" % (filter_width, (num_samples / num_injections / interpolate.interp1d(x, dydx)(A50)**2.0)**(1.0/3.0)), file=sys.stderr)
532 print(
"Average number of injections in each bin = %g" % efficiency_den.array.mean(), file=sys.stderr)
534 return line, A50, A50_err
538 def __init__(self, detection_threshold, cal_uncertainty, filter_width, open_box):
553 assert other.open_box == self.
open_box
556 self.
found += other.found
559 self.
all += other.all
569 seglists = contents.seglists - contents.vetoseglists
570 if set((
"H1",
"H2")).issubset(set(seglists)):
573 seglists -= segments.segmentlistdict.fromkeys(seglists, seglists.intersection((
"H1",
"H2")) - seglists.union(set(seglists) - set((
"H1",
"H2"))))
579 offsetvectors = contents.time_slide_table.as_dict()
580 stringutils.create_recovered_ln_likelihood_ratio_table(contents.connection, contents.bb_definer_id)
581 for values
in contents.connection.cursor().execute(
"""
584 recovered_ln_likelihood_ratio.ln_likelihood_ratio
587 LEFT JOIN recovered_ln_likelihood_ratio ON (
588 recovered_ln_likelihood_ratio.simulation_id == sim_burst.simulation_id
591 sim = contents.sim_burst_table.row_from_cols(values[:-1])
592 ln_likelihood_ratio = values[-1]
593 found = ln_likelihood_ratio is not None
596 if len(SimBurstUtils.on_instruments(sim, seglists, offsetvectors[sim.time_slide_id])) >= 2:
600 self.
found.append(sim)
603 record = (1.0 / sim.amplitude, sim, offsetvectors[sim.time_slide_id], contents.filename, ln_likelihood_ratio)
611 record = (sim.amplitude, sim, offsetvectors[sim.time_slide_id], contents.filename, ln_likelihood_ratio)
618 print(
"%s: odd, injection %s was found but not injected ..." % (contents.filename, sim.simulation_id), file=sys.stderr)
621 fig, axes = SnglBurstUtils.make_burst_plot(
r"Injection Amplitude (\(\mathrm{s}^{-\frac{1}{3}}\))",
"Detection Efficiency", width = 108.0)
622 axes.set_title(
r"Detection Efficiency vs.\ Amplitude")
624 axes.set_position([0.10, 0.150, 0.86, 0.77])
627 axes.set_yticks((0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0))
628 axes.set_yticklabels((
r"\(0\)",
r"\(0.1\)",
r"\(0.2\)",
r"\(0.3\)",
r"\(0.4\)",
r"\(0.5\)",
r"\(0.6\)",
r"\(0.7\)",
r"\(0.8\)",
r"\(0.9\)",
r"\(1.0\)"))
629 axes.xaxis.grid(
True, which =
"major,minor")
630 axes.yaxis.grid(
True, which =
"major,minor")
634 bins = rate.NDBins((rate.LogarithmicBins(
min(sim.amplitude
for sim
in self.
all),
max(sim.amplitude
for sim
in self.
all), 400),))
635 efficiency_num = rate.BinnedArray(bins)
636 efficiency_den = rate.BinnedArray(bins)
637 for sim
in self.
found:
638 efficiency_num[sim.amplitude,] += 1
640 efficiency_den[sim.amplitude,] += 1
651 windowfunc /= windowfunc[len(windowfunc) / 2 + 1]
652 rate.filter_array(efficiency_num.array, windowfunc)
653 rate.filter_array(efficiency_den.array, windowfunc)
657 assert (efficiency_num.array <= efficiency_den.array).
all()
658 efficiency_den.array[(efficiency_num.array == 0) & (efficiency_den.array == 0)] = 1
660 line1, A50, A50_err =
render_data_from_bins(
file(
"string_efficiency.dat",
"w"), axes, efficiency_num, efficiency_den, self.
cal_uncertainty, self.
filter_width, colour =
"k", linestyle =
"-", erroralpha = 0.2)
661 print(
"Pipeline's 50%% efficiency point for all detections = %g +/- %g%%\n" % (A50, A50_err * 100), file=sys.stderr)
664 axes.legend((line1,), (
r"\noindent Injections recovered with $\log \Lambda > %.2f$" % self.
detection_threshold,), loc =
"lower right")
667 axes.set_xlim([3e-22, 3e-19])
668 axes.set_ylim([0.0, 1.0])
678 f =
file(
"string_loud_missed_injections.txt",
"w")
679 print(
"Highest Amplitude Missed Injections", file=f)
680 print(
"===================================", file=f)
681 for amplitude, sim, offsetvector, filename, ln_likelihood_ratio
in self.
loudest_missed:
683 print(
"%s in %s:" % (str(sim.simulation_id), filename), file=f)
684 if ln_likelihood_ratio
is None:
685 print(
"Not recovered", file=f)
687 print(
"Recovered with \\log \\Lambda = %.16g, detection threshold was %.16g" % (ln_likelihood_ratio, self.
detection_threshold), file=f)
689 print(
"In %s:" % instrument, file=f)
690 print(
"\tInjected amplitude:\t%.16g" % SimBurstUtils.string_amplitude_in_instrument(sim, instrument, offsetvector), file=f)
691 print(
"\tTime of injection:\t%s s" % sim.time_at_instrument(instrument, offsetvector), file=f)
692 print(
"Amplitude in waveframe:\t%.16g" % sim.amplitude, file=f)
693 t = sim.get_time_geocent()
694 print(
"Time at geocentre:\t%s s" % t, file=f)
695 print(
"Segments within 60 seconds:\t%s" % segmentsUtils.segmentlistdict_to_short_string(self.
seglists & segments.segmentlistdict((instrument, segments.segmentlist([segments.segment(t-offsetvector[instrument]-60, t-offsetvector[instrument]+60)]))
for instrument
in self.
seglists)), file=f)
696 print(
"Vetoes within 60 seconds:\t%s" % segmentsUtils.segmentlistdict_to_short_string(self.
vetoseglists & segments.segmentlistdict((instrument, segments.segmentlist([segments.segment(t-offsetvector[instrument]-60, t-offsetvector[instrument]+60)]))
for instrument
in self.
vetoseglists)), file=f)
698 f =
file(
"string_quiet_found_injections.txt",
"w")
699 print(
"Lowest Amplitude Found Injections", file=f)
700 print(
"=================================", file=f)
701 for inv_amplitude, sim, offsetvector, filename, ln_likelihood_ratio
in self.
quietest_found:
703 print(
"%s in %s:" % (str(sim.simulation_id), filename), file=f)
704 if ln_likelihood_ratio
is None:
705 print(
"Not recovered", file=f)
707 print(
"Recovered with \\log \\Lambda = %.16g, detection threshold was %.16g" % (ln_likelihood_ratio, self.
detection_threshold), file=f)
709 print(
"In %s:" % instrument, file=f)
710 print(
"\tInjected amplitude:\t%.16g" % SimBurstUtils.string_amplitude_in_instrument(sim, instrument, offsetvector), file=f)
711 print(
"\tTime of injection:\t%s s" % sim.time_at_instrument(instrument, offsetvector), file=f)
712 print(
"Amplitude in waveframe:\t%.16g" % sim.amplitude, file=f)
713 t = sim.get_time_geocent()
714 print(
"Time at geocentre:\t%s s" % t, file=f)
715 print(
"Segments within 60 seconds:\t%s" % segmentsUtils.segmentlistdict_to_short_string(self.
seglists & segments.segmentlistdict((instrument, segments.segmentlist([segments.segment(t-offsetvector[instrument]-60, t-offsetvector[instrument]+60)]))
for instrument
in self.
seglists)), file=f)
716 print(
"Vetoes within 60 seconds:\t%s" % segmentsUtils.segmentlistdict_to_short_string(self.
vetoseglists & segments.segmentlistdict((instrument, segments.segmentlist([segments.segment(t-offsetvector[instrument]-60, t-offsetvector[instrument]+60)]))
for instrument
in self.
vetoseglists)), file=f)
736 injection_filenames = []
737 noninjection_filenames = []
738 for n, filename
in enumerate(filenames):
740 print(
"%d/%d: %s" % (n + 1, len(filenames), filename), file=sys.stderr)
741 connection = sqlite3.connect(filename)
742 if "sim_burst" in dbtables.get_table_names(connection):
744 print(
"\t--> injections", file=sys.stderr)
745 injection_filenames.append(filename)
748 print(
"\t--> non-injections", file=sys.stderr)
749 noninjection_filenames.append(filename)
751 return injection_filenames, noninjection_filenames
755 bins = packing.BiggestIntoEmptiest([packing.Bin()
for n
in range(n_threads)])
756 bins.packlist((os.stat(filename).st_size, filename)
for filename
in filenames)
757 return [bin.objects
for bin
in bins.bins]
761 rate_vs_threshold =
None
763 for filename
in filenames:
765 print(
"\t%s ..." % filename, end=
' ', file=sys.stderr)
766 dump = pickle.load(open(filename))
767 if type(dump)
is RateVsThreshold:
769 print(
"found rate vs. threshold data", file=sys.stderr)
770 if rate_vs_threshold
is None:
771 rate_vs_threshold = dump
773 rate_vs_threshold += dump
774 elif type(dump)
is Efficiency:
776 print(
"found efficiency data", file=sys.stderr)
777 if efficiency
is None:
782 raise ValueError(
"cannot determine contents of %s" % filename)
783 return rate_vs_threshold, efficiency
786def process_file(filename, products, live_time_program, tmp_path = None, veto_segments_name = None, verbose = False):
791 working_filename = dbtables.get_connection_filename(filename, tmp_path = tmp_path, verbose = verbose)
792 contents = SnglBurstUtils.CoincDatabase(sqlite3.connect(str(working_filename)), live_time_program, search =
"StringCusp", veto_segments_name = veto_segments_name)
794 SnglBurstUtils.summarize_coinc_database(contents, filename = working_filename)
805 contents.filename = filename
807 contents.coincidence_segments = ligolwprocess.get_process_params(contents.xmldoc,
"lalburst_coinc",
"--coincidence-segments")
808 if contents.coincidence_segments:
811 contents.coincidence_segments, = contents.coincidence_segments
813 contents.coincidence_segments = contents.coincidence_segments.encode(
'utf-8')
814 contents.coincidence_segments = segments.segmentlistdict.fromkeys(contents.seglists, segmentsUtils.from_range_strings(contents.coincidence_segments.split(
","), boundtype = dbtables.lsctables.LIGOTimeGPS).coalesce())
816 contents.coincidence_segments =
None
822 for n, product
in enumerate(products):
824 print(
"%s: adding to product %d ..." % (working_filename, n), file=sys.stderr)
825 product.add_contents(contents, verbose = verbose)
831 contents.connection.close()
832 dbtables.discard_connection_filename(filename, working_filename, verbose = verbose)
835def process_files(filenames, products, live_time_program, tmp_path = None, veto_segments_name = None, verbose = False):
836 for n, filename
in enumerate(filenames):
838 print(
"%d/%d: %s" % (n + 1, len(filenames), filename), file=sys.stderr)
839 process_file(filename, products, live_time_program, tmp_path = tmp_path, veto_segments_name = veto_segments_name, verbose = verbose)
843 format =
"%%s%%0%dd%%s.%%s" % (int(math.log10(
max(len(products) - 1, 1))) + 1)
847 print(
"finishing product %d ..." % (n - 1), file=sys.stderr)
848 product = products.pop(0)
850 filename =
"%sdump_%d.pickle" % (prefix, n)
852 print(
"\twriting %s ..." % filename, end=
' ', file=sys.stderr)
853 pickle.dump(product, open(filename,
"w"))
855 print(
"done", file=sys.stderr)
857 for m, fig
in enumerate(product.finish()):
858 for ext
in image_formats:
859 filename = format % (prefix, n, chr(m + 97), ext)
861 print(
"\twriting %s ..." % filename, end=
' ', file=sys.stderr)
862 fig.savefig(filename)
864 print(
"done", file=sys.stderr)
871print(
"""Command line:
874""" %
" ".join(sys.argv), file=sys.stderr)
878---=== !! BOX IS OPEN !! ===---
880PRESS CTRL-C SOON IF YOU DIDN'T MEAN TO OPEN THE BOX
891 print(
"Identifying injection and non-injection databases ...", file=sys.stderr)
892injection_filenames, noninjection_filenames =
group_files(filenames, verbose = options.verbose)
900if options.import_dump:
902 print(
"Loading dump files ...", file=sys.stderr)
903 rate_vs_threshold, efficiency =
import_dumps(options.import_dump, verbose = options.verbose)
905 if rate_vs_threshold
is not None:
906 rate_vs_threshold.open_box = options.open_box
907 if efficiency
is not None and options.open_box
and not efficiency.open_box:
908 raise ValueError(
"Box is open but one or more imjported efficiency dump file was generated in closed-box mode. Efficiency must be re-measured in open-box mode to use correct detection threshold.")
910 rate_vs_threshold, efficiency =
None,
None
918if options.detection_threshold
is None:
920 print(
"Collecting background and zero-lag statistics ...", file=sys.stderr)
923 rate_vs_thresholds = []
926 for filenames
in pack_files(noninjection_filenames,
min(options.threads, len(noninjection_filenames)), verbose = options.verbose):
929 random.shuffle(filenames)
932 r, w = os.fdopen(r,
"r", 0), os.fdopen(w,
"w", 0)
939 rate_vs_threshold =
RateVsThreshold(options.open_box, record_background = options.record_background, record_candidates = options.record_candidates)
940 process_files(filenames, [rate_vs_threshold], options.live_time_program, tmp_path = options.tmp_space, veto_segments_name = options.vetoes_name, verbose = options.verbose)
941 pickle.dump(rate_vs_threshold, w)
943 pickle.dump(traceback.format_exc(), w)
954 for r
in select.select(children.keys(), [], [])[0]:
955 process_output = pickle.load(r)
957 pid, exit_status = os.waitpid(children.pop(r), 0)
958 if isinstance(process_output, RateVsThreshold):
959 if rate_vs_threshold
is None:
960 rate_vs_threshold = process_output
962 rate_vs_threshold += process_output
964 print(process_output, file=sys.stderr)
967 sys.exit(exit_status)
968 if rate_vs_threshold
is None:
969 raise ValueError(
"no non-injection data available: cannot determine detection threshold. provide non-injection data or set an explicit detection treshold. Consult --help for more information.")
972 write_products([rate_vs_threshold],
"string_rate_", options.image_formats, verbose = options.verbose)
977 print(
"Zero-lag events: %d" % len(rate_vs_threshold.zero_lag), file=sys.stderr)
978 except OverflowError:
981 print(
"Zero-lag events: %d" % rate_vs_threshold.zero_lag.n, file=sys.stderr)
982 print(
"Total time in zero-lag segments: %s s" % str(rate_vs_threshold.zero_lag_time), file=sys.stderr)
983 print(
"Time-slide events: %d" % rate_vs_threshold.n_background, file=sys.stderr)
984 print(
"Total time in time-slide segments: %s s" % str(rate_vs_threshold.background_time), file=sys.stderr)
986 detection_threshold = rate_vs_threshold.zero_lag[-1]
987 print(
"Likelihood ratio for highest-ranked zero-lag survivor: %.9g" % detection_threshold, file=sys.stderr)
996 detection_threshold = sorted(rate_vs_threshold.background)[-int(round(rate_vs_threshold.background_time / rate_vs_threshold.zero_lag_time))]
997 print(
"Simulated \\log \\Lambda for highest-ranked zero-lag survivor: %.9g" % detection_threshold, file=sys.stderr)
999 detection_threshold = options.detection_threshold
1000 print(
"Likelihood ratio for highest-ranked zero-lag survivor from command line: %.9g" % detection_threshold, file=sys.stderr)
1010 print(
"Collecting efficiency statistics ...", file=sys.stderr)
1014for filenames
in pack_files(injection_filenames,
min(options.threads, len(injection_filenames)), verbose = options.verbose):
1017 random.shuffle(filenames)
1020 r, w = os.fdopen(r,
"r", 0), os.fdopen(w,
"w", 0)
1027 efficiency =
Efficiency(detection_threshold, options.cal_uncertainty, options.injections_bin_size, options.open_box)
1028 process_files(filenames, [efficiency], options.live_time_program, tmp_path = options.tmp_space, veto_segments_name = options.vetoes_name, verbose = options.verbose)
1029 pickle.dump(efficiency, w)
1031 pickle.dump(traceback.format_exc(), w)
1042 for r
in select.select(children.keys(), [], [])[0]:
1043 process_output = pickle.load(r)
1045 pid, exit_status = os.waitpid(children.pop(r), 0)
1046 if isinstance(process_output, Efficiency):
1047 if efficiency
is None:
1048 efficiency = process_output
1050 efficiency += process_output
1052 print(process_output, file=sys.stderr)
1055 sys.exit(exit_status)
1057if efficiency
is not None:
1058 write_products([efficiency],
"string_efficiency_", options.image_formats, verbose = options.verbose)
1061 print(
"no injection data available, not writing efficiency data products.", file=sys.stderr)
1064 print(
"done.", file=sys.stderr)
def __init__(self, detection_threshold, cal_uncertainty, filter_width, open_box)
def add_contents(self, contents, verbose=False)
def __iadd__(self, other)
def __init__(self, open_box, record_background, record_candidates)
def __iadd__(self, other)
def add_contents(self, contents, verbose=False)
most_significant_background
def group_files(filenames, verbose=False)
def process_files(filenames, products, live_time_program, tmp_path=None, veto_segments_name=None, verbose=False)
def upper_err(y, yerr, deltax)
def expected_count(x, background_x, background_y)
def process_file(filename, products, live_time_program, tmp_path=None, veto_segments_name=None, verbose=False)
def compress_ratevsthresh_curve(x, y, yerr)
def slope(x, y)
From the x and y arrays, compute the slope at the x co-ordinates using a first-order finite differenc...
def ratevsthresh_bounds(background_x, background_y, zero_lag_x, zero_lag_y)
def write_efficiency(fileobj, bins, eff, yerr)
def render_data_from_bins(dump_file, axes, efficiency_num, efficiency_den, cal_uncertainty, filter_width, colour="k", erroralpha=0.3, linestyle="-")
def write_products(products, prefix, image_formats, verbose=False)
def lower_err(y, yerr, deltax)
def import_dumps(filenames, verbose=False)
def pack_files(filenames, n_threads, verbose=False)