gstlal 1.13.0
Loading...
Searching...
No Matches
source.py
1"""Module for producing source elements
2
3"""
4import pathlib
5import sys
6import os
7from typing import List, Tuple, Union, Iterable, Optional
8
9from ligo import segments
10
11from gstlal.pipeparts import pipetools, transform, filters, mux
12from gstlal.utilities import laltools
13
14BYTE_ORDER = 'LE' if sys.byteorder == "little" else 'BE'
15
16
18 """Enumeration of test waveforms
19
20 References:
21 [1] https://gstreamer.freedesktop.org/documentation/audiotestsrc/index.html?gi-language=python#GstAudioTestSrcWave
22 """
23 Sine = 0
24 Square = 1
25 Saw = 2
26 Triangle = 3
27 Silence = 4
28 WhiteNoise = 5
29 PinkNoise = 6
30 SineTable = 7
31 Ticks = 8
32 GaussianNoise = 9
33 RedNoise = 10
34 BlueNoise = 11
35 VioletNoise = 12
36
37
39 """Enumeration of NDS channel types
40
41 References:
42 Implementation: gstlal-ugly/gst/nds/ndssrc.c
43 """
44 Unknown = 'unknown'
45 Online = 'online'
46 Raw = 'raw'
47 Reduced = 'reduced'
48 SecondTrend = 's-trend'
49 MinuteTrend = 'm-trend'
50 TestPoint = 'test-pt'
51
52
53class SrcDeferredLink(object):
54 """A class that manages the task of watching for and connecting to new
55 source pads by name. The inputs are an element, the name of the
56 source pad to watch for on that element, and the sink pad (on a
57 different element) to which the source pad should be linked when it
58 appears.
59
60 The "pad-added" signal of the element will be used to watch for new
61 pads, and if the "no-more-pads" signal is emitted by the element
62 before the requested pad has appeared ValueError is raised.
63 """
64
65 def __init__(self, element, srcpadname, sinkpad):
66 no_more_pads_handler_id = element.connect("no-more-pads", self.no_more_pads, srcpadname)
67 assert no_more_pads_handler_id > 0
68 pad_added_data = [srcpadname, sinkpad, no_more_pads_handler_id]
69 pad_added_handler_id = element.connect("pad-added", self.pad_added, pad_added_data)
70 assert pad_added_handler_id > 0
71 pad_added_data.append(pad_added_handler_id)
72
73 @staticmethod
74 def pad_added(element, pad, src_sink_ids):
75 srcpadname, sinkpad, no_more_pads_handler_id, pad_added_handler_id = src_sink_ids
76 if pad.get_name() == srcpadname:
77 element.handler_disconnect(no_more_pads_handler_id)
78 element.handler_disconnect(pad_added_handler_id)
79 pad.link(sinkpad)
80
81 @staticmethod
82 def no_more_pads(element, srcpadname):
83 raise ValueError("<%s>: no pad named '%s'" % (element.get_name(), srcpadname))
84
85
86def fake_ligo(pipeline: pipetools.Pipeline, instrument: str = None, channel_name: str = None, blocksize: int = 16384 * 8 * 1) -> pipetools.Element:
87 """Fake LIGO Source
88
89 Args:
90 pipeline:
91 Gst.Pipeline, the pipeline to which the new element will be added
92 instrument:
93 str, default None
94 channel_name:
95 str, default None
96 blocksize:
97 int, default 16384 * 8 * 1, Number of samples in each outgoing buffer
98
99 References:
100 Implementation gstlal/gst/python/lal_fakeligosrc.py
101
102 Returns:
103 Element
104 """
105 properties = {"blocksize": blocksize}
106 properties.update((name, val) for name, val in (("instrument", instrument), ("channel_name", channel_name)) if val is not None)
107 return pipetools.make_element_with_src(pipeline, None, "lal_fakeligosrc", **properties)
108
109
110def fake_aligo(pipeline: pipetools.Pipeline, instrument: str = None, channel_name: str = None, blocksize: int = 16384 * 8 * 1) -> pipetools.Element:
111 """Fake Advanced LIGO Source
112
113 Args:
114 pipeline:
115 Gst.Pipeline, the pipeline to which the new element will be added
116 instrument:
117 str, default None
118 channel_name:
119 str, default None
120 blocksize:
121 int, default 16384 * 8 * 1, Number of samples in each outgoing buffer
122
123 References:
124 Implementation gstlal/gst/python/lal_fakeadvligosrc.py
125
126 Returns:
127 Element
128 """
129 properties = {"blocksize": blocksize}
130 properties.update((name, val) for name, val in (("instrument", instrument), ("channel_name", channel_name)) if val is not None)
131 return pipetools.make_element_with_src(pipeline, None, "lal_fakeadvligosrc", **properties)
132
133
134def fake_avirgo(pipeline: pipetools.Pipeline, instrument: str = None, channel_name: str = None, blocksize: int = 16384 * 8 * 1) -> pipetools.Element:
135 """Fake Advanced Virgo Source
136
137 Args:
138 pipeline:
139 Gst.Pipeline, the pipeline to which the new element will be added
140 instrument:
141 str, default None
142 channel_name:
143 str, default None
144 blocksize:
145 int, default 16384 * 8 * 1, Number of samples in each outgoing buffer
146
147 References:
148 Implementation gstlal/gst/python/lal_fakeadvvirgosrc.py
149
150 Returns:
151 Element
152 """
153 properties = {"blocksize": blocksize}
154 if instrument is not None:
155 properties["instrument"] = instrument
156 if channel_name is not None:
157 properties["channel_name"] = channel_name
158 return pipetools.make_element_with_src(pipeline, None, "lal_fakeadvvirgosrc", **properties)
159
160
161
162def segment(pipeline: pipetools.Pipeline, segment_list: List[Tuple[pipetools.TimeGPS, pipetools.TimeGPS]], blocksize: int = 4096 * 1 * 1,
163 invert_output: bool = False) -> pipetools.Element:
164 """The output is a buffer of boolean values specifying when a list of segments are on and off.
165
166 Args:
167 pipeline:
168 Gst.Pipeline, the pipeline to which the new element will be added
169 segment_list:
170 Iterable[Tuple[TimeGPS, TimeGPS]], list of segment start / stop times
171 blocksize:
172 int, default blocksize is 4096 seconds of unsigned integers at 1 Hz, e.g. segments without nanoseconds
173 invert_output:
174 bool, default False, False = output is high in segments (default), True = output is low in segments
175
176 References:
177 Implementation: gstlal/gst/lal/gstlal_segmentsrc.c
178
179 Returns:
180 Element
181 """
182 return pipetools.make_element_with_src(pipeline, None, "lal_segmentsrc", blocksize=blocksize,
183 segment_list=segments.segmentlist(segments.segment(a.ns(), b.ns()) for a, b in segment_list),
184 invert_output=invert_output)
185
186
187
188def cache(pipeline: pipetools.Pipeline, location: str, use_mmap: bool = True, **properties) -> pipetools.Element:
189 """Retrieve frame files from locations recorded in a LAL cache file.
190
191 Args:
192 pipeline:
193 Gst.Pipeline, the pipeline to which the new element will be added
194 location:
195 str, Path to LAL cache file.
196 use_mmap:
197 bool, default True, if True Use mmap() instead of read()
198 **properties:
199
200 References:
201 Implementation: gstlal/gst/lal/gstlal_cachesrc.c
202
203 Returns:
204 Element
205 """
206 return pipetools.make_element_with_src(pipeline, None, "lal_cachesrc", location=location, use_mmap=use_mmap, **properties)
207
208
209def lvshm(pipeline: pipetools.Pipeline, shm_name: str, **properties) -> pipetools.Element:
210 """LIGO-Virgo shared memory frame file source element
211
212 Args:
213 pipeline:
214 Gst.Pipeline, the pipeline to which the new element will be added
215 shm_name:
216 str, Shared memory partition name. Suggestions: LHO_Data, LLO_Data, VIRGO_Data
217 **properties:
218
219 References:
220 Implementation: gstlal-ugly/gst/gds/lvshmsrc.cc
221
222 Returns:
223 Element
224 """
225 return pipetools.make_element_with_src(pipeline, None, "gds_lvshmsrc", shm_name=shm_name, **properties)
226
227def devshm(pipeline: pipetools.Pipeline, shm_dirname: str, **properties) -> pipetools.Element:
228 """LIGO-Virgo /dev/shm frame file source element
229
230 Args:
231 pipeline:
232 Gst.Pipeline, the pipeline to which the new element will be added
233 shm_dirname:
234 str, Shared memory directory name (full path). Suggestion: /dev/shm/kafka/L1_O3ReplayMDC
235 **properties:
236
237 References:
238 Implementation: gstlal-ugly/gst/gds/devshmsrc.cc
239
240 Returns:
241 Element
242 """
243 return pipetools.make_element_with_src(pipeline, None, "gds_devshmsrc", shm_dirname=shm_dirname, **properties)
244
245
246def framexmit(pipeline: pipetools.Pipeline, multicast_group: str = '0.0.0.0', port: int = 0, **properties) -> pipetools.Element:
247 """FrameXMIT based source element
248
249 Args:
250 pipeline:
251 Gst.Pipeline, the pipeline to which the new element will be added
252 multicast_group:
253 str, default "0.0.0.0", The address of multicast group to join. If no multicast address is supplied, the receiver will listen for
254 UDP/IP broadcast transmissions at the specified port.
255 port:
256 int, default 0, The local port on which to receive broadcasts (0 = allocate). These ports can be reused by multiple applications.
257 **properties:
258
259 References:
260 Implementation: gstlal-ugly/gst/gds/framexmitsrc.cc
261
262 Returns:
263 Element
264 """
265 return pipetools.make_element_with_src(pipeline, None, "gds_framexmitsrc", multicast_group=multicast_group, port=port, **properties)
266
267
268def nds(pipeline: pipetools.Pipeline, host: str, instrument: str, channel_name: str, channel_type: str, blocksize: int = 16384 * 8 * 1, port: int = 31200) -> pipetools.Element:
269 """NDS-based src element
270
271 Args:
272 pipeline:
273 Gst.Pipeline, the pipeline to which the new element will be added
274 host:
275 str, NDS1 or NDS2 remote host name or IP address
276 instrument:
277 str, name of instrument
278 channel_name:
279 str, Name of the desired NDS channel.
280 channel_type:
281 str, Type of the desired NDS channel.
282 blocksize:
283 int, default 16384 * 8 * 1, blocksize
284 port:
285 int, NDS1 or NDS2 remote host port
286
287 References:
288 Implementation: gstlal-ugly/gst/nds/ndssrc.c
289
290 Returns:
291 Element
292 """
293 # default blocksize is 1 second of double precision floats at
294 # 16384 Hz, e.g., LIGO h(t)
295 return pipetools.make_element_with_src(pipeline, None, "ndssrc", blocksize=blocksize, port=port, host=host, channel_name="%s:%s" % (instrument, channel_name),
296 channel_type=channel_type)
297
298
299
300def audio_test(pipeline: pipetools.Pipeline, freq: float = 440, volume: float = 0.8, wave: int = AudioTestWaveform.Sine, samples_per_buffer: int = 1024,
301 **properties) -> pipetools.Element:
302 """AudioTestSrc can be used to generate basic audio signals. It support several different waveforms and
303 allows to set the base frequency and volume. Some waveforms might use additional properties.
304
305 Args:
306 pipeline:
307 Gst.Pipeline, the pipeline to which the new element will be added
308 freq:
309 float, Frequency of test signal. The sample rate needs to be at least 2 times higher.
310 volume:
311 float, default 0.8, Volume of test signal
312 wave:
313 int, default 0, the type of waveform to produce. Options are:
314 sine (0) – Sine
315 square (1) – Square
316 saw (2) – Saw
317 triangle (3) – Triangle
318 silence (4) – Silence
319 white-noise (5) – White uniform noise
320 pink-noise (6) – Pink noise
321 sine-table (7) – Sine table
322 ticks (8) – Periodic Ticks
323 gaussian-noise (9) – White Gaussian noise
324 red-noise (10) – Red (brownian) noise
325 blue-noise (11) – Blue noise
326 violet-noise (12) – Violet noise
327 samples_per_buffer:
328 int, default 1024, Number of samples in each outgoing buffer. Must be at least twice 'freq'
329 **properties:
330
331 References:
332 [1] https://gstreamer.freedesktop.org/documentation/audiotestsrc/index.html?gi-language=python
333
334 Returns:
335 Element
336 """
337 if 'samplesperbuffer' in properties: # support legacy argument name
338 samples_per_buffer = properties.pop('samplesperbuffer')
339 return pipetools.make_element_with_src(pipeline, None, "audiotestsrc", freq=freq, volume=volume, wave=wave,
340 samplesperbuffer=samples_per_buffer, **properties)
341
342
343
344def fake(pipeline: pipetools.Pipeline, instrument: str, channel_name: str, blocksize: int = None, volume: float = 1e-20,
345 is_live: bool = False, wave: int = AudioTestWaveform.GaussianNoise, rate: int = 16384, **properties) -> pipetools.Element:
346 """Create an audio_test source with several additional, lal-specific caps specified
347
348 Args:
349 pipeline:
350 Gst.Pipeline, the pipeline to which the new element will be added
351 instrument:
352 str, name of instrument
353 channel_name:
354 str, name of input channel
355 blocksize:
356 int, default 1 second * rate samples/second * 8
357 volume:
358 float, default 1e-20, the sample volume
359 is_live:
360 bool, default False, whether or not audio_test source will behave like live source
361 wave:
362 int, default 9 (Gaussian Noise), see AudioTestWaveform enum for options
363 rate:
364 int, default 16384, sample rate
365 **properties:
366
367 Returns:
368 Element
369 """
370 if blocksize is None:
371 # default blocksize is 1 second * rate samples/second * 8
372 # bytes/sample (assume double-precision floats)
373 blocksize = 1 * rate * 8
374 caps = filters.caps(pipeline,
375 audio_test(pipeline, samples_per_buffer=int(blocksize / 8), wave=wave,
376 volume=volume, is_live=is_live, **properties),
377 "audio/x-raw, format=F64%s, rate=%d" % (BYTE_ORDER, rate))
378 return transform.tag_inject(pipeline, caps, "instrument=%s,channel-name=%s,units=strain" % (instrument, channel_name))
379
380
381def files(pipeline: pipetools.Pipeline, paths: Iterable[Union[str, pathlib.Path]], instrument: str, channel_name: str,
382 cache_path: Optional[Union[str, pathlib.Path]] = None) -> pipetools.Element:
383 """Create a source from a list of file paths
384
385 Args:
386 pipeline:
387 Gst.Pipeline, the pipeline to which the new element will be added
388 paths:
389 Iterable[Path or str], the full paths to the frame files
390 cache_path:
391 Path or str, default None, the path to write out the cache file if specified, else write to temporary directory
392
393 Notes:
394 This is a convenience utility around cache source and framecppdemux that creates a cache file
395 from a list of file paths
396
397 Returns:
398 Element
399 """
400 cache_path = laltools.create_cache(entries=paths, cache_path=cache_path)
401 src = cache(pipeline, location=cache_path.as_posix())
402
403 demux = mux.framecpp_channel_demux(pipeline, src, do_file_checksum=False, channel_list=["%s:%s" % (instrument, channel_name)])
404 mux.FrameCPPChannelDemuxSetUnitsHandler(demux, dict.fromkeys(demux.get_property("channel-list"), "strain"))
405
406 # allow frame reading and decoding to occur in a different thread
407 src = transform.queue(pipeline, None, max_size_buffers=0, max_size_bytes=0, max_size_time=8 * pipetools.Gst.SECOND)
408 SrcDeferredLink(demux, "%s:%s" % (instrument, channel_name), src.get_static_pad("sink"))
409
410 return src
pipetools.Element devshm(pipetools.Pipeline pipeline, str shm_dirname, **properties)
Definition source.py:227
pipetools.Element cache(pipetools.Pipeline pipeline, str location, bool use_mmap=True, **properties)
Adds a lal_cachesrc element to a pipeline with useful default properties.
Definition source.py:188
pipetools.Element nds(pipetools.Pipeline pipeline, str host, str instrument, str channel_name, str channel_type, int blocksize=16384 *8 *1, int port=31200)
Definition source.py:268
pipetools.Element fake(pipetools.Pipeline pipeline, str instrument, str channel_name, int blocksize=None, float volume=1e-20, bool is_live=False, int wave=AudioTestWaveform.GaussianNoise, int rate=16384, **properties)
see documentation for mktaginject() mkcapsfilter() and mkaudiotestsrc()
Definition source.py:345
pipetools.Element fake_avirgo(pipetools.Pipeline pipeline, str instrument=None, str channel_name=None, int blocksize=16384 *8 *1)
Definition source.py:134
pipetools.Element segment(pipetools.Pipeline pipeline, List[Tuple[pipetools.TimeGPS, pipetools.TimeGPS]] segment_list, int blocksize=4096 *1 *1, bool invert_output=False)
Adds a lal_segmentsrc element to a pipeline with useful default properties.
Definition source.py:163
pipetools.Element fake_ligo(pipetools.Pipeline pipeline, str instrument=None, str channel_name=None, int blocksize=16384 *8 *1)
Definition source.py:86
pipetools.Element fake_aligo(pipetools.Pipeline pipeline, str instrument=None, str channel_name=None, int blocksize=16384 *8 *1)
Definition source.py:110
pipetools.Element framexmit(pipetools.Pipeline pipeline, str multicast_group='0.0.0.0', int port=0, **properties)
Definition source.py:246
pipetools.Element files(pipetools.Pipeline pipeline, Iterable[Union[str, pathlib.Path]] paths, str instrument, str channel_name, Optional[Union[str, pathlib.Path]] cache_path=None)
Definition source.py:382
pipetools.Element audio_test(pipetools.Pipeline pipeline, float freq=440, float volume=0.8, int wave=AudioTestWaveform.Sine, int samples_per_buffer=1024, **properties)
Adds a audiotestsrc element to a pipeline with useful default properties.
Definition source.py:301
pipetools.Element lvshm(pipetools.Pipeline pipeline, str shm_name, **properties)
Definition source.py:209