gstlal  1.4.1
gstlal_spectrum_movie
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #
3 # Copyright (C) 2010 Kipp Cannon
4 #
5 # This program is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the
7 # Free Software Foundation; either version 2 of the License, or (at your
8 # option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 # Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License along
16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 
19 ## @file
20 # A program to make a movie of power spectral densities taken over time
21 
22 #
23 # =============================================================================
24 #
25 # Preamble
26 #
27 # =============================================================================
28 #
29 
30 
31 from optparse import OptionParser
32 import pygtk
33 pygtk.require("2.0")
34 import gi
35 gi.require_version('Gst', '1.0')
36 from gi.repository import GObject, Gst
37 
38 
39 from gstlal import simplehandler
40 from gstlal import pipeparts
41 from gstlal import datasource
42 
43 
44 from ligo import segments
45 
46 
47 #
48 # =============================================================================
49 #
50 # Command Line
51 #
52 # =============================================================================
53 #
54 
55 
56 def parse_command_line():
57  parser = OptionParser(
58  description = "%prog generates an animated view of the PSD measured from h(t). The video can be shown on the screen or saved to a OGG Theora movie file. Example:\n\n%prog \\\n\t--frame-cache \"/home/kipp/scratch_local/874100000-20000/cache/874100000-20000.cache\" \\\n\t--instrument \"H1\" \\\n\t--channel-name \"LSC-STRAIN\" \\\n\t--gps-start-time 874100000.0 \\\n\t--gps-end-time 874120000.0 \\\n\t--psd-fft-length 8.0 \\\n\t--psd-zero-pad-length 0.0 \\\n\t--average-length 64.0 \\\n\t--median-samples 3 \\\n\t--frame-rate 10/1 \\\n\t--output spectrum_movie.ogm \\\n\t--verbose"
59  )
60  # generic "source" options
61  datasource.append_options(parser)
62  parser.add_option("--sample-rate", metavar = "Hz", type = "float", default = 8192.0, help = "Downsample the data to this sample rate. Default = 8192 Hz.")
63  parser.add_option("--psd-fft-length", metavar = "seconds", type = "float", default = 8.0, help = "Set the length of the FFT windows used to measure the PSD (optional).")
64  parser.add_option("--psd-zero-pad-length", metavar = "seconds", type = "float", default = 0.0, help = "Set the length of zero-padding in the FFT windows used to measure the PSD (optional).")
65  parser.add_option("--average-length", metavar = "seconds", type = "float", default = 64.0, help = "Set the time scale for the running mean (optional). Default = 64.0.")
66  parser.add_option("--median-samples", metavar = "samples", type = "int", default = 5, help = "Set the number of samples in the median history (optional). Default = 5.")
67  parser.add_option("--f-min", metavar = "Hz", type = "float", default = 10.0, help = "Set the lower bound of the spectrum plot's horizontal axis. Default = 10.0.")
68  parser.add_option("--f-max", metavar = "Hz", type = "float", default = 4000.0, help = "Set the upper bound of the spectrum plot's horizontal axis. Default = 4000.0.")
69  parser.add_option("--output", metavar = "filename", help = "Set the name of the movie file to write (optional). The default is to display the video on screen.")
70  parser.add_option("-v", "--verbose", action = "store_true", help = "Be verbose (optional).")
71 
72  options, filenames = parser.parse_args()
73 
74  if options.f_max <= options.f_min:
75  raise ValueError, "--f-max must be >= --f-min"
76 
77  return options, filenames
78 
79 
80 #
81 # =============================================================================
82 #
83 # Main
84 #
85 # =============================================================================
86 #
87 
88 
89 #
90 # parse command line
91 #
92 
93 
94 options, filenames = parse_command_line()
95 
96 
97 #
98 # parse the generic "source" options, check for inconsistencies is done inside
99 # the class init method
100 #
101 
102 
103 gw_data_source_info = datasource.GWDataSourceInfo(options)
104 if len(gw_data_source_info.channel_dict) != 1:
105  raise ValueError("can only specify one channel, one instrument")
106 instrument, = gw_data_source_info.channel_dict.keys()
107 
108 
109 #
110 # build pipeline
111 #
112 
113 
114 def build_pipeline(pipeline, head, sample_rate, psd_fft_length, psd_zero_pad_length, average_length, median_samples, (f_min, f_max), verbose = False):
115  head = pipeparts.mkresample(pipeline, head, quality = 9)
116  head = pipeparts.mkcapsfilter(pipeline, head, "audio/x-raw, rate=%d" % sample_rate)
117  head = pipeparts.mkwhiten(pipeline, head, fft_length = psd_fft_length, zero_pad = psd_zero_pad_length, average_samples = int(round(average_length / (psd_fft_length / 2) - 1)), median_samples = median_samples)
118  pipeparts.mkfakesink(pipeline, head)
119  head = pipeparts.mkqueue(pipeline, head.get_static_pad("mean-psd"), max_size_buffers = 4)
120 
121  head = pipeparts.mkspectrumplot(pipeline, head, f_min = f_min, f_max = f_max)
122  head = pipeparts.mkcapsfilter(pipeline, head, "video/x-raw-rgb, width=768, height=320")
123  return head
124 
125 
126 #
127 # construct and run pipeline
128 #
129 
130 
131 mainloop = GObject.MainLoop()
132 pipeline = Gst.Pipeline(name="spectrum-movie")
133 handler = simplehandler.Handler(mainloop, pipeline)
134 
135 
136 head, _, _ = datasource.mkbasicsrc(pipeline, gw_data_source_info, instrument, verbose = options.verbose)
137 head = build_pipeline(
138  pipeline,
139  head,
140  options.sample_rate,
141  options.psd_fft_length,
142  options.psd_zero_pad_length,
143  options.average_length,
144  options.median_samples,
145  (options.f_min, options.f_max),
146  verbose = options.verbose
147 )
148 if options.output is not None:
149  pipeparts.mkogmvideosink(pipeline, head, options.output, verbose = options.verbose)
150 else:
151  pipeparts.mkvideosink(pipeline, pipeparts.mkcolorspace(pipeline, head))
152 
153 
154 #
155 # process segment
156 #
157 
158 
159 if pipeline.set_state(Gst.State.PLAYING) == Gst.StateChangeReturn.FAILURE:
160  raise RuntimeError("pipeline failed to enter PLAYING state")
161 mainloop.run()
162 
163 
164 #
165 # done
166 #