gstlal  0.8.1
 All Classes Namespaces Files Functions Variables Pages
lal_fakeadvvirgosrc.py
1 # Copyright (C) 2012 Drew Keppel
2 #
3 # This program is free software; you can redistribute it and/or modify it
4 # under the terms of the GNU General Public License as published by the
5 # Free Software Foundation; either version 2 of the License, or (at your
6 # option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful, but
9 # WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11 # Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License along
14 # with this program; if not, write to the Free Software Foundation, Inc.,
15 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 """
17 Generate simulated Advanced Virgo h(t) based on the baseline document
18 https://wwwcascina.virgo.infn.it/advirgo/docs/AdV_refsens_100512.txt
19 """
20 __author__ = "Drew Keppel <drew.keppel@ligo.org>"
21 
22 from gstlal import pipeutil
23 from gstlal.pipeutil import gobject, gst
24 from math import cos, pi, sqrt
25 
26 
27 class lal_fakeadvvirgosrc(gst.Bin):
28 
29  __gstdetails__ = (
30  'Fake Advanced Virgo Source',
31  'Source',
32  __doc__,
33  __author__
34  )
35 
36  __gproperties__ = {
37  'blocksize': (
38  gobject.TYPE_UINT64,
39  'blocksize',
40  'Number of samples in each outgoing buffer',
41  0, gobject.G_MAXULONG, 16384 * 8 * 1, # min, max, default
42  gobject.PARAM_WRITABLE
43  ),
44  'instrument': (
45  gobject.TYPE_STRING,
46  'instrument',
47  'Instrument name (e.g., "V1")',
48  None,
49  gobject.PARAM_WRITABLE
50  ),
51  'channel-name': (
52  gobject.TYPE_STRING,
53  'channel-name',
54  'Channel name (e.g., "h_16384Hz")',
55  None,
56  gobject.PARAM_WRITABLE
57  )
58  }
59 
60  __gsttemplates__ = (
61  gst.PadTemplate("src",
62  gst.PAD_SRC, gst.PAD_ALWAYS,
63  gst.caps_from_string("""
64  audio/x-raw-float,
65  channels = (int) 1,
66  endianness = (int) BYTE_ORDER,
67  width = (int) 64,
68  rate = (int) 16384
69  """)
70  ),
71  )
72 
73  def do_set_property(self, prop, val):
74  if prop.name == 'blocksize':
75  # Set property on all sources
76  for elem in self.iterate_sources():
77  elem.set_property('blocksize', val)
78  elif prop.name in ('instrument', 'channel-name'):
79  self.__tags[prop.name] = val
80  tagstring = ','.join('%s="%s"' % kv for kv in self.__tags.iteritems())
81  self.__taginject.set_property('tags', tagstring)
82 
83 
84  def do_send_event(self, event):
85  """
86  Send SEEK and EOS events to the source elements, all others
87  to the by default bins send all events to the sink
88  elements.
89  """
90  # FIXME: seeks should go to sink elements as well
91  success = True
92  if event.type in (gst.EVENT_SEEK, gst.EVENT_EOS):
93  for elem in self.iterate_sources():
94  success &= elem.send_event(event)
95  else:
96  for elem in self.iterate_sinks():
97  success &= elem.send_event(event)
98  return success
99 
100 
101  def __init__(self):
102  super(lal_fakeadvvirgosrc, self).__init__()
103 
104  self.__tags = {'units':'strain'}
105 
106  chains = []
107 
108  # the f^-2 part of the spectrum
109  peak_width = 1 - 1e-3
110  vol = 2.6e-31
111  a = [1.]
112  b = [-1.0, 4 * peak_width, -6 * peak_width**2, 4 * peak_width**3, -peak_width**4]
113  chains.append(pipeutil.mkelems_in_bin(self,
114  ('audiotestsrc', {'wave':'gaussian-noise', 'volume': vol, 'samplesperbuffer': 16384}),
115  ('audioiirfilter', {'a': a, 'b': b}),
116  ))
117 
118  # this pole recreates a line at 16.83 Hz
119  central_freq = cos(2*pi*16.85/16384)
120  peak_width = 1. - 2e-5
121  vol = 5e-28
122  a = [1.]
123  b = [-1.0, 2 * central_freq * peak_width, -peak_width**2]
124  chains.append(pipeutil.mkelems_in_bin(self,
125  ('audiotestsrc', {'wave':'gaussian-noise', 'volume': vol, 'samplesperbuffer': 16384}),
126  ('audioiirfilter', {'a': a, 'b': b}),
127  ))
128 
129  # this f^-1 response helps connect the f^-2 part to the bucket
130  peak_width = 1. - 1e-3
131  vol = 1.5e-27
132  a = [1.]
133  b = [-1.0, 2 * peak_width, -peak_width**2]
134  chains.append(pipeutil.mkelems_in_bin(self,
135  ('audiotestsrc', {'wave':'gaussian-noise', 'volume': vol, 'samplesperbuffer': 16384}),
136  ('audioiirfilter', {'a': a, 'b': b}),
137  ))
138 
139  # this broad pole models the bump in the bucket
140  central_freq = cos(2*pi*50./16384)
141  peak_width = 1. - 1.1e-1
142  vol = 6.3e-26
143  a = [1.]
144  b = [-1.0, 2 * central_freq * peak_width, -peak_width**2]
145  chains.append(pipeutil.mkelems_in_bin(self,
146  ('audiotestsrc', {'wave':'gaussian-noise', 'volume': vol, 'samplesperbuffer': 16384}),
147  ('audioiirfilter', {'a': a, 'b': b}),
148  ))
149 
150  # this pole recreates a line at 438 Hz
151  central_freq = cos(2*pi*438./16384)
152  peak_width = 1. - 7e-5
153  vol = 2e-27
154  a = [1.]
155  b = [-1.0, 2 * central_freq * peak_width, -peak_width**2]
156  chains.append(pipeutil.mkelems_in_bin(self,
157  ('audiotestsrc', {'wave':'gaussian-noise', 'volume': vol, 'samplesperbuffer': 16384}),
158  ('audioiirfilter', {'a': a, 'b': b}),
159  ))
160 
161  # this is a 1st order one-sided finite-difference second-derivative stencil
162  # it has a response of |H(f)| \propto f^2
163  # FIXME: this could be tuned to more closely match at high
164  # frequencies the baseline found above
165  vol = 1.8e-22
166  ker = [1.0, -2.0, 1.0]
167  chains.append(pipeutil.mkelems_in_bin(self,
168  ('audiotestsrc', {'wave':'gaussian-noise', 'volume': vol, 'samplesperbuffer': 16384}),
169  ('audiofirfilter', {'kernel': ker}),
170  ))
171 
172  outputchain = pipeutil.mkelems_in_bin(self,
173  ('lal_adder', {'sync': True}),
174  ('audioamplify', {'clipping-method': 3, 'amplification': sqrt(16384.)*3/4}),
175  ('taginject',)
176  )
177 
178  for chain in chains:
179  chain[-1].link(outputchain[0])
180 
181  self.__taginject = outputchain[-1]
182  self.add_pad(gst.ghost_pad_new_from_template('src', outputchain[-1].get_static_pad('src'), self.__gsttemplates__[0]))
183 
184 
185 
186 # Register element class
187 gobject.type_register(lal_fakeadvvirgosrc)
188 
189 __gstelementfactory__ = (
190  lal_fakeadvvirgosrc.__name__,
191  gst.RANK_NONE,
192  lal_fakeadvvirgosrc
193 )