1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 """
24 Convert a ROOT file produced by cWB into a ligolw document.
25 """
26
27 import sys
28 import os
29 import platform
30 import re
31
32
33 import glue
34
35 from glue import segments
36 from glue.ligolw import ligolw
37 from glue.ligolw import lsctables
38 from glue.ligolw import table
39 from glue.ligolw import types
40 from glue.ligolw import utils
41 from glue.ligolw import ilwd
42 from glue.ligolw.utils import time_slide
43
44 from glue.lal import LIGOTimeGPS
45 from glue.lal import CacheEntry
46 from lalburst import timeslides as ligolw_tisi
47 from pylal import llwapp
48 from pylal import git_version
49
50
51
52
53
54
55
56
57 try:
58 from ROOT import TFile, TChain, TTree
59 from ROOT import gDirectory
60 except ImportError:
61 print >>sys.stderr, "WARNING: Unable to import modules from ROOT. ROOT file processing will not be possible."
62
63
64 __author__ = "Chris Pankow <chris.pankow@ligo.org>"
65 __version__ = "git id %s" % git_version.id
66 __date__ = git_version.date
67
68
69
70
71
72
73
74
75
77 """
78 Turn a ROOT TBranch into a python list
79 """
80
81 list = []
82 for i in range(0, len):
83 list.append( branch[i] )
84
85 return list
86
88 """
89 Index map copied from detector definitions in WaveBurst. Constructs a string with all relevant detector strings from a set of indexes given.
90 """
91
92 if not isinstance(indx, list):
93 indx = [indx]
94
95 ifolist = []
96 for i in indx :
97 if i == 1 : ifolist.append("L1")
98 if i == 2 : ifolist.append("H1")
99 if i == 3 : ifolist.append("H2")
100 if i == 4 : ifolist.append("G1")
101 if i == 5 : ifolist.append("T1")
102 if i == 6 : ifolist.append("V1")
103 if i == 7 : ifolist.append("A1")
104
105 if len(ifolist) == 0 : return None
106 if len(ifolist) == 1 : return ifolist[0]
107 return ifolist
108
109
110
111
112
113
114
115
116
118 """
119 Class to convert a set of rootfiles to a ligolw_document.
120 """
121
122 - def __init__(self, joblist=None, start=None, end=None, instruments=None,
123
124 waveoffset=0, verbose=False):
125 self.job_list = joblist
126 self.start = start
127 self.end = end
128
129 self.verbose = verbose
130 self.instruments = lsctables.ifos_from_instrument_set( instruments.split(",") )
131 self.waveoffset = waveoffset
132
134 """
135 Sets up table structures and calls populating methods.
136 """
137
138 if os.path.splitext(rootfiles[0])[1] == ".root":
139 sim_tree = TChain("waveburst")
140 else:
141 sim_tree = CWBTextConverter()
142
143 for rootfile in rootfiles:
144 sim_tree.Add(rootfile)
145
146
147 sngl_burst_table = lsctables.New(lsctables.SnglBurstTable,
148 ["peak_time_ns", "start_time_ns", "stop_time_ns",
149 "process_id", "ifo", "peak_time", "start_time", "stop_time",
150 "duration", "time_lag", "peak_frequency", "search",
151 "flow", "fhigh", "bandwidth", "tfvolume", "hrss", "event_id", "snr"])
152 xmldoc.childNodes[0].appendChild(sngl_burst_table)
153 sngl_burst_table.sync_next_id()
154
155 coinc_event_table = lsctables.New(lsctables.CoincTable,
156 [ "process_id", "coinc_event_id", "nevents", "instruments", "time_slide_id",
157 "coinc_def_id", "likelihood"])
158 xmldoc.childNodes[0].appendChild(coinc_event_table)
159 coinc_event_table.sync_next_id()
160
161
162
163
164
165
166
167
168
169
170
171 multi_burst_table = lsctables.New(lsctables.MultiBurstTable,
172 ["process_id", "peak_time", "peak_time_ns", "coinc_event_id", "snr", "ifos",
173
174 "false_alarm_rate", "ligo_axis_ra", "ligo_axis_dec"])
175 xmldoc.childNodes[0].appendChild(multi_burst_table)
176
177 coinc_event_map_table = lsctables.New(lsctables.CoincMapTable)
178 xmldoc.childNodes[0].appendChild(coinc_event_map_table)
179
180 jobsegment = None
181 if self.start and self.end :
182 jobsegment = segments.segment(LIGOTimeGPS(self.start), LIGOTimeGPS(self.end))
183
184 if self.verbose:
185 print "Creating Process Table...",
186
187 if self.job_list:
188 self.do_process_table(xmldoc, sim_tree)
189 else :
190 self.do_process_table_from_segment(xmldoc, sim_tree, jobsegment)
191
192 process_index = dict((int(row.process_id), row) for row in lsctables.ProcessTable.get_table(xmldoc))
193
194 if self.verbose:
195 print " done."
196
197 if self.verbose:
198 print "Creating Summary Table...",
199
200 if self.job_list :
201 self.do_summary_table_from_joblist(xmldoc, sim_tree)
202 elif self.job_list == None and self.start and self.end :
203 self.do_summary_table_from_segment(xmldoc, jobsegment, sim_tree)
204 else :
205 self.do_summary_table(xmldoc, sim_tree)
206 if self.verbose:
207 print " done."
208
209
210 row = self.get_coinc_def_row(sim_tree)
211 coinc_def_id = llwapp.get_coinc_def_id(xmldoc, row.search, row.search_coinc_type, description = row.description)
212
213 entries = sim_tree.GetEntries()
214 for i in range(0, entries):
215 sim_tree.GetEntry(i)
216 if self.start != None :
217 if float(self.start) > sim_tree.start[0] : continue
218 if self.end != None :
219 if float(self.end) < sim_tree.stop[0] : continue
220
221
222 offset_vector = dict((get_ifos_from_index(instrument_index), offset) for instrument_index, offset in zip(sim_tree.ifo, sim_tree.lag))
223
224 coinc_event = coinc_event_table.RowType()
225 coinc_event.process_id = process_index[sim_tree.run].process_id
226 coinc_event.coinc_event_id = coinc_event_table.get_next_id()
227 coinc_event.coinc_def_id = coinc_def_id
228 coinc_event.nevents = sim_tree.ndim
229 coinc_event.instruments = lsctables.ifos_from_instrument_set( get_ifos_from_index( branch_array_to_list ( sim_tree.ifo, sim_tree.ndim ) ) )
230 coinc_event.time_slide_id = time_slide.get_time_slide_id(xmldoc, offset_vector, process_index[sim_tree.run])
231 coinc_event.likelihood = sim_tree.likelihood
232 coinc_event_table.append(coinc_event)
233
234 for d in range(0, sim_tree.ndim):
235 sngl_burst = self.get_sngl_burst_row(sngl_burst_table, sim_tree, d)
236 sngl_burst.process_id = coinc_event.process_id
237 sngl_burst.event_id = sngl_burst_table.get_next_id()
238 sngl_burst_table.append(sngl_burst)
239
240 coinc_event_map = coinc_event_map_table.RowType()
241 coinc_event_map.event_id = sngl_burst.event_id
242 coinc_event_map.table_name = sngl_burst.event_id.table_name
243 coinc_event_map.coinc_event_id = coinc_event.coinc_event_id
244 coinc_event_map_table.append(coinc_event_map)
245
246
247
248
249
250
251
252
253
254 multi_burst = self.get_multi_burst_row(multi_burst_table, sim_tree)
255 multi_burst.process_id = coinc_event.process_id
256 multi_burst.coinc_event_id = coinc_event.coinc_event_id
257
258
259 try:
260 multi_burst.snr = sim_tree.rho[1]
261 except TypeError:
262 multi_burst.snr = sim_tree.rho
263
264 multi_burst.false_alarm_rate = -1.0
265
266 multi_burst.ligo_axis_ra = sim_tree.phi[2]
267 multi_burst.ligo_axis_dec = sim_tree.theta[2]
268 multi_burst.ifos = lsctables.ifos_from_instrument_set( get_ifos_from_index( branch_array_to_list ( sim_tree.ifo, sim_tree.ndim ) ) )
269
270 multi_burst_table.append(multi_burst)
271
273 """
274 Fill in a coinc definer entry for waveburst
275 """
276
277 return lsctables.CoincDef(search = u"waveburst", search_coinc_type = 0, description = u"fully coherent search (burst events)")
278
280 """
281 Fill in a custom cwb event table
282 """
283
284 row = cohwb_table.RowType()
285
286 row.ellipticity = sim_tree.norm
287
288 row.correlated_energy = sim_tree.ecor
289
290 row.eff_correlated_energy = sim_tree.ECOR
291
292
293
294 row.coherent_network_amp = sim_tree.rho[1]
295
296
297
298
299 row.penalty = sim_tree.penalty
300
301
302
303
304 row.network_correlation = sim_tree.netcc[0]
305
306
307
308 row.energy_disbalance = sim_tree.neted[0]/sim_tree.ecor
309
310
311 row.ellip_energy_disbalance = sim_tree.neted[1]/sim_tree.ecor
312
313 return row
314
316 """
317 Fill in a sngl_burst row for a cwb event
318 """
319 row = sngl_burst_table.RowType()
320 row.search = u"waveburst"
321
322 row.ifo = get_ifos_from_index(sim_tree.ifo[d] )
323
324 peak = LIGOTimeGPS(sim_tree.time[d])
325 seg = segments.segment(LIGOTimeGPS(sim_tree.start[d]), LIGOTimeGPS(sim_tree.stop[d]))
326
327 row.set_peak(peak)
328
329 row.set_start(seg[0])
330
331 row.set_stop(seg[1])
332
333 row.duration = abs(seg)
334
335 row.time_lag = sim_tree.lag[d]
336
337
338 row.peak_frequency = sim_tree.frequency[d]
339 try:
340
341 row.flow = sim_tree.low[d]
342
343 row.fhigh = sim_tree.high[d]
344 except TypeError:
345 row.flow = sim_tree.low
346 row.fhigh = sim_tree.high
347
348 row.bandwidth = sim_tree.bandwidth[d]
349
350
351 row.tfvolume = sim_tree.size[d]
352
353
354 row.snr = sim_tree.snr[d]**(1./2.)
355
356
357
358 row.hrss = sim_tree.hrss[d]
359
360 return row
361
363 """
364 Fill in a multi_burst row for a cwb event -- these should exactly correlate to the sngl_burst events within a single coherent event
365 """
366 row = multi_burst_table.RowType()
367
368
369 row.set_peak(LIGOTimeGPS(sim_tree.time[0]))
370 return row
371
373 """
374 Create the process_table for the cWB job(s) from a job segment.
375 """
376
377 try:
378 process_table = lsctables.ProcessTable.get_table(xmldoc)
379 except ValueError:
380 process_table = lsctables.New(lsctables.ProcessTable,
381 ["process_id", "ifos", "comment", "program", "start_time", "jobid",
382 "end_time",
383
384 "version", "cvs_repository", "cvs_entry_time", "is_online", "node",
385 "username", "unix_procid", "domain"])
386 xmldoc.childNodes[0].appendChild(process_table)
387
388
389
390 if(jobid < 0):
391 N = sim_tree.GetEntries()
392 if N == 0:
393 exit("There is no information available to parse from the ROOT file, and no external information was provided.")
394 runs = set()
395 for i in xrange(N):
396 sim_tree.GetEntry(i)
397 run = sim_tree.run
398 runs.add(int(run))
399 else:
400 run = jobid
401 seg = segment
402
403
404 ifos = lsctables.ifos_from_instrument_set( get_ifos_from_index( branch_array_to_list ( sim_tree.ifo, sim_tree.ndim ) ) )
405
406 if( ifos == None or len(ifos) == 0 ):
407 if( self.instruments ):
408 ifos = self.instruments
409 else:
410 sys.exit("Found a job with no IFOs on, or not enough to determine IFOs. Try specifying instruments directly.")
411
412 for run in runs:
413 row = process_table.RowType()
414 row.process_id = type(process_table.next_id)(run)
415 row.ifos = ifos
416 row.comment = u"waveburst"
417 row.program = u"waveburst"
418 row.start_time = None
419 row.end_time = None
420 row.jobid = run
421 row.version = __version__
422 row.cvs_repository = u"lscsoft"
423
424 row.cvs_entry_time = 0
425 row.is_online = 0
426 row.username = os.environ['USER']
427 row.node = platform.node()
428 row.unix_procid = os.getpid()
429 row.domain = u"pylal"
430 process_table.append(row)
431
433 """
434 Create the process_table for the cWB job(s)
435 """
436
437 try:
438 process_table = lsctables.ProcessTable.get_table(xmldoc)
439 except ValueError:
440 process_table = lsctables.New(lsctables.ProcessTable,
441 ["process_id", "ifos", "comment", "program", "start_time", "jobid",
442 "end_time",
443
444 "version", "cvs_repository", "cvs_entry_time", "is_online", "node",
445 "username", "unix_procid", "domain"])
446 xmldoc.childNodes[0].appendChild(process_table)
447
448 runids = set()
449 runid = dict()
450
451 itr = 0
452 for line in file(self.job_list) :
453 if line[0] == '#' :
454 continue
455
456
457
458 line = line.split()
459 if len(line) == 2 :
460 seg = segments.segment( map( LIGOTimeGPS, map(float, line[0:2]) ) )
461 runid[itr] = seg
462 itr += 1
463 elif len(line) == 3 :
464 seg = segments.segment( map( LIGOTimeGPS, map(float, line[1:3]) ) )
465 runid[int(line[0])] = seg
466 elif len(line) == 4 :
467 seg = segments.segment( map( LIGOTimeGPS, map(float, line[1:3]) ) )
468 runid[int(line[0])] = seg
469 else :
470 sys.exit("Unable to understand job list segment format. Why do you confused me so?")
471
472
473 sim_tree.GetEntry(0)
474 for run, seg in runid.iteritems() :
475 if self.start != None :
476 if float(self.start) > seg[0] : continue
477 if self.end != None :
478 if float(self.end) < seg[1] : continue
479
480 row = process_table.RowType()
481 row.process_id = type(process_table.next_id)(run)
482
483 runids.add(sim_tree.run)
484
485
486 ifos = lsctables.ifos_from_instrument_set( get_ifos_from_index( branch_array_to_list ( sim_tree.ifo, sim_tree.ndim ) ) )
487
488 if( ifos == None or len(ifos) == 0 ):
489 if( self.instruments ):
490 ifos = self.instruments
491 else:
492 sys.exit("Found a job with no IFOs on, or not enough to determine IFOs. Try specifying instruments directly.")
493
494 row.ifos = ifos
495 row.comment = u"waveburst"
496 row.program = u"waveburst"
497
498 row.start_time = None
499 row.end_time = None
500 row.jobid = run
501
502 row.version = __version__
503 row.cvs_repository = u"lscsoft"
504
505 row.cvs_entry_time = 0
506 row.is_online = 0
507 row.username = os.environ['USER']
508 row.node = platform.node()
509 row.unix_procid = os.getpid()
510 row.domain = "pylal"
511
512 process_table.append(row)
513
515 """
516 Create the search_summary table for a cWB from a segment specified from the command line. The function will try to determine the proper job intervals from the waveoffset, if specified.
517 """
518
519 try:
520 search_summary = lsctables.SearchSummaryTable.get_table(xmldoc)
521 except ValueError:
522 search_summary = lsctables.New(lsctables.SearchSummaryTable,
523 ["process_id", "nevents", "ifos", "comment", "in_start_time",
524 "in_start_time_ns", "out_start_time", "out_start_time_ns",
525 "in_end_time", "in_end_time_ns", "out_end_time", "out_end_time_ns"])
526 xmldoc.childNodes[0].appendChild(search_summary)
527
528 process_id_type = type(lsctables.ProcessTable.get_table(xmldoc).next_id)
529
530 sim_tree.GetEntry(0)
531
532 if(jobid < 0):
533 run = sim_tree.run
534 else: run = jobid
535 seg = segment
536
537
538
539 row = search_summary.RowType()
540 row.process_id = process_id_type(run)
541 row.nevents = sim_tree.GetEntries()
542
543 ifos = lsctables.ifos_from_instrument_set( get_ifos_from_index( branch_array_to_list ( sim_tree.ifo, sim_tree.ndim ) ) )
544
545 if( ifos == None or len(ifos) == 0 ):
546 if( self.instruments ):
547 ifos = self.instruments
548 else:
549 sys.exit("Found a job with no IFOs on, or not enough to determine IFOs. Try specifying instruments directly.")
550
551 row.ifos = ifos
552 row.comment = "waveburst"
553
554
555 waveoffset = self.waveoffset
556 if waveoffset == None: waveoffset = 0
557
558
559 row.set_in(seg)
560
561 waveoffset = LIGOTimeGPS(waveoffset)
562 row.set_out(segments.segment(seg[0]+waveoffset, seg[1]-waveoffset))
563 search_summary.append(row)
564
566 """
567 Create the search_summary table for the cWB job(s) and a provided cWB joblist. The function will try to determine the proper job intervals from the waveoffset, if specified.
568 """
569
570 try:
571 search_summary = lsctables.SearchSummaryTable.get_table(xmldoc)
572 except ValueError:
573 search_summary = lsctables.New(lsctables.SearchSummaryTable,
574 ["process_id", "nevents", "ifos", "comment", "in_start_time",
575 "in_start_time_ns", "out_start_time", "out_start_time_ns",
576 "in_end_time", "in_end_time_ns", "out_end_time", "out_end_time_ns"])
577 xmldoc.childNodes[0].appendChild(search_summary)
578
579 process_id_type = type(lsctables.ProcessTable.get_table(xmldoc).next_id)
580
581 runid = dict()
582 itr = 0
583 for line in file(self.job_list) :
584 if line[0] == '#' :
585 continue
586
587
588
589 line = line.split()
590
591 if len(line) == 2 :
592 seg = segments.segment( map( LIGOTimeGPS, map(float, line[0:2]) ) )
593 runid[itr] = seg
594 itr += 1
595 elif len(line) == 3 :
596 seg = segments.segment( map( LIGOTimeGPS, map(float, line[1:3]) ) )
597 runid[int(line[0])] = seg
598 elif len(line) == 4 :
599 seg = segments.segment( map( LIGOTimeGPS, map(float, line[1:3]) ) )
600 runid[int(line[0])] = seg
601 else :
602 sys.exit("Unable to understand job list segment format.")
603
604 for run, seg in runid.iteritems() :
605 if self.start != None :
606 if float(self.start) > seg[0] : continue
607 if self.end != None :
608 if float(self.end) < seg[1] : continue
609
610 row = search_summary.RowType()
611 row.process_id = process_id_type(run)
612
613
614
615 row.nevents = 0
616
617
618
619 sim_tree.GetEntry(0)
620 ifos = lsctables.ifos_from_instrument_set( get_ifos_from_index( branch_array_to_list ( sim_tree.ifo, sim_tree.ndim ) ) )
621
622 if( ifos == None or len(ifos) == 0 ):
623 if( self.instruments ):
624 ifos = self.instruments
625 else:
626 sys.exit("Found a job with no IFOs on, or not enough to determine IFOs. Try specifying instruments directly.")
627
628 row.ifos = ifos
629 row.comment = "waveburst"
630
631
632
633
634
635 waveoffset, livetime = self.waveoffset, -1
636 if waveoffset == None: waveoffset = 0
637 livetime = abs(seg)
638
639 if livetime < 0:
640 print >>sys.stderr, "WARNING: Run %d will have zero livetime because no events are recorded in this run, and therefore livetime cannot be calculated." % run
641
642 row.set_in(segments.segment(LIGOTimeGPS(0), LIGOTimeGPS(1)))
643
644 row.set_out(segments.segment(LIGOTimeGPS(0), LIGOTimeGPS(1)))
645 else:
646
647 row.set_in(seg)
648
649 row.set_out(segments.segment(seg[0]+waveoffset, seg[1]-waveoffset))
650
651 search_summary.append(row)
652
654 """
655 Create the search_summary table for the cWB job(s). This function exists as a backup in case no job list exists. It will try and reconstruct the job segments from the event data, but this list will be incomplete in the case where no events were found during a job.
656 """
657
658 try:
659 search_summary = lsctables.SearchSummaryTable.get_table(xmldoc)
660 except ValueError:
661 search_summary = lsctables.New(lsctables.SearchSummaryTable,
662 ["process_id", "nevents", "ifos", "comment", "in_start_time",
663 "in_start_time_ns", "out_start_time", "out_start_time_ns",
664 "in_end_time", "in_end_time_ns", "out_end_time", "out_end_time_ns"])
665 xmldoc.childNodes[0].appendChild(search_summary)
666
667 process_id_type = type(lsctables.ProcessTable.get_table(xmldoc).next_id)
668
669 runids = set()
670 entries = sim_tree.GetEntries()
671 for i in range(0, entries) :
672 sim_tree.GetEntry(i)
673
674 if self.start != None :
675 if float(self.start) > sim_tree.start[0] : continue
676 if self.end != None :
677 if float(self.end) < sim_tree.stop[0] : continue
678
679
680 run = sim_tree.run
681 if run in runids :
682 continue
683
684 row = search_summary.RowType()
685 row.process_id = process_id_type(run)
686 runids.add(run)
687
688
689
690
691
692 row.nevents = 0
693
694
695 ifos = lsctables.ifos_from_instrument_set( get_ifos_from_index( branch_array_to_list ( sim_tree.ifo, sim_tree.ndim ) ) )
696
697 if( ifos == None or len(ifos) == 0 ):
698 if( self.instruments ):
699 ifos = self.instruments
700 else:
701 sys.exit("Found a job with no IFOs on, or not enough to determine IFOs. Try specifying instruments directly.")
702
703 row.ifos = ifos
704 row.comment = "waveburst"
705
706
707 if self.waveoffset != None :
708 waveoffset = self.waveoffset
709 else:
710 waveoffset = 0
711
712 livetime = -1
713
714
715 livetime = sim_tree.left[0] + sim_tree.duration[0] + sim_tree.right[0]
716
717 if livetime < 0:
718 print >>sys.stderr, "WARNING: Run %d will have zero livetime because no events are recorded in this run, and therefore livetime cannot be calculated." % run
719
720 row.set_in(segments.segment(LIGOTimeGPS(0), LIGOTimeGPS(1)))
721
722 row.set_out(segments.segment(LIGOTimeGPS(0), LIGOTimeGPS(1)))
723 else:
724
725 seg_start_with_offset = sim_tree.gps - waveoffset
726 seg_start_without_offset = sim_tree.gps
727 seg_end_with_offset = sim_tree.gps + waveoffset + livetime
728 seg_end_without_offset = sim_tree.gps + livetime
729
730 row.set_in(segments.segment(LIGOTimeGPS(seg_start_with_offset), LIGOTimeGPS(seg_end_with_offset)))
731
732 row.set_out(segments.segment(LIGOTimeGPS(seg_start_without_offset), LIGOTimeGPS(seg_end_without_offset)))
733
734 search_summary.append(row)
735
736 -class CWBTextConverter(object):
737 """
738 Class to transparently emit data as if the input were a ROOT file. The input is an unstructured text file made by cWB at runtime.
739 """
740
741 CWB_SEARCH_TYPES = { 'r': "unmodelled", 'i': "elliptical", 's': "linear", 'g': "circular", 'R': "unmodelled", 'I': "elliptical", 'S': "linear", 'G': "circular" }
742
743 - def __init__(self):
744 self.data = []
745 self.this_data = None
746 self.version = None
747 self.online_version = None
748 self.search_type = None
749 self._skymap_reg = re.compile( "^map_lenght" )
750 self._far_info_reg = re.compile( "^##" )
751
752 - def __getattr__(self, name):
753 """
754 This overrides the attribute getter for this class so that when the proxy class is required to produce information based on an attribute (say 'rho') it responds just like a TBranch would. If no event is 'selected' via GetEntry, then None is returned, regardless of the attribute, because there's no way to know whether we're asking for a TBranch leaf or something else.
755 """
756 if self.this_data is None:
757 return None
758 try:
759 return self.this_data[name]
760 except KeyError:
761 return getattr(self, name)
762
763 - def GetEntry(self, i):
764 """
765 Emulate a TTree GetEntry() call by switching internal pointer to a row in the table.
766 """
767 self.this_data = self.data[i]
768
769 - def GetEntries(self):
770 """
771 Emulate a TTree GetEntries() call by returning the length of the internal data table.
772 """
773 return len(self.data)
774
775 - def Add(self, filen):
776 """
777 Add a file which will be parsed by the class and added to the internal table.
778 """
779 self.parse_transcript( open(filen) )
780
781 - def get_far_segments( self ):
782 """
783 Gets the segments for which various FARs have been defined.
784 """
785 if self.this_data["far_data"] is None:
786 raise ValueError( "No FAR info for this event." )
787
788 return self.this_data["far_data"].keys()
789
790
792 """
793 Returns the false alarm rate for a given segment, usually one of the segments retrieved from 'get_far_segments'. If segment is None (default), then the FAR from the biggest segment is returned.
794 """
795
796 if self.this_data["far_data"] is None:
797 raise ValueError( "No FAR info for this event." )
798
799
800 if segment is None:
801 segs = sorted( self.get_far_segments(), key=lambda s: abs(s) )
802 return self.this_data["far_data"][segs[-1]]
803
804 return self.this_data["far_data"][segment]
805
806
807 - def get_skymap_coords( self ):
808 """
809 Get a list of the skymap coordinates (R.A. and dec) which cWB has probability values for.
810 """
811 if self.this_data["skymap"] is None:
812 raise ValueError( "No skymap set for this event." )
813
814 return self.this_data["skymap"].keys()
815
816 - def get_skymap_prob( self, ra, dec ):
817 """
818 Return the probability for a given R.A. and dec from the skymap data. If there is no entry for this, then 0 is returned. This is the implied value for no R.A. and dec entry in the skymap data.
819 """
820 if self.this_data["skymap"] is None:
821 raise ValueError( "No skymap set for this event." )
822
823 try:
824 return self.this_data["skymap"][(ra, dec)]
825 except KeyError:
826 return 0
827
828 - def parse_with_type(self, val):
829 """
830 Attempt to coerce data to the proper type. Note that this depends on python's finickiness with int / float parsing. It won't do string -> float -> int truncation with one call to float(). So, this check whether or not int() works, then tries float(). Then it gives up and gives the value (presumed a string) back.
831 """
832 try:
833 return int(val)
834 except ValueError:
835 pass
836 try:
837 return float(val)
838 except ValueError:
839 pass
840 return val
841
842 - def parse_transcript(self, text):
843 """
844 Parses a textual event transcript and adds the data to the internal table.
845 """
846 row, mode = {}, "var"
847 row["skymap"] = {}
848 row["far_data"] = {}
849
850 for line in text.readlines():
851
852
853 if "wat version" in line:
854 self.version = line.split("=")[1].strip()
855 continue
856 elif "online version" in line:
857 self.online_version = line.split("=")[1].strip()
858 continue
859 elif "search" in line:
860 self.search_type = self.CWB_SEARCH_TYPES[line.split("=")[1].strip()]
861 continue
862 elif re.match( self._far_info_reg, line ) is not None:
863 mode = "far"
864 continue
865 elif re.match( self._skymap_reg, line ) is not None:
866 mode = "skymap"
867 continue
868 elif len(line.strip()) == 0:
869
870 row["gps"] = row["segment"][0]
871 self.data.append( row )
872 row = {}
873 row["skymap"] = {}
874 row["far_data"] = {}
875 mode = "var"
876 continue
877
878 if line[0] == "#": continue
879
880
881 if mode == "var":
882
883 varn, val = line.split(":")
884 val = [ self.parse_with_type(v) for v in val.split() ]
885 if len(val) == 1: val = val[0]
886
887 row[varn] = val
888 elif mode == "skymap":
889 sid, theta, dec, step, phi, ra, step2, prob, cum = line.split()
890 row["skymap"][(float(ra), float(dec))] = float(prob)
891 elif mode == "far":
892 try:
893 rank, rate, segstart, segend, segdur = line.split()
894 except ValueError:
895
896
897 continue
898 far_seg = segments.segment( float(segstart), float(segend) )
899 row["far_data"][far_seg] = float(rate)
900
901
902 row["gps"] = row["segment"][0]
903 self.data.append( row )
904 return row
905