gstlal  0.8.1
 All Classes Namespaces Files Functions Variables Pages
gstlal_spectrum_movie
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 pygst
35 pygst.require("0.10")
36 import gobject
37 import gst
38 
39 
40 from gstlal import simplehandler
41 from gstlal import pipeparts
42 from gstlal import datasource
43 
44 
45 from glue import segments
46 from pylal.datatypes import LIGOTimeGPS
47 
48 
49 #
50 # =============================================================================
51 #
52 # Command Line
53 #
54 # =============================================================================
55 #
56 
57 
58 def parse_command_line():
59  parser = OptionParser(
60  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"
61  )
62  # generic "source" options
63  datasource.append_options(parser)
64  parser.add_option("--sample-rate", metavar = "Hz", type = "float", default = 8192.0, help = "Downsample the data to this sample rate. Default = 8192 Hz.")
65  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).")
66  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).")
67  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.")
68  parser.add_option("--median-samples", metavar = "samples", type = "int", default = 5, help = "Set the number of samples in the median history (optional). Default = 5.")
69  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.")
70  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.")
71  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.")
72  parser.add_option("-v", "--verbose", action = "store_true", help = "Be verbose (optional).")
73 
74  options, filenames = parser.parse_args()
75 
76  if options.f_max <= options.f_min:
77  raise ValueError, "--f-max must be >= --f-min"
78 
79  return options, filenames
80 
81 
82 #
83 # =============================================================================
84 #
85 # Main
86 #
87 # =============================================================================
88 #
89 
90 
91 #
92 # parse command line
93 #
94 
95 
96 options, filenames = parse_command_line()
97 
98 
99 #
100 # parse the generic "source" options, check for inconsistencies is done inside
101 # the class init method
102 #
103 
104 
105 gw_data_source_info = datasource.GWDataSourceInfo(options)
106 if len(gw_data_source_info.channel_dict) != 1:
107  raise ValueError("can only specify one channel, one instrument")
108 instrument, = gw_data_source_info.channel_dict.keys()
109 
110 
111 #
112 # build pipeline
113 #
114 
115 
116 def build_pipeline(pipeline, head, sample_rate, psd_fft_length, psd_zero_pad_length, average_length, median_samples, (f_min, f_max), verbose = False):
117  head = pipeparts.mkresample(pipeline, head, quality = 9)
118  head = pipeparts.mkcapsfilter(pipeline, head, "audio/x-raw-float, rate=%d" % sample_rate)
119  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)
120  pipeparts.mkfakesink(pipeline, head)
121  head = pipeparts.mkqueue(pipeline, head.get_pad("mean-psd"), max_size_buffers = 4)
122 
123  head = pipeparts.mkspectrumplot(pipeline, head, f_min = f_min, f_max = f_max)
124  head = pipeparts.mkcapsfilter(pipeline, head, "video/x-raw-rgb, width=768, height=320")
125  return head
126 
127 
128 #
129 # construct and run pipeline
130 #
131 
132 
133 mainloop = gobject.MainLoop()
134 pipeline = gst.Pipeline("spectrum-movie")
135 handler = simplehandler.Handler(mainloop, pipeline)
136 
137 
138 head = datasource.mkbasicsrc(pipeline, gw_data_source_info, instrument, verbose = options.verbose)
139 head = build_pipeline(
140  pipeline,
141  head,
142  options.sample_rate,
143  options.psd_fft_length,
144  options.psd_zero_pad_length,
145  options.average_length,
146  options.median_samples,
147  (options.f_min, options.f_max),
148  verbose = options.verbose
149 )
150 if options.output is not None:
151  pipeparts.mkogmvideosink(pipeline, head, options.output, verbose = options.verbose)
152 else:
153  pipeparts.mkvideosink(pipeline, pipeparts.mkcolorspace(pipeline, head))
154 
155 
156 #
157 # process segment
158 #
159 
160 
161 if pipeline.set_state(gst.STATE_PLAYING) == gst.STATE_CHANGE_FAILURE:
162  raise RuntimeError("pipeline failed to enter PLAYING state")
163 mainloop.run()
164 
165 
166 #
167 # done
168 #