gstlal-inspiral  0.4.2
 All Classes Namespaces Files Functions Variables Pages
spiirparts.py
1 # Copyright (C) 2009--2013 Kipp Cannon, Chad Hanna, Drew Keppel
2 # Copyright (C) 2013, 2014 Qi Chu
3 #
4 # This program is free software; you can redistribute it and/or modify it
5 # under the terms of the GNU General Public License as published by the
6 # Free Software Foundation; either version 2 of the License, or (at your
7 # option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
12 # Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License along
15 # with this program; if not, write to the Free Software Foundation, Inc.,
16 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 
18 #
19 #
20 # =============================================================================
21 #
22 # Preamble
23 #
24 # =============================================================================
25 #
26 
27 
28 import math
29 import sys
30 import numpy
31 import warnings
32 import StringIO
33 
34 
35 # The following snippet is taken from http://gstreamer.freedesktop.org/wiki/FAQ#Mypygstprogramismysteriouslycoredumping.2Chowtofixthis.3F
36 import pygtk
37 pygtk.require("2.0")
38 import gobject
39 gobject.threads_init()
40 import pygst
41 pygst.require('0.10')
42 import gst
43 
44 
45 from glue import iterutils
46 from glue import segments
47 from glue.ligolw import ligolw
48 from glue.ligolw import lsctables
49 from glue.ligolw import utils as ligolw_utils
50 from glue.ligolw.utils import segments as ligolw_segments
51 from glue.ligolw.utils import process as ligolw_process
52 from gstlal import bottle
53 from gstlal import datasource
54 from gstlal import multirate_datasource
55 from gstlal import pipeio
56 from gstlal import pipeparts
57 from gstlal import simplehandler
58 from gstlal import simulation
59 from pylal.datatypes import LIGOTimeGPS
60 
61 #
62 # SPIIR many instruments, many template banks
63 #
64 
65 
66 def mkSPIIRmulti(pipeline, detectors, banks, psd, psd_fft_length = 8, ht_gate_threshold = None, veto_segments = None, verbose = False, nxydump_segment = None, chisq_type = 'autochisq', track_psd = False, block_duration = gst.SECOND, blind_injections = None):
67  #
68  # check for recognized value of chisq_type
69  #
70 
71  if chisq_type not in ['autochisq']:
72  raise ValueError("chisq_type must be either 'autochisq', given %s" % chisq_type)
73 
74  #
75  # extract segments from the injection file for selected reconstruction
76  #
77 
78  if detectors.injection_filename is not None:
79  inj_seg_list = simulation.sim_inspiral_to_segment_list(injection_filename)
80  else:
81  inj_seg_list = None
82  #
83  # Check to see if we are specifying blind injections now that we know
84  # we don't want real injections. Setting this
85  # detectors.injection_filename will ensure that injections are added
86  # but won't only reconstruct injection segments.
87  #
88  detectors.injection_filename = blind_injections
89 
90  #
91  # construct dictionaries of whitened, conditioned, down-sampled
92  # h(t) streams
93  #
94 
95  hoftdicts = {}
96  for instrument in detectors.channel_dict:
97  rates = set(rate for bank in banks[instrument] for rate in bank.get_rates()) # FIXME what happens if the rates are not the same?
98  src = datasource.mkbasicsrc(pipeline, detectors, instrument, verbose)
99  if veto_segments is not None:
100  hoftdicts[instrument] = multirate_datasource.mkwhitened_multirate_src(pipeline, src, rates, instrument, psd = psd[instrument], psd_fft_length = psd_fft_length, ht_gate_threshold = ht_gate_threshold, veto_segments = veto_segments[instrument], seekevent = detectors.seekevent, nxydump_segment = nxydump_segment, track_psd = track_psd, zero_pad = 0, width = 32)
101  else:
102  hoftdicts[instrument] = multirate_datasource.mkwhitened_multirate_src(pipeline, src, rates, instrument, psd = psd[instrument], psd_fft_length = psd_fft_length, ht_gate_threshold = ht_gate_threshold, veto_segments = None, seekevent = detectors.seekevent, nxydump_segment = nxydump_segment, track_psd = track_psd, zero_pad = 0, width = 32)
103 
104  #
105  # construct trigger generators
106  #
107 
108  triggersrcs = dict((instrument, set()) for instrument in hoftdicts)
109  for instrument, bank in [(instrument, bank) for instrument, banklist in banks.items() for bank in banklist]:
110  suffix = "%s%s" % (instrument, (bank.logname and "_%s" % bank.logname or ""))
111 
112  snr = mkSPIIRhoftToSnrSlices(
113  pipeline,
114  hoftdicts[instrument],
115  bank,
116  instrument,
117  verbose = verbose,
118  nxydump_segment = nxydump_segment,
119  quality = 4
120  )
121  snr = pipeparts.mkchecktimestamps(pipeline, snr, "timestamps_%s_snr" % suffix)
122 
123  snr = pipeparts.mktogglecomplex(pipeline, snr)
124  snr = pipeparts.mktee(pipeline, snr)
125  # FIXME you get a different trigger generator depending on the chisq calculation :/
126  if chisq_type == 'autochisq':
127  # FIXME don't hardcode
128  # peak finding window (n) in samples is one second at max rate, ie max(rates)
129  head = pipeparts.mkitac(pipeline, snr, max(rates), bank.template_bank_filename, autocorrelation_matrix = bank.autocorrelation_bank, mask_matrix = bank.autocorrelation_mask, snr_thresh = bank.snr_threshold, sigmasq = bank.sigmasq)
130  if verbose:
131  head = pipeparts.mkprogressreport(pipeline, head, "progress_xml_%s" % suffix)
132  triggersrcs[instrument].add(head)
133  # FIXME: find a way to use less memory without this hack
134  del bank.autocorrelation_bank
135  #pipeparts.mknxydumpsink(pipeline, pipeparts.mktogglecomplex(pipeline, pipeparts.mkqueue(pipeline, snr)), "snr_%s.dump" % suffix, segment = nxydump_segment)
136  #pipeparts.mkogmvideosink(pipeline, pipeparts.mkcapsfilter(pipeline, pipeparts.mkchannelgram(pipeline, pipeparts.mkqueue(pipeline, snr), plot_width = .125), "video/x-raw-rgb, width=640, height=480, framerate=64/1"), "snr_channelgram_%s.ogv" % suffix, audiosrc = pipeparts.mkaudioamplify(pipeline, pipeparts.mkqueue(pipeline, hoftdict[max(bank.get_rates())], max_size_time = 2 * int(math.ceil(bank.filter_length)) * gst.SECOND), 0.125), verbose = True)
137 
138  #
139  # done
140  #
141 
142  assert any(triggersrcs.values())
143  return triggersrcs
144 
145 
146 def mkSPIIRhoftToSnrSlices(pipeline, src, bank, instrument, verbose = None, nxydump_segment = None, quality = 4, sample_rates = None, max_rate = None):
147  if sample_rates is None:
148  sample_rates = sorted(bank.get_rates())
149  else:
150  sample_rates = sorted(sample_rates)
151  #FIXME don't upsample everything to a common rate
152  if max_rate is None:
153  max_rate = max(sample_rates)
154  prehead = None
155 
156  for sr in sample_rates:
157  head = pipeparts.mkqueue(pipeline, src[sr], max_size_time=gst.SECOND * 10, max_size_buffers=0, max_size_bytes=0)
158  head = pipeparts.mkreblock(pipeline, head)
159  head = pipeparts.mkiirbank(pipeline, head, a1 = bank.A[sr], b0 = bank.B[sr], delay = bank.D[sr], name = "gstlaliirbank_%d_%s_%s" % (sr, instrument, bank.logname))
160  head = pipeparts.mkqueue(pipeline, head, max_size_time=gst.SECOND * 10, max_size_buffers=0, max_size_bytes=0)
161  if prehead is not None:
162  head = pipeparts.mkadder(pipeline, (head, prehead))
163  # FIXME: this should get a nofakedisconts after it until the resampler is patched
164  head = pipeparts.mkresample(pipeline, head, quality = quality)
165  if sr == max_rate:
166  head = pipeparts.mkcapsfilter(pipeline, head, "audio/x-raw-float, rate=%d" % max_rate)
167  else:
168  head = pipeparts.mkcapsfilter(pipeline, head, "audio/x-raw-float, rate=%d" % (2 * sr))
169  prehead = head
170 
171  return head
172