3 from bisect
import bisect_left, bisect_right
8 from optparse
import OptionParser
14 from lal
import LIGOTimeGPS
15 from lalburst
import burca
16 from lalburst
import offsetvector
17 from lalburst
import snglcoinc
19 from ligo
import segments
20 from ligo.lw
import ligolw
21 from ligo.lw
import lsctables
22 from ligo.lw
import utils
as ligolw_utils
23 from ligo.lw.utils
import process
as ligolw_process
24 from ligo.lw.utils
import time_slide
as ligolw_time_slide
38 "H1": segments.segment(LIGOTimeGPS(1e6), LIGOTimeGPS(1e6 + 300)),
39 "L1": segments.segment(LIGOTimeGPS(1e6), LIGOTimeGPS(1e6 + 300)),
40 "V1": segments.segment(LIGOTimeGPS(1e6), LIGOTimeGPS(1e6 + 300))
42 mean_rates = {
"H1": 1.0,
"L1": math.pi,
"V1": math.e},
45 assert set(mean_rates) == set(segs),
"need rates and segments for the same instruments"
48 xmldoc = ligolw.Document()
49 xmldoc.appendChild(ligolw.LIGO_LW())
50 process = ligolw_process.register_to_xmldoc(xmldoc,
"snglcoinc_coincs_verify", {}, instruments = segs.keys(), comment =
"artificial data for coincidence engine test suite")
53 for i
in range(n_offset_vectors):
54 ligolw_time_slide.get_time_slide_id(xmldoc, offsetvector.offsetvector((instrument, random.uniform(-28. * n_offset_vectors, +28. * n_offset_vectors))
for instrument
in segs), create_new = process)
57 snglbursttable = xmldoc.childNodes[-1].appendChild(lsctables.New(lsctables.SnglBurstTable, [
"event_id",
"ifo",
"peak_time",
"peak_time_ns",
"process:process_id"]))
58 snglbursttable.sync_next_id()
61 for instrument, segment
in segs.items():
62 for i
in range(numpy.random.poisson(mean_rates[instrument] * float(abs(segment)))):
63 snglbursttable.append(snglbursttable.RowType(
64 event_id = snglbursttable.get_next_id(),
66 peak = segment[0] + random.uniform(0., float(abs(segment))),
67 process_id = process.process_id
81 process = ligolw_process.register_to_xmldoc(xmldoc,
"brute_force_coinc", {})
84 coinctables = snglcoinc.CoincTables(xmldoc, burca.StringCuspBBCoincDef)
90 instruments = list(set(row.ifo
for row
in lsctables.SnglBurstTable.get_table(xmldoc)))
91 dt =
dict((frozenset(pair), delta_t + snglcoinc.light_travel_time(*pair))
for pair
in itertools.combinations(instruments, 2))
95 sngls_by_instrument =
dict((instrument, [])
for instrument
in instruments)
96 for row
in lsctables.SnglBurstTable.get_table(xmldoc):
97 sngls_by_instrument[row.ifo].append(row)
98 for instrument
in instruments:
99 sngls_by_instrument[instrument].sort(key =
lambda row: row.peak)
102 for time_slide_id, offsetvector
in lsctables.TimeSlideTable.get_table(xmldoc).as_dict().items():
103 print(
"offsets = %s" % str(offsetvector))
112 for n
in range(len(instruments), min_instruments - 1, -1):
115 for select_instruments
in itertools.combinations(instruments, n):
116 offsets = tuple(offsetvector[instrument]
for instrument
in select_instruments)
117 total = functools.reduce(
lambda a, b: a * b, map(
lambda instrument: len(sngls_by_instrument[instrument]), select_instruments), 1)
120 for sngls
in tqdm(itertools.product(*map(sngls_by_instrument.__getitem__, select_instruments)), total = total, desc =
", ".join(sorted(select_instruments))):
124 if any(abs(t_a - t_b) > dt[frozenset((instrument_a, instrument_b))]
for (instrument_a, t_a), (instrument_b, t_b)
in itertools.combinations(((instrument, sngl.peak + offset)
for instrument, sngl, offset
in zip(select_instruments, sngls, offsets)), 2)):
130 event_ids = frozenset(sngl.event_id
for sngl
in sngls)
131 if event_ids
in exclude:
134 coinctables.append_coinc(*coinctables.coinc_rows(process.process_id, time_slide_id, sngls,
"sngl_burst"))
135 exclude |= {frozenset(x)
for i
in range(n - 1, min_instruments - 1, -1)
for x
in itertools.combinations(event_ids, i)}
138 process.set_end_time_now()
156 self.
timestimes = tuple(map(coincgen_doubles.singlesqueue.event_time, events))
158 def __call__(self, event_a, offset_a, coinc_window):
159 peak = event_a.peak + offset_a
160 return self.
eventsevents[bisect_left(self.
timestimes, peak - coinc_window) : bisect_right(self.
timestimes, peak + coinc_window)]
165 process = ligolw_process.register_to_xmldoc(xmldoc,
"snglcoinc_coinc", {})
168 coinctables = snglcoinc.CoincTables(xmldoc, burca.StringCuspBBCoincDef)
171 time_slide_graph = snglcoinc.TimeSlideGraph(coincgen_doubles, coinctables.time_slide_index, delta_t, min_instruments = min_instruments, verbose =
True)
175 with tqdm(desc =
"snglcoinc", total = len(lsctables.SnglBurstTable.get_table(xmldoc)))
as progress:
176 for instrument, events
in itertools.groupby(sorted(lsctables.SnglBurstTable.get_table(xmldoc), key =
lambda row: (row.peak, row.ifo)),
lambda event: event.ifo):
177 events = tuple(events)
178 progress.update(len(events))
179 if time_slide_graph.push(instrument, events,
max(event.peak
for event
in events)):
180 for node, events
in time_slide_graph.pull():
181 coinctables.append_coinc(*coinctables.coinc_rows(process.process_id, node.time_slide_id, events,
"sngl_burst"))
182 for node, events
in time_slide_graph.pull(flush =
True):
183 coinctables.append_coinc(*coinctables.coinc_rows(process.process_id, node.time_slide_id, events,
"sngl_burst"))
186 process.set_end_time_now()
197 process_id, = lsctables.ProcessTable.get_table(xmldoc).get_ids_by_program(algorithm_name)
199 coinc_def_id = lsctables.CoincDefTable.get_table(xmldoc).get_coinc_def_id(search = burca.StringCuspBBCoincDef.search, search_coinc_type = burca.StringCuspBBCoincDef.search_coinc_type, create_new =
False)
201 self.
snglssngls =
dict((row.event_id, row)
for row
in lsctables.SnglBurstTable.get_table(xmldoc))
202 if len(lsctables.SnglBurstTable.get_table(xmldoc)) - len(self.
snglssngls):
203 raise ValueError(
"document contains %d duplicate sngl_burst rows" % (len(lsctables.SnglBurstTable.get_table(xmldoc)) - len(self.
snglssngls)))
204 self.
coincscoincs =
dict((row.coinc_event_id, row)
for row
in lsctables.CoincTable.get_table(xmldoc)
if row.coinc_def_id == coinc_def_id
and row.process_id == process_id)
205 self.
offsetvectorsoffsetvectors = lsctables.TimeSlideTable.get_table(xmldoc).as_dict()
207 coinc_event_ids = frozenset(self.
coincscoincs)
208 coinc_map = [row
for row
in lsctables.CoincMapTable.get_table(xmldoc)
if row.table_name ==
"sngl_burst" and row.coinc_event_id
in coinc_event_ids]
209 coinc_map.sort(key =
lambda row: row.coinc_event_id)
212 self.
coinc_mapcoinc_map[time_slide_id] =
dict((frozenset(row.event_id
for row
in rows), coinc_event_id)
for coinc_event_id, rows
in itertools.groupby(coinc_map, key =
lambda row: row.coinc_event_id)
if self.
coincscoincs[coinc_event_id].time_slide_id == time_slide_id)
215 return tuple(self.
snglssngls[event_id]
for event_id
in event_ids)
218 offsetvector = self.
offsetvectorsoffsetvectors[time_slide_id]
219 return min(sngl.peak + offsetvector[sngl.ifo]
for sngl
in self.
get_snglsget_sngls(event_ids))
222 offsetvector = self.
offsetvectorsoffsetvectors[time_slide_id]
223 sngls = self.
get_snglsget_sngls(event_ids)
225 for sngl
in sorted(sngls, key =
lambda row: row.ifo):
226 peak_times.append(sngl.peak + offsetvector[sngl.ifo])
227 print(
"\tevent ID %d: %s: %s + %g s = %s" % (sngl.event_id, sngl.ifo, sngl.peak, offsetvector[sngl.ifo], sngl.peak + offsetvector[sngl.ifo]))
228 print(
"\tmax Delta t = %g s" % float(
max(peak_times) -
min(peak_times)))
237 parser = OptionParser(
239 parser.add_option(
"--mode", metavar =
"mode", default =
"test", help =
"Select operating mode. Allowed values are \"initialize\" (generate random test document), \"brute-force\" (apply brute-force algorithm to test document to construct correct-answer document), \"test\" (default; apply snglcoinc algorithm to test document and compare to brute-force result contained in the document).")
240 parser.add_option(
"--delta-t", metavar =
"seconds", type = float, default = 0.015, help =
"Coincidence window (default = 0.015 s).")
241 parser.add_option(
"--min-instruments", metavar =
"count", type = int, default = 1, help =
"Require candidates to have at least this many instruments participating (default = 2).")
242 parser.add_option(
"-v",
"--verbose", action =
"store_true", help =
"Be verbose.")
244 options, filenames = parser.parse_args()
246 if options.mode
not in (
"initialize",
"brute-force",
"test"):
247 raise ValueError(
"invalide --mode %s" % options.mode)
248 if options.delta_t < 0.:
249 raise ValueError(
"--delta-t must be >= 0")
250 if options.min_instruments < 1:
251 raise ValueError(
"--min-instruments must be >= 1")
253 filenames = [os.path.join(os.environ.get(
"LAL_TEST_SRCDIR",
"."),
"snglcoinc_coincs_verify_input.xml.gz")]
254 elif len(filenames) != 1:
255 raise ValueError(
"only exactly one filename may be provided. if no filenames are given, a default will be used.")
257 return options, filenames[0]
263 if options.mode ==
"initialize":
269 ligolw_utils.write_filename(xmldoc, filename, verbose = options.verbose)
271 elif options.mode ==
"brute-force":
277 xmldoc = ligolw_utils.load_filename(filename, contenthandler = LIGOLWContentHandler, verbose = options.verbose)
279 ligolw_utils.write_filename(xmldoc, filename, verbose = options.verbose)
281 elif options.mode ==
"test":
288 xmldoc = ligolw_utils.load_filename(filename, contenthandler = LIGOLWContentHandler, verbose = options.verbose)
289 do_snglcoinc(xmldoc, delta_t = options.delta_t, min_instruments = options.min_instruments)
292 algorithm_names = (
"brute_force_coinc",
"snglcoinc_coinc")
293 summaries = [
summary(xmldoc, algorithm_name)
for algorithm_name
in algorithm_names]
297 if summaries[0].offsetvectors != summaries[1].offsetvectors:
298 raise ValueError(
"documents do not contain identical offset vectors, or their IDs are not equivalent")
302 print(
"\ncoincs in %s that are not in %s:" % algorithm_names)
303 for time_slide_id
in summaries[0].offsetvectors:
304 for n, event_ids
in enumerate(sorted(set(summaries[0].coinc_map[time_slide_id]) - set(summaries[1].coinc_map[time_slide_id]), key =
lambda event_ids: summaries[0].min_time(time_slide_id, event_ids)), start = m):
306 summaries[0].print_summary(time_slide_id, event_ids)
308 print(
"\ncoincs in %s that are not in %s:" % tuple(reversed(algorithm_names)))
309 for time_slide_id
in summaries[0].offsetvectors:
310 for n, event_ids
in enumerate(sorted(set(summaries[1].coinc_map[time_slide_id]) - set(summaries[0].coinc_map[time_slide_id]), key =
lambda event_ids: summaries[1].min_time(time_slide_id, event_ids)), start = m):
312 summaries[1].print_summary(time_slide_id, event_ids)
315 raise ValueError(
"documents do not contain identical candidate sets")
static double max(double a, double b)
static double min(double a, double b)
def __call__(self, event_a, offset_a, coinc_window)
def __init__(self, events)
def __init__(self, xmldoc, algorithm_name)
def min_time(self, time_slide_id, event_ids)
def get_sngls(self, event_ids)
def print_summary(self, time_slide_id, event_ids)
def do_brute_force_coinc(xmldoc, delta_t=0.015, min_instruments=1)
def make_input_test_document(segs={ "H1":segments.segment(LIGOTimeGPS(1e6), LIGOTimeGPS(1e6+300)), "L1":segments.segment(LIGOTimeGPS(1e6), LIGOTimeGPS(1e6+300)), "V1":segments.segment(LIGOTimeGPS(1e6), LIGOTimeGPS(1e6+300)) }, mean_rates={"H1":1.0, "L1":math.pi, "V1":math.e}, n_offset_vectors=3)
def do_snglcoinc(xmldoc, delta_t=0.015, min_instruments=1)