gstlal 1.13.0
Loading...
Searching...
No Matches
transform.py
1"""Module for general transformation elements
2
3"""
4from typing import Iterable, Tuple, List
5
6import gi
7import numpy
8import os
9
10gi.require_version('Gst', '1.0')
11from gi.repository import GObject
12from gi.repository import Gst
13
14GObject.threads_init()
15Gst.init(None)
16from ligo import segments
17from gstlal import pipeio
18from gstlal.pipeparts import pipetools, filters
19
20
21# a macro to turn on mkchecktimestamps
22if "GSTLAL_CHECK_TIMESTAMPS" in os.environ:
23 GSTLAL_CHECK_TIMESTAMPS = True
24else:
25 GSTLAL_CHECK_TIMESTAMPS = False
26
27
28def integrate(pipeline: pipetools.Pipeline, src: pipetools.Element, template_dur: float = 1.0, **properties) -> pipetools.Element:
29 """Integrates audio channel temp_dur length into the past.
30
31 Args:
32 pipeline:
33 Gst.Pipeline, the pipeline to which the new element will be added
34 src:
35 Gst.Element, the source element
36 **properties:
37
38 References:
39 Implementation: gstlal-ugly/gst/lal/gstlal_integrate.c
40
41 Returns:
42 Element
43 """
44 return pipetools.make_element_with_src(pipeline, src, "lal_integrate", template_dur=template_dur, **properties)
45
46
47def mean(pipeline: pipetools.Pipeline, src: pipetools.Element, **properties) -> pipetools.Element:
48 """Compute mean
49
50 Args:
51 pipeline:
52 Gst.Pipeline, the pipeline to which the new element will be added
53 src:
54 Gst.Element, the source element
55
56 References:
57 Implementation: gstlal-ugly/gst/lal/gstlal_mean.c
58
59 Returns:
60 Element
61 """
62 return pipetools.make_element_with_src(pipeline, src, "lal_mean", **properties)
63
64
65def abs_(pipeline: pipetools.Pipeline, src: pipetools.Element, **properties) -> pipetools.Element:
66 """Compute absolute value
67
68 Args:
69 pipeline:
70 Gst.Pipeline, the pipeline to which the new element will be added
71 src:
72 Gst.Element, the source element
73
74 Returns:
75 Element
76 """
77 return pipetools.make_element_with_src(pipeline, src, "abs", **properties)
78
79
80def pow(pipeline: pipetools.Pipeline, src: pipetools.Element, **properties) -> pipetools.Element:
81 """Compute power
82
83 Args:
84 pipeline:
85 Gst.Pipeline, the pipeline to which the new element will be added
86 src:
87 Gst.Element, the source element
88
89 Returns:
90 Element
91 """
92 return pipetools.make_element_with_src(pipeline, src, "pow", **properties)
93
94
95
96def sum_squares(pipeline: pipetools.Pipeline, src: pipetools.Element, weights: pipetools.ValueArray = None) -> pipetools.Element:
97 """Computes the weighted sum-of-squares of the input channels.
98
99 Args:
100 pipeline:
101 Gst.Pipeline, the pipeline to which the new element will be added
102 src:
103 Gst.Element, the source element
104 weights:
105 ValueArray, default None, Vector of weights to use in sum. If no vector is provided weights of 1.0 are assumed,
106 otherwise the number of input channels must equal the vector length. The incoming channels are first multiplied
107 by the weights, then squared, then summed.
108
109 References:
110 Implementation gstlal/gstlal/gst/lal/gstlal_sumsquares.c
111
112 Returns:
113 Element
114 """
115 if weights is not None:
116 return pipetools.make_element_with_src(pipeline, src, "lal_sumsquares", weights=weights)
117 else:
118 return pipetools.make_element_with_src(pipeline, src, "lal_sumsquares")
119
120
121
122def tag_inject(pipeline: pipetools.Pipeline, src: pipetools.Element, tags: str) -> pipetools.Element:
123 """Element that injects new metadata tags, but passes incoming data through unmodified.
124
125 Args:
126 pipeline:
127 Gst.Pipeline, the pipeline to which the new element will be added
128 src:
129 Gst.Element, the source element
130 tags:
131 str, List of tags to inject into the target file
132
133 References:
134 [1] https://gstreamer.freedesktop.org/documentation/debug/taginject.html?gi-language=python
135
136 Returns:
137 Element, unmodified data with new tags
138 """
139 return pipetools.make_element_with_src(pipeline, src, "taginject", tags=tags)
140
141
142
143def shift(pipeline: pipetools.Pipeline, src: pipetools.Element, **properties) -> pipetools.Element:
144 """Adjust segment events by +shift
145
146 Args:
147 pipeline:
148 Gst.Pipeline, the pipeline to which the new element will be added
149 src:
150 Gst.Element, the source element
151 **properties:
152
153 References:
154 Implementation: gstlal/gst/lal/gstlal_shift.c
155
156 Returns:
157 Element
158 """
159 return pipetools.make_element_with_src(pipeline, src, "lal_shift", **properties)
160
161
162
163def amplify(pipeline: pipetools.Pipeline, src: pipetools.Element, amplification: float) -> pipetools.Element:
164 """Amplifies an audio stream by a given factor and allows the selection of different clipping modes. The
165 difference between the clipping modes is best evaluated by testing.
166
167 Args:
168 pipeline:
169 Gst.Pipeline, the pipeline to which the new element will be added
170 src:
171 Gst.Element, the source element
172 amplification:
173 float, Factor of amplification
174
175 References:
176 [1] https://gstreamer.freedesktop.org/documentation/audiofx/audioamplify.html?gi-language=python
177
178 Returns:
179 Element
180 """
181 return pipetools.make_element_with_src(pipeline, src, "audioamplify", clipping_method=3, amplification=amplification)
182
183
184
185def undersample(pipeline: pipetools.Pipeline, src: pipetools.Element) -> pipetools.Element:
186 """Undersamples an audio stream. Undersampling downsamples by taking every n-th sample, with no antialiasing or
187 low-pass filter. For data confined to a narrow frequency band, this transformation simultaneously downconverts
188 and downsamples the data (otherwise it does weird things). This element's output sample rate must be an integer
189 divisor of its input sample rate.
190
191 Args:
192 pipeline:
193 Gst.Pipeline, the pipeline to which the new element will be added
194 src:
195 Gst.Element, the source element
196
197 References:
198 Implementation: gstlal/gst/lal/gstlal_audioundersample.c
199
200 Returns:
201 Element
202 """
203 return pipetools.make_element_with_src(pipeline, src, "lal_audioundersample")
204
205
206
207def resample(pipeline: pipetools.Pipeline, src: pipetools.Element, **properties) -> pipetools.Element:
208 """Resamples raw audio buffers to different sample rates using a configurable windowing function to enhance quality. By default,
209 the resampler uses a reduced sinc table, with cubic interpolation filling in the gaps. This ensures that the table does not
210 become too big. However, the interpolation increases the CPU usage considerably. As an alternative, a full sinc table can be
211 used. Doing so can drastically reduce CPU usage (4x faster with 44.1 -> 48 kHz conversions for example), at the cost of increased
212 memory consumption, plus the sinc table takes longer to initialize when the element is created. A third mode exists, which uses
213 the full table unless said table would become too large, in which case the interpolated one is used instead.
214
215 Args:
216 pipeline:
217 Gst.Pipeline, the pipeline to which the new element will be added
218 src:
219 Gst.Element, the source element
220 **properties:
221
222 References:
223 [1] https://gstreamer.freedesktop.org/documentation/audioresample/index.html?gi-language=python
224
225 Returns:
226 Element
227 """
228 return pipetools.make_element_with_src(pipeline, src, "audioresample", **properties)
229
230
231
232def interpolator(pipeline: pipetools.Pipeline, src: pipetools.Element, **properties) -> pipetools.Element:
233 """Interpolates multichannel audio data using BLAS
234
235 Args:
236 pipeline:
237 Gst.Pipeline, the pipeline to which the new element will be added
238 src:
239 Gst.Element, the source element
240 **properties:
241
242 References:
243 Implementation: gstlal-ugly/gst/lal/gstlal_interpolator.c
244
245 Returns:
246 Element
247 """
248 return pipetools.make_element_with_src(pipeline, src, "lal_interpolator", **properties)
249
250
251
252def whiten(pipeline: pipetools.Pipeline, src: pipetools.Element, psd_mode: int = 0, zero_pad: int = 0, fft_length: int = 8,
253 average_samples: int = 64, median_samples: int = 7, **properties) -> pipetools.Element:
254 """A PSD estimator and time series whitener.
255
256 Args:
257 pipeline:
258 Gst.Pipeline, the pipeline to which the new element will be added
259 src:
260 Gst.Element, the source element
261 psd_mode:
262 int, default 0, PSD estimation mode. Options are:
263 "GSTLAL_PSDMODE_RUNNING_AVERAGE", Use running average for PSD
264 "GSTLAL_PSDMODE_FIXED", Use fixed spectrum for PSD
265 zero_pad:
266 int, default 0, Length of the zero-padding to include on both sides of the FFT in seconds
267 fft_length:
268 int, default 8, Total length of the FFT convolution (including zero padding) in seconds
269 average_samples:
270 int, default 64, Number of FFTs to be used in PSD average
271 median_samples:
272 int, default 7, Number of FFTs to be used in PSD median history
273 **properties:
274
275 References:
276 Implementation: gstlal/gst/lal/gstlal_whiten.c
277
278 Returns:
279 Element
280 """
281 return pipetools.make_element_with_src(pipeline, src, "lal_whiten", psd_mode=psd_mode, zero_pad=zero_pad, fft_length=fft_length, average_samples=average_samples,
282 median_samples=median_samples,
283 **properties)
284
285
286
287def tee(pipeline: pipetools.Pipeline, src: pipetools.Element) -> pipetools.Element:
288 """Split data to multiple pads. Branching the data flow is useful when e.g. capturing a video where the video is shown on
289 the screen and also encoded and written to a file. Another example is playing music and hooking up a visualisation module.
290 One needs to use separate queue elements (or a multiqueue) in each branch to provide separate threads for each branch.
291 Otherwise a blocked dataflow in one branch would stall the other branches.
292
293 Args:
294 pipeline:
295 Gst.Pipeline, the pipeline to which the new element will be added
296 src:
297 Gst.Element, the source element
298
299 References:
300 [1] https://gstreamer.freedesktop.org/documentation/coreelements/tee.html?gi-language=python
301
302 Returns:
303 Element
304 """
305 return pipetools.make_element_with_src(pipeline, src, "tee")
306
307
308
309def adder(pipeline: pipetools.Pipeline, srcs: Iterable[pipetools.Element], sync: bool = True, mix_mode: str = "sum", **properties) -> pipetools.Element:
310 """The adder allows to mix several streams into one by adding the data. Mixed data is clamped to the min/max
311 values of the data format. If the element's sync property is TRUE the streams are mixed with the timestamps
312 synchronized. If the sync property is FALSE (the default, to be compatible with older versions), then the
313 first samples from each stream are added to produce the first sample of the output, the second samples are
314 added to produce the second sample of the output, and so on.
315
316 Args:
317 pipeline:
318 Gst.Pipeline, the pipeline to which the new element will be added
319 srcs:
320 Iterable[Gst.Element], the source elements
321 sync:
322 bool, default True, Align the time stamps of input streams
323 mix_mode:
324 str, default 'sum', Algorithm for mixing the input streams, options: "sum", "product"
325 **properties:
326
327 References:
328 Implementation: gstlal/gst/lal/gstadder.c
329
330 Returns:
331 Element
332 """
333 elem = pipetools.make_element_with_src(pipeline, None, "lal_adder", sync=sync, mix_mode=mix_mode, **properties)
334 if srcs is not None:
335 for src in srcs:
336 src.link(elem)
337 return elem
338
339
340
341def multiplier(pipeline: pipetools.Pipeline, srcs: Iterable[pipetools.Element], sync: bool = True, mix_mode: str = "product", **properties) -> pipetools.Element:
342 """Helper function around adder that defaults to a mix mode of "product"
343
344 Args:
345 pipeline:
346 Gst.Pipeline, the pipeline to which the new element will be added
347 srcs:
348 Iterable[Gst.Element], the source elements
349 sync:
350 bool, default True, Align the time stamps of input streams
351 mix_mode:
352 str, default 'product', Algorithm for mixing the input streams, options: "sum", "product"
353 **properties:
354
355 References:
356 Implementation: gstlal/gst/lal/gstadder.c
357
358 Returns:
359 Element
360 """
361 return adder(pipeline, srcs, sync=sync, mix_mode=mix_mode, **properties)
362
363
364
365def queue(pipeline: pipetools.Pipeline, src: pipetools.Element, **properties) -> pipetools.Element:
366 """Data is queued until one of the limits specified by the , and/or properties has been reached. Any attempt to push
367 more buffers into the queue will block the pushing thread until more space becomes available. The queue will create a
368 new thread on the source pad to decouple the processing on sink and source pad. You can query how many buffers are
369 queued by reading the property. You can track changes by connecting to the notify::current-level-buffers signal (which
370 like all signals will be emitted from the streaming thread). The same applies to the and properties. The default queue
371 size limits are 200 buffers, 10MB of data, or one second worth of data, whichever is reached first. As said earlier, the
372 queue blocks by default when one of the specified maximums (bytes, time, buffers) has been reached. You can set the
373 property to specify that instead of blocking it should leak (drop) new or old buffers. The signal is emitted when the
374 queue has less data than the specified minimum thresholds require (by default: when the queue is empty). The signal is
375 emitted when the queue is filled up. Both signals are emitted from the context of the streaming thread.
376
377 Args:
378 pipeline:
379 Gst.Pipeline, the pipeline to which the new element will be added
380 src:
381 Gst.Element, the source element
382 **properties:
383
384 References:
385 [1] https://gstreamer.freedesktop.org/documentation/coreelements/queue.html?gi-language=python
386
387 Returns:
388 Element
389 """
390 return pipetools.make_element_with_src(pipeline, src, "queue", **properties)
391
392
393
394def fir_bank(pipeline: pipetools.Pipeline, src: pipetools.Element, latency: int = None, fir_matrix: numpy.ndarray = None, time_domain: bool = None,
395 block_stride: int = None) -> pipetools.Element:
396 """Projects a single audio channel onto a bank of FIR filters to produce a multi-channel output
397
398 Args:
399 pipeline:
400 Gst.Pipeline, the pipeline to which the new element will be added
401 src:
402 Gst.Element, the source element
403 latency:
404 int, default None, Filter latency in samples.
405 fir_matrix:
406 numpy.ndarray, default None, Array of impulse response vectors. Number of vectors (rows) in matrix sets number of output channels. All filters
407 must have the same length.
408 time_domain:
409 bool, default None, Set to true to use time-domain (a.k.a. direct) convolution, set to false to use FFT-based convolution.
410 For long filters FFT-based convolution is usually significantly faster than time-domain convolution but incurs a higher processing
411 latency and requires more RAM.
412 block_stride:
413 int, default None, When using FFT convolutions, this many samples will be produced from each block. Smaller values decrease latency
414 but increase computational cost. If very small values are desired, consider using time-domain convolution mode instead.
415
416 References:
417 Implementation: gstlal/gst/lal/gstlal_firbank.c
418
419 Returns:
420 Element
421 """
422 properties = dict((name, value) for name, value in zip(("latency", "fir_matrix", "time_domain", "block_stride"),
423 (latency, fir_matrix, time_domain, block_stride)) if value is not None)
424 return pipetools.make_element_with_src(pipeline, src, "lal_firbank", **properties)
425
426
427def td_whiten(pipeline: pipetools.Pipeline, src: pipetools.Element, latency: int = None, kernel: numpy.ndarray = None, taper_length: int = None):
428 """Generic audio FIR filter with custom filter kernel and smooth kernel updates
429
430 Args:
431 pipeline:
432 Gst.Pipeline, the pipeline to which the new element will be added
433 src:
434 Gst.Element, the source element
435 latency:
436 int, default None, Filter latency in samples.
437 kernel:
438 array, default None, The newest kernel.
439 taper_length:
440 int, default None, Number of samples for kernel transition.
441
442 References:
443 Implementation: gstlal-ugly/gst/lal/gstlal_tdwhiten.c
444
445 Returns:
446 Element
447 """
448 # a taper length of 1/4 kernel length mimics the default
449 # configuration of the FFT whitener
450 if taper_length is None and kernel is not None:
451 taper_length = len(kernel) // 4
452 properties = dict((name, value) for name, value in zip(("latency", "kernel", "taper_length"),
453 (latency, kernel, taper_length)) if value is not None)
454 return pipetools.make_element_with_src(pipeline, src, "lal_tdwhiten", **properties)
455
456
457def trim(pipeline: pipetools.Pipeline, src: pipetools.Element, initial_offset: int = None, final_offset: int = None, inverse: bool = None) -> pipetools.Element:
458 """Pass data only inside a region and mark everything else as gaps. The offsets are media-type specific. For audio
459 buffers, it's the number of samples produced so far. For video buffers, it's generally the frame number. For compressed
460 data, it could be the byte offset in a source or destination file. If inverse=true is set, only data *outside* of the
461 specified region will pass, and data in the inside will be marked as gaps.
462
463 Args:
464 pipeline:
465 Gst.Pipeline, the pipeline to which the new element will be added
466 src:
467 Gst.Element, the source element
468 initial_offset:
469 int, default None, Only let data with offset bigger than this value pass.
470 final_offset:
471 int, default None, Only let data with offset smaller than this value pass
472 inverse:
473 bool, default None, If True only data *outside* the region will pass.
474
475 References:
476 Implementation: gstlal-ugly/gst/lal/gstlal_trim.c
477
478 Returns:
479 Element
480 """
481 properties = dict((name, value) for name, value in zip(("initial-offset", "final-offset", "inverse"),
482 (initial_offset, final_offset, inverse)) if value is not None)
483 return pipetools.make_element_with_src(pipeline, src, "lal_trim", **properties)
484
485
486
487def reblock(pipeline: pipetools.Pipeline, src: pipetools.Element, **properties) -> pipetools.Element:
488 """Chop audio buffers into smaller pieces to enforce a maximum allowed buffer duration
489
490 Args:
491 pipeline:
492 Gst.Pipeline, the pipeline to which the new element will be added
493 src:
494 Gst.Element, the source element
495 **properties:
496 block_duration:
497 int, Maximum output buffer duration in nanoseconds. Buffers may be smaller than this.
498
499 References:
500 Implementation: gstlal/gst/lal/gstlal_reblock.c
501
502 Returns:
503 Element
504 """
505 return pipetools.make_element_with_src(pipeline, src, "lal_reblock", **properties)
506
507
508def bit_vector_gen(pipeline: pipetools.Pipeline, src: pipetools.Element, bit_vector: int, **properties) -> pipetools.Element:
509 """Generate a bit vector stream based on the value of a control input
510
511 Args:
512 pipeline:
513 Gst.Pipeline, the pipeline to which the new element will be added
514 src:
515 Gst.Element, the source element
516 bit_vector:
517 int, Value to generate when output is \"on\" (output is 0 otherwise). Only as many
518 low-order bits as are needed by the output word size will be used.
519 **properties:
520
521 References:
522 Implementation: gstlal-ugly/gst/lal/gstlal_bitvectorgen.c
523
524 Returns:
525 Element
526 """
527 return pipetools.make_element_with_src(pipeline, src, "lal_bitvectorgen", bit_vector=bit_vector, **properties)
528
529
530
531def matrix_mixer(pipeline: pipetools.Pipeline, src: pipetools.Element, matrix: numpy.ndarray = None) -> pipetools.Element:
532 """A many-to-many mixer
533
534 Args:
535 pipeline:
536 Gst.Pipeline, the pipeline to which the new element will be added
537 src:
538 Gst.Element, the source element
539 matrix:
540 array, Matrix of mixing coefficients. Number of rows in matrix sets number of input channels,
541 number of columns sets number of output channels.
542
543 References:
544 Implementation: gstlal/gst/lal/gstlal_matrixmixer.c
545
546 Returns:
547 Element
548 """
549 if matrix is not None:
550 return pipetools.make_element_with_src(pipeline, src, "lal_matrixmixer", matrix=matrix)
551 else:
552 return pipetools.make_element_with_src(pipeline, src, "lal_matrixmixer")
553
554
555
556def toggle_complex(pipeline: pipetools.Pipeline, src: pipetools.Element) -> pipetools.Element:
557 """Replace float caps with complex (with half the channels), complex with float (with twice the channels).
558
559 Args:
560 pipeline:
561 Gst.Pipeline, the pipeline to which the new element will be added
562 src:
563 Gst.Element, the source element
564
565 References:
566 Implementation: gstlal/gst/lal/gstlal_togglecomplex.c
567
568 Returns:
569 Element
570 """
571 return pipetools.make_element_with_src(pipeline, src, "lal_togglecomplex")
572
573
574
575def auto_chisq(pipeline: pipetools.Pipeline, src: pipetools.Element, autocorrelation_matrix: numpy.ndarray = None, mask_matrix=None,
576 latency: int = 0, snr_thresh: int = 0) -> pipetools.Element:
577 """Computes the chisquared time series from a filter's autocorrelation
578
579 Args:
580 pipeline:
581 Gst.Pipeline, the pipeline to which the new element will be added
582 src:
583 Gst.Element, the source element
584 autocorrelation_matrix:
585 array, default None, Array of complex autocorrelation vectors. Number of vectors (rows) in matrix sets
586 number of channels. All vectors must have the same length.
587 mask_matrix:
588 array, default None, Array of integer mask vectors. Matrix must be the same size as the autocorrelation
589 matrix. Only autocorrelation vector samples corresponding to non-zero samples in these vectors will be
590 used to construct the \\chi^{2} statistic. If this matrix is not supplied, all autocorrelation samples
591 are used.
592 latency:
593 int, default 0, Filter latency in samples. Must be in (-autocorrelation length, 0].
594 snr_thresh:
595 float, default 0, SNR Threshold that determines a trigger.
596
597 References:
598 Implementation: gstlal/gst/lal/gstlal_autochisq.c
599
600 Returns:
601 Element
602 """
603 properties = {}
604 if autocorrelation_matrix is not None:
605 properties.update({
606 "autocorrelation_matrix": pipeio.repack_complex_array_to_real(autocorrelation_matrix),
607 "latency": latency,
608 "snr_thresh": snr_thresh
609 })
610 if mask_matrix is not None:
611 properties["autocorrelation_mask_matrix"] = mask_matrix
612 return pipetools.make_element_with_src(pipeline, src, "lal_autochisq", **properties)
613
614
615def colorspace(pipeline: pipetools.Pipeline, src: pipetools.Element) -> pipetools.Element:
616 """Convert video frames between a great variety of video formats.
617
618 Args:
619 pipeline:
620 Gst.Pipeline, the pipeline to which the new element will be added
621 src:
622 Gst.Element, the source element
623
624 References:
625 Pre gstreamer-1.0 docs: (ffmpegcolorspace) https://www.freedesktop.org/software/gstreamer-sdk/data/docs/2012.5/gst-plugins-base-plugins-0.10/gst-plugins-base-plugins-ffmpegcolorspace.html
626 Post gstreamer-1.0 docs: (videoconvert) https://gstreamer.freedesktop.org/documentation/videoconvert/index.html?gi-language=python
627 Migration: https://gstreamer.freedesktop.org/documentation/application-development/appendix/porting-1-0.html?gi-language=c
628
629 Returns:
630 Element
631 """
632 return pipetools.make_element_with_src(pipeline, src, "videoconvert")
633
634
635
636def audio_convert(pipeline: pipetools.Pipeline, src: pipetools.Element, caps_string: str = None) -> pipetools.Element:
637 """Audioconvert converts raw audio buffers between various possible formats. It supports integer to float conversion,
638 width/depth conversion, signedness and endianness conversion and channel transformations (ie. upmixing and downmixing),
639 as well as dithering and noise-shaping.
640
641 Args:
642 pipeline:
643 Gst.Pipeline, the pipeline to which the new element will be added
644 src:
645 Gst.Element, the source element
646 caps_string:
647 str, Caps string
648
649 References:
650 [1] https://gstreamer.freedesktop.org/documentation/audioconvert/index.html?gi-language=python
651
652 Returns:
653 Element
654 """
655 elem = pipetools.make_element_with_src(pipeline, src, "audioconvert")
656 if caps_string is not None:
657 elem = filters.caps(pipeline, elem, caps_string)
658 return elem
659
660
661
662def audio_rate(pipeline: pipetools.Pipeline, src: pipetools.Element, **properties) -> pipetools.Element:
663 """This element takes an incoming stream of timestamped raw audio frames and produces a perfect stream by
664 inserting or dropping samples as needed. This operation may be of use to link to elements that require or
665 otherwise implicitly assume a perfect stream as they do not store timestamps, but derive this by some means
666 (e.g. bitrate for some AVI cases). The properties , , and can be read to obtain information about number of
667 input samples, output samples, dropped samples (i.e. the number of unused input samples) and inserted samples
668 (i.e. the number of samples added to stream). When the property is set to FALSE, a GObject property notification
669 will be emitted whenever one of the or values changes. This can potentially cause performance degradation. Note
670 that property notification will happen from the streaming thread, so applications should be prepared for this. If
671 the property is non-zero, and an incoming buffer's timestamp deviates less than the property indicates from what
672 would make a 'perfect time', then no samples will be added or dropped. Note that the output is still guaranteed to
673 be a perfect stream, which means that the incoming data is then simply shifted (by less than the indicated tolerance)
674 to a perfect time.
675
676 Args:
677 pipeline:
678 Gst.Pipeline, the pipeline to which the new element will be added
679 src:
680 Gst.Element, the source element
681 **properties:
682
683 References:
684 [1] https://gstreamer.freedesktop.org/documentation/audiorate/index.html?gi-language=python
685
686 Returns:
687 Element
688 """
689 return pipetools.make_element_with_src(pipeline, src, "audiorate", **properties)
690
691
692def deglitch(pipeline: pipetools.Pipeline, src: pipetools.Element, segment_list: List[Tuple[pipetools.TimeGPS, pipetools.TimeGPS]]) -> pipetools.Element:
693 """Removes glitches based on a segment list. Must be coalesced.
694
695 Args:
696 pipeline:
697 Gst.Pipeline, the pipeline to which the new element will be added
698 src:
699 Gst.Element, the source element
700 segment_list:
701 Iterable[Tuple[TimeGPS, TimeGPS]], list of segment start / stop times
702
703 References:
704 Implementation: gstlal-ugly/gst/lal/gstlaldeglitchfilter.c
705
706 Returns:
707 Element
708 """
709 return pipetools.make_element_with_src(pipeline, src, "lal_deglitcher", segment_list=segments.segmentlist(segments.segment(a.ns(), b.ns()) for a, b in segment_list))
710
711
712def check_timestamps(pipeline: pipetools.Pipeline, src: pipetools.Element, name: str = None, silent: bool = True, timestamp_fuzz: int = 1) -> pipetools.Element:
713 """Timestamp Checker Pass-Through Element
714
715 Args:
716 pipeline:
717 Gst.Pipeline, the pipeline to which the new element will be added
718 src:
719 Gst.Element, the source element
720 name:
721 str, name of check
722 silent:
723 bool, default True, Only report errors.
724 timestamp_fuzz:
725 int, Number of nanoseconds of timestamp<-->offset discrepancy to accept before reporting it. Timestamp<-->offset discrepancies
726 of 1/2 a sample or more are always reported.
727
728 References:
729 Implementation: gstlal/gst/python/lal_checktimestamps.py
730
731 Returns:
732 Element
733 """
734 if GSTLAL_CHECK_TIMESTAMPS == True:
735 return pipetools.make_element_with_src(pipeline, src, "lal_checktimestamps", name=name, silent=silent, timestamp_fuzz=timestamp_fuzz)
736 else:
737 return src
738
739
740
741def peak(pipeline: pipetools.Pipeline, src: pipetools.Element, n: int) -> pipetools.Element:
742 """Find peaks in a time series every n samples
743
744 Args:
745 pipeline:
746 Gst.Pipeline, the pipeline to which the new element will be added
747 src:
748 Gst.Element, the source element
749 n:
750 int, number of samples over which to identify peaks
751
752 References:
753 Implementation: gstlal/gst/lal/gstlal_peak.c
754
755 Returns:
756 Element
757 """
758 return pipetools.make_element_with_src(pipeline, src, "lal_peak", n=n)
759
760
761def denoise(pipeline: pipetools.Pipeline, src: pipetools.Element, **properties) -> pipetools.Element:
762 """Separate out stationary/non-stationary components from signals.
763
764 Args:
765 pipeline:
766 Gst.Pipeline, the pipeline to which the new element will be added
767 src:
768 Gst.Element, the source element
769 **properties:
770
771 References:
772 Implementation: gstlal-ugly/gst/lal/gstlal_denoiser.c
773
774 Returns:
775 Element
776 """
777 return pipetools.make_element_with_src(pipeline, src, "lal_denoiser", **properties)
778
779
780def clean(pipeline: pipetools.Pipeline, src: pipetools.Element, threshold: float = 1.0) -> pipetools.Element:
781 """Helper function for denoise that cleans for a stationary, threshold
782
783 Args:
784 pipeline:
785 Gst.Pipeline, the pipeline to which the new element will be added
786 src:
787 Gst.Element, the source element
788 threshold:
789 float, default 1.0, The threshold in which to allow non-stationary signals in stationary component
790
791 Returns:
792 Element
793 """
794 return denoise(pipeline, src, stationary=True, threshold=threshold)
795
796
797def latency(pipeline: pipetools.Pipeline, src: pipetools.Element, name: str = None, silent: bool = False) -> pipetools.Element:
798 """Outputs the current GPS time at time of data flow
799
800 Args:
801 pipeline:
802 Gst.Pipeline, the pipeline to which the new element will be added
803 src:
804 Gst.Element, the source element
805 name:
806 str, name
807 silent:
808 bool, if True run silent
809
810 References:
811 Implementation: gstlal-ugly/gst/lal/gstlal_latency.c
812
813 Returns:
814 Element
815 """
816 return pipetools.make_element_with_src(pipeline, src, "lal_latency", name=name, silent=silent)
817
818
819
820def set_caps(pipeline: pipetools.Pipeline, src: pipetools.Element, caps: pipetools.Caps, **properties) -> pipetools.Element:
821 """Sets or merges caps on a stream's buffers. That is, a buffer's caps are updated using (fields of) “caps”. Note that this
822 may contain multiple structures (though not likely recommended), but each of these must be fixed (or will otherwise be rejected).
823
824 If “join” is TRUE, then the incoming caps' mime-type is compared to the mime-type(s) of provided caps and only matching
825 structure(s) are considered for updating.
826
827 If “replace” is TRUE, then any caps update is preceded by clearing existing fields, making provided fields (as a whole)
828 replace incoming ones. Otherwise, no clearing is performed, in which case provided fields are added/merged onto incoming caps
829
830 Although this element might mainly serve as debug helper, it can also practically be used to correct a faulty pixel-aspect-ratio,
831 or to modify a yuv fourcc value to effectively swap chroma components or such alike.
832
833 Args:
834 pipeline:
835 Gst.Pipeline, the pipeline to which the new element will be added
836 src:
837 Gst.Element, the source element
838 caps:
839 Gst.Caps, the caps
840 **properties:
841
842 References:
843 [1] https://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-good/html/gst-plugins-good-plugins-capssetter.html
844
845 Returns:
846 Element
847 """
848 return pipetools.make_element_with_src(pipeline, src, "capssetter", caps=Gst.Caps.from_string(caps), **properties)
849
850
851
852def progress_report(pipeline: pipetools.Pipeline, src: pipetools.Element, name: str):
853 """The progressreport element can be put into a pipeline to report progress, which is done by doing upstream
854 duration and position queries in regular (real-time) intervals. Both the interval and the preferred query format
855 can be specified via the and the property.
856
857 Element messages containing a "progress" structure are posted on the bus whenever progress has been queried
858 (since gst-plugins-good 0.10.6 only).
859
860 Since the element was originally designed for debugging purposes, it will by default also print information
861 about the current progress to the terminal. This can be prevented by setting the property to True.
862
863 This element is most useful in transcoding pipelines or other situations where just querying the pipeline might
864 not lead to the wanted result. For progress in TIME format, the element is best placed in a 'raw stream' section
865 of the pipeline (or after any demuxers/decoders/parsers).
866
867 Three more things should be pointed out:
868 First, the element will only query progress when data flow happens. If data flow is stalled for some reason, no
869 progress messages will be posted.
870
871 Second, there are other elements (like qtdemux, for example) that may also post "progress" element messages on the bus.
872 Applications should check the source of any element messages they receive, if needed.
873
874 Third, applications should not take action on receiving notification of progress being 100%, they should only take action
875 when they receive an EOS message (since the progress reported is in reference to an internal point of a pipeline and
876 not the pipeline as a whole).
877
878 Args:
879 pipeline:
880 Gst.Pipeline, the pipeline to which the new element will be added
881 src:
882 Gst.Element, the source element
883 name:
884 str, the name
885
886 References:
887 [1] https://gstreamer.freedesktop.org/documentation/debug/progressreport.html?gi-language=python
888
889 Returns:
890 Element
891 """
892 return pipetools.make_element_with_src(pipeline, src, "progressreport", do_query=False, name=name)
893
894
895# TODO move to calibration specific module
896def lho_coherent_null(pipeline: pipetools.Pipeline, H1src: pipetools.Element, H2src: pipetools.Element, H1_impulse, H1_latency, H2_impulse, H2_latency,
897 srate: int) -> pipetools.Element:
898 """LHO Coherent and Null Streams
899
900 Args:
901 pipeline:
902 Gst.Pipeline, the pipeline to which the new element will be added
903 H1src:
904 Element, h1 source
905 H2src:
906 Element, h2 source
907 H1_impulse:
908 impulse response for H1
909 H1_latency:
910 latency for H1
911 H2_impulse:
912 impulse response for H2
913 H2_latency:
914 latency for H2
915 srate:
916 int, block stride for fir bank
917
918 References:
919 Implementation: gstlal/gst/python/lal_lho_coherent_null.py
920
921 Returns:
922 Element
923 """
924 elem = pipetools.make_element_with_src(pipeline, None, "lal_lho_coherent_null", block_stride=srate, H1_impulse=H1_impulse, H2_impulse=H2_impulse, H1_latency=H1_latency,
925 H2_latency=H2_latency)
926 for peer, padname in ((H1src, "H1sink"), (H2src, "H2sink")):
927 if isinstance(peer, Gst.Pad):
928 peer.get_parent_element().link_pads(peer, elem, padname)
929 elif peer is not None:
930 peer.link_pads(None, elem, padname)
931 return elem
932
933
934# TODO move to calibration specific module
935def mkcomputegamma(pipeline, dctrl, exc, cos, sin, **properties):
936 """Compute Gamma
937
938 Args:
939 pipeline:
940 dctrl:
941 exc:
942 cos:
943 sin:
944 **properties:
945
946 References:
947 Implementation: gstlal-calibration/gst/python/lal_compute_gamma.py
948
949 Returns:
950 Element
951 """
952 elem = pipetools.make_element_with_src(pipeline, None, "lal_compute_gamma", **properties)
953 for peer, padname in ((dctrl, "dctrl_sink"), (exc, "exc_sink"), (cos, "cos"), (sin, "sin")):
954 if isinstance(peer, Gst.Pad):
955 peer.get_parent_element().link_pads(peer, elem, padname)
956 elif peer is not None:
957 peer.link_pads(None, elem, padname)
958 return elem
959
960
961# TODO find source for lal_odc_to_dqv or delete
962def mkodctodqv(pipeline, src, **properties):
963 return pipetools.make_element_with_src(pipeline, src, "lal_odc_to_dqv", **properties)
964
965
966# TODO move this somewhere else, it's not a transform element
967def audioresample_variance_gain(quality: int, num: int, den: int) -> float:
968 """Calculate the output gain of GStreamer's stock audioresample element.
969
970 The audioresample element has a frequency response of unity "almost" all the
971 way up the Nyquist frequency. However, for an input of unit variance
972 Gaussian noise, the output will have a variance very slighly less than 1.
973 The return value is the variance that the filter will produce for a given
974 "quality" setting and sample rate.
975
976 @param den The denomenator of the ratio of the input and output sample rates
977 @param num The numerator of the ratio of the input and output sample rates
978 @return The variance of the output signal for unit variance input
979
980 The following example shows how to apply the correction factor using an
981 audioamplify element.
982
983 >>> from gstlal.pipeutil import *
984 >>> from gstlal.pipeparts import audioresample_variance_gain
985 >>> from gstlal import pipeio
986 >>> import numpy
987 >>> nsamples = 2 ** 17
988 >>> num = 2
989 >>> den = 1
990 >>> def handoff_handler(element, buffer, pad, (quality, filt_len, num, den)):
991 ... out_latency = numpy.ceil(float(den) / num * filt_len)
992 ... buf = pipeio.array_from_audio_buffer(buffer).flatten()
993 ... std = numpy.std(buf[out_latency:-out_latency])
994 ... print "quality=%2d, filt_len=%3d, num=%d, den=%d, stdev=%.2f" % (
995 ... quality, filt_len, num, den, std)
996 ...
997 >>> for quality in range(11):
998 ... pipeline = Gst.Pipeline()
999 ... correction = 1/numpy.sqrt(audioresample_variance_gain(quality, num, den))
1000 ... elems = mkelems_in_bin(pipeline,
1001 ... ('audiotestsrc', {'wave':'gaussian-noise','volume':1}),
1002 ... ('capsfilter', {'caps':Gst.Caps.from_string('audio/x-raw,format=F64LE,rate=%d' % num)}),
1003 ... ('audioresample', {'quality':quality}),
1004 ... ('capsfilter', {'caps':Gst.Caps.from_string('audio/x-raw,width=F64LE,rate=%d' % den)}),
1005 ... ('audioamplify', {'amplification':correction,'clipping-method':'none'}),
1006 ... ('fakesink', {'signal-handoffs':True, 'num-buffers':1})
1007 ... )
1008 ... filt_len = elems[2].get_property('filter-length')
1009 ... elems[0].set_property('samplesperbuffer', 2 * filt_len + nsamples)
1010 ... if elems[-1].connect_after('handoff', handoff_handler, (quality, filt_len, num, den)) < 1:
1011 ... raise RuntimeError
1012 ... try:
1013 ... if pipeline.set_state(Gst.State.PLAYING) is not Gst.State.CHANGE_ASYNC:
1014 ... raise RuntimeError
1015 ... if not pipeline.get_bus().poll(Gst.MessageType.EOS, -1):
1016 ... raise RuntimeError
1017 ... finally:
1018 ... if pipeline.set_state(Gst.State.NULL) is not Gst.StateChangeReturn.SUCCESS:
1019 ... raise RuntimeError
1020 ...
1021 quality= 0, filt_len= 8, num=2, den=1, stdev=1.00
1022 quality= 1, filt_len= 16, num=2, den=1, stdev=1.00
1023 quality= 2, filt_len= 32, num=2, den=1, stdev=1.00
1024 quality= 3, filt_len= 48, num=2, den=1, stdev=1.00
1025 quality= 4, filt_len= 64, num=2, den=1, stdev=1.00
1026 quality= 5, filt_len= 80, num=2, den=1, stdev=1.00
1027 quality= 6, filt_len= 96, num=2, den=1, stdev=1.00
1028 quality= 7, filt_len=128, num=2, den=1, stdev=1.00
1029 quality= 8, filt_len=160, num=2, den=1, stdev=1.00
1030 quality= 9, filt_len=192, num=2, den=1, stdev=1.00
1031 quality=10, filt_len=256, num=2, den=1, stdev=1.00
1032 """
1033
1034 # These constants were measured with 2**22 samples.
1035
1036 if num > den: # downsampling
1037 return den * (
1038 0.7224862140943990596,
1039 0.7975021342935247892,
1040 0.8547537598970208483,
1041 0.8744072146753004704,
1042 0.9075294214410336568,
1043 0.9101523813406768859,
1044 0.9280549396020538744,
1045 0.9391809530012216189,
1046 0.9539276644089494939,
1047 0.9623083437067311285,
1048 0.9684700588501590213
1049 )[quality] / num
1050 elif num < den: # upsampling
1051 return (
1052 0.7539740617648067467,
1053 0.8270076656536116122,
1054 0.8835072979478705291,
1055 0.8966758456219333651,
1056 0.9253434087537378838,
1057 0.9255866674042573239,
1058 0.9346487800036394900,
1059 0.9415331868209220190,
1060 0.9524608799160205752,
1061 0.9624372769883490220,
1062 0.9704505626409354324
1063 )[quality]
1064 else: # no change in sample rate
1065 return 1.
pipetools.Element set_caps(pipetools.Pipeline pipeline, pipetools.Element src, pipetools.Caps caps, **properties)
Adds a capssetter element to a pipeline with useful default properties.
Definition transform.py:820
pipetools.Element audio_rate(pipetools.Pipeline pipeline, pipetools.Element src, **properties)
Adds a audiorate element to a pipeline with useful default properties.
Definition transform.py:662
pipetools.Element toggle_complex(pipetools.Pipeline pipeline, pipetools.Element src)
Adds a lal_togglecomplex element to a pipeline with useful default properties.
Definition transform.py:556
pipetools.Element lho_coherent_null(pipetools.Pipeline pipeline, pipetools.Element H1src, pipetools.Element H2src, H1_impulse, H1_latency, H2_impulse, H2_latency, int srate)
Definition transform.py:897
pipetools.Element whiten(pipetools.Pipeline pipeline, pipetools.Element src, int psd_mode=0, int zero_pad=0, int fft_length=8, int average_samples=64, int median_samples=7, **properties)
Adds a lal_whiten element to a pipeline with useful default properties.
Definition transform.py:253
pipetools.Element undersample(pipetools.Pipeline pipeline, pipetools.Element src)
Adds a lal_audioundersample element to a pipeline with useful default properties.
Definition transform.py:185
pipetools.Element deglitch(pipetools.Pipeline pipeline, pipetools.Element src, List[Tuple[pipetools.TimeGPS, pipetools.TimeGPS]] segment_list)
Definition transform.py:692
pipetools.Element multiplier(pipetools.Pipeline pipeline, Iterable[pipetools.Element] srcs, bool sync=True, str mix_mode="product", **properties)
Adds a lal_adder element to a pipeline configured for synchronous "product" mode mixing.
Definition transform.py:341
float audioresample_variance_gain(int quality, int num, int den)
Definition transform.py:967
pipetools.Element tee(pipetools.Pipeline pipeline, pipetools.Element src)
Adds a tee element to a pipeline with useful default properties.
Definition transform.py:287
pipetools.Element adder(pipetools.Pipeline pipeline, Iterable[pipetools.Element] srcs, bool sync=True, str mix_mode="sum", **properties)
Adds a lal_adder element to a pipeline configured for synchronous "sum" mode mixing.
Definition transform.py:309
pipetools.Element denoise(pipetools.Pipeline pipeline, pipetools.Element src, **properties)
Definition transform.py:761
pipetools.Element interpolator(pipetools.Pipeline pipeline, pipetools.Element src, **properties)
Adds a lal_interpolator element to a pipeline with useful default properties.
Definition transform.py:232
pipetools.Element sum_squares(pipetools.Pipeline pipeline, pipetools.Element src, pipetools.ValueArray weights=None)
Adds a lal_sumsquares element to a pipeline with useful default properties.
Definition transform.py:96
pipetools.Element abs_(pipetools.Pipeline pipeline, pipetools.Element src, **properties)
Definition transform.py:65
pipetools.Element check_timestamps(pipetools.Pipeline pipeline, pipetools.Element src, str name=None, bool silent=True, int timestamp_fuzz=1)
Definition transform.py:712
pipetools.Element tag_inject(pipetools.Pipeline pipeline, pipetools.Element src, str tags)
Adds a taginject element to a pipeline with useful default properties.
Definition transform.py:122
pipetools.Element reblock(pipetools.Pipeline pipeline, pipetools.Element src, **properties)
Adds a lal_reblock element to a pipeline with useful default properties.
Definition transform.py:487
pipetools.Element trim(pipetools.Pipeline pipeline, pipetools.Element src, int initial_offset=None, int final_offset=None, bool inverse=None)
Definition transform.py:457
pipetools.Element audio_convert(pipetools.Pipeline pipeline, pipetools.Element src, str caps_string=None)
Adds a audioconvert element to a pipeline with useful default properties.
Definition transform.py:636
pipetools.Element bit_vector_gen(pipetools.Pipeline pipeline, pipetools.Element src, int bit_vector, **properties)
Definition transform.py:508
td_whiten(pipetools.Pipeline pipeline, pipetools.Element src, int latency=None, numpy.ndarray kernel=None, int taper_length=None)
Definition transform.py:427
mkcomputegamma(pipeline, dctrl, exc, cos, sin, **properties)
Definition transform.py:935
pipetools.Element mean(pipetools.Pipeline pipeline, pipetools.Element src, **properties)
Definition transform.py:47
pipetools.Element latency(pipetools.Pipeline pipeline, pipetools.Element src, str name=None, bool silent=False)
Definition transform.py:797
pipetools.Element amplify(pipetools.Pipeline pipeline, pipetools.Element src, float amplification)
Adds a audioamplify element to a pipeline with useful default properties.
Definition transform.py:163
pipetools.Element pow(pipetools.Pipeline pipeline, pipetools.Element src, **properties)
Definition transform.py:80
progress_report(pipetools.Pipeline pipeline, pipetools.Element src, str name)
Adds a progress_report element to a pipeline with useful default properties.
Definition transform.py:852
pipetools.Element clean(pipetools.Pipeline pipeline, pipetools.Element src, float threshold=1.0)
Definition transform.py:780
pipetools.Element colorspace(pipetools.Pipeline pipeline, pipetools.Element src)
Definition transform.py:615
pipetools.Element queue(pipetools.Pipeline pipeline, pipetools.Element src, **properties)
Adds a queue element to a pipeline with useful default properties.
Definition transform.py:365
pipetools.Element matrix_mixer(pipetools.Pipeline pipeline, pipetools.Element src, numpy.ndarray matrix=None)
Adds a lal_matrixmixer element to a pipeline with useful default properties.
Definition transform.py:531
pipetools.Element resample(pipetools.Pipeline pipeline, pipetools.Element src, **properties)
Adds a audioresample element to a pipeline with useful default properties.
Definition transform.py:207
pipetools.Element shift(pipetools.Pipeline pipeline, pipetools.Element src, **properties)
Adds a lal_shift element to a pipeline with useful default properties.
Definition transform.py:143
pipetools.Element auto_chisq(pipetools.Pipeline pipeline, pipetools.Element src, numpy.ndarray autocorrelation_matrix=None, mask_matrix=None, int latency=0, int snr_thresh=0)
Adds a lal_autochisq element to a pipeline with useful default properties.
Definition transform.py:576
pipetools.Element fir_bank(pipetools.Pipeline pipeline, pipetools.Element src, int latency=None, numpy.ndarray fir_matrix=None, bool time_domain=None, int block_stride=None)
Adds a lal_firbank element to a pipeline with useful default properties.
Definition transform.py:395
pipetools.Element integrate(pipetools.Pipeline pipeline, pipetools.Element src, float template_dur=1.0, **properties)
Definition transform.py:28
pipetools.Element peak(pipetools.Pipeline pipeline, pipetools.Element src, int n)
Adds a lal_peak element to a pipeline with useful default properties.
Definition transform.py:741