28 matplotlib.rcParams.update({
30 "axes.titlesize": 10.0,
31 "axes.labelsize": 10.0,
32 "xtick.labelsize": 8.0,
33 "ytick.labelsize": 8.0,
34 "legend.fontsize": 8.0,
40 from matplotlib
import figure
41 from matplotlib
import cm
as colourmap
42 from matplotlib.backends.backend_agg
import FigureCanvasAgg
as FigureCanvas
52 from gst.extend.pygobject
import gproperty
55 from gstlal
import pipeio
56 from gstlal.elements
import matplotlibcaps
59 __author__ =
"Kipp Cannon <kipp.cannon@ligo.org>"
75 def __init__(self, buf):
80 if bool(buf.flags & gst.BUFFER_FLAG_GAP):
81 self.
data = numpy.zeros((self.
offset_end - self.
offset, buf.caps[0][
"channels"]), dtype = pipeio.numpy_dtype_from_caps(buf.caps))
83 self.
data = pipeio.array_from_audio_buffer(buf)
86 return self.data.shape[0]
89 if n > self.data.shape[0]:
90 n = self.data.shape[0]
101 def extract(self, n):
102 extracted, timestamp = self.
get(n)
104 return extracted, timestamp
106 def append(self, buf):
110 if not list.__len__(self):
112 return self[-1].offset_end - self[0].offset
116 while n > 0
and self:
117 n -= self[0].flush(n)
124 timestamp = self[0].timestamp
129 data.append(i.get(n)[0])
130 n -= data[-1].shape[0]
133 return numpy.concatenate(data), timestamp
135 def extract(self, n):
136 extracted, timestamp = self.
get(n)
137 self.
flush(extracted.shape[0])
138 return extracted, timestamp
141 def yticks(min, max, n):
142 delta = float(max - min) / n
143 return sorted(set(min + int(round(delta * i))
for i
in range(n + 1)))
157 "Scrolling channel amplitude plot",
159 "Generates video showing a scrolling plot of channel amplitudes",
166 "Width of the plot in seconds, 0 = 1/framerate",
170 readable =
True, writable =
True
174 gst.PadTemplate(
"sink",
177 gst.caps_from_string(
178 "audio/x-raw-complex, " +
179 "rate = (int) [1, MAX], " +
180 "channels = (int) [1, MAX], " +
181 "endianness = (int) BYTE_ORDER, " +
182 "width = (int) {64, 128};" +
183 "audio/x-raw-float, " +
184 "rate = (int) [1, MAX], " +
185 "channels = (int) [1, MAX], " +
186 "endianness = (int) BYTE_ORDER, " +
187 "width = (int) {32, 64};" +
188 "audio/x-raw-int, " +
189 "rate = (int) [1, MAX], " +
190 "channels = (int) [1, MAX], " +
191 "endianness = (int) BYTE_ORDER, " +
192 "width = (int) 32," +
193 "depth = (int) 32," +
194 "signed = (bool) {true, false}; " +
195 "audio/x-raw-int, " +
196 "rate = (int) [1, MAX], " +
197 "channels = (int) [1, MAX], " +
198 "endianness = (int) BYTE_ORDER, " +
199 "width = (int) 64," +
200 "depth = (int) 64," +
201 "signed = (bool) {true, false}"
204 gst.PadTemplate(
"src",
207 gst.caps_from_string(
208 matplotlibcaps +
", " +
209 "width = (int) [1, MAX], " +
210 "height = (int) [1, MAX], " +
211 "framerate = (fraction) [0, MAX]"
218 gst.BaseTransform.__init__(self)
224 self.set_property(
"plot-width", 0.0)
230 def do_set_caps(self, incaps, outcaps):
231 self.
in_rate = incaps[0][
"rate"]
232 channels = incaps[0][
"channels"]
236 self.
out_rate = outcaps[0][
"framerate"]
249 def do_get_unit_size(self, caps):
250 return pipeio.get_unit_size(caps)
253 def do_event(self, event):
254 if event.type == gst.EVENT_TAG:
255 tags = pipeio.parse_framesrc_tags(event.parse_tag())
262 def make_frame(self, samples, samples_timestamp, outbuf):
270 outbuf.timestamp = self.
t0 + int(round(float(int(outbuf.offset - self.
offset0) / self.
out_rate) * gst.SECOND))
271 outbuf.duration = self.
t0 + int(round(float(int(outbuf.offset_end - self.
offset0) / self.
out_rate) * gst.SECOND)) - outbuf.timestamp
277 fig = figure.Figure()
279 fig.set_size_inches(self.
out_width / float(fig.get_dpi()), self.
out_height / float(fig.get_dpi()))
280 axes = fig.gca(rasterized =
True)
281 x, y = map(
lambda n: numpy.arange(n + 1, dtype =
"double"), samples.shape)
282 x = x / self.
in_rate + float(samples_timestamp) / gst.SECOND
286 x, y = numpy.meshgrid(x, y)
287 if samples.dtype.kind ==
"c":
292 axes.pcolormesh(x, y, numpy.abs(samples.transpose()), cmap = colourmap.gray)
298 axes.pcolormesh(x, y, samples.transpose(), cmap = colourmap.gray)
301 axes.set_yticks(yticks(0, samples.shape[1] - 1, 20))
302 axes.set_title(
r"Amplitude of %s, %s" % (self.
instrument or "Unknown Instrument", (self.
channel_name or "Unknown Channel").replace(
"_",
r"\_")))
303 axes.set_xlabel(
r"Time (s)")
304 axes.set_ylabel(
r"Channel Number")
311 rgba_buffer = fig.canvas.buffer_rgba(0, 0)
312 rgba_buffer_size = len(rgba_buffer)
318 outbuf[0:rgba_buffer_size] = rgba_buffer
319 outbuf.datasize = rgba_buffer_size
328 def do_transform(self, inbuf, outbuf):
334 self.
t0 = inbuf.timestamp
342 self.queue.append(inbuf)
352 samples_flushed_per_frame = int(round(self.
in_rate / float(self.
out_rate)))
353 plot_width = self.get_property(
"plot-width")
354 if plot_width != 0.0:
355 samples_per_frame = int(round(plot_width * self.
in_rate))
357 samples_per_frame = samples_flushed_per_frame
363 if len(self.
queue) < samples_per_frame:
370 return gst.FLOW_CUSTOM_SUCCESS
372 while len(self.
queue) >= 2 * samples_per_frame:
374 samples, timestamp = self.queue.get(samples_per_frame)
375 self.queue.flush(samples_flushed_per_frame)
376 self.get_pad(
"src").push(self.
make_frame(samples, timestamp, newoutbuf))
377 samples, timestamp = self.queue.get(samples_per_frame)
378 self.queue.flush(samples_flushed_per_frame)
388 def do_transform_caps(self, direction, caps):
389 if direction == gst.PAD_SRC:
394 return self.get_pad(
"sink").get_fixed_caps_func()
396 elif direction == gst.PAD_SINK:
401 return self.get_pad(
"src").get_fixed_caps_func()
403 raise ValueError(direction)
406 def do_transform_size(self, direction, caps, size, othercaps):
409 if direction == gst.PAD_SRC:
415 bytes_per_frame = caps[0][
"width"] * caps[0][
"height"] * caps[0][
"bpp"] / 8
416 samples = int(size / bytes_per_frame) * samples_per_frame - len(self.
queue)
424 return samples * (othercaps[0][
"width"] // 8) * othercaps[0][
"channels"]
426 elif direction == gst.PAD_SINK:
432 frames = (int(size * 8 / caps[0][
"width"]) // caps[0][
"channels"] + len(self.
queue)) / samples_per_frame
444 return othercaps[0][
"width"] * othercaps[0][
"height"] * othercaps[0][
"bpp"] / 8
446 raise ValueError(direction)
454 gobject.type_register(lal_channelgram)
456 __gstelementfactory__ = (
457 lal_channelgram.__name__,