def plot_spectrum(fd_psd): ''' Plot power spectral density ''' plot = FrequencySeriesPlot() ax = plot.gca() ax.plot(FrequencySeries(fd_psd, df=fd_psd.delta_f)) #plt.ylim(1e-10, 1e-3) plt.xlim(0.1, 500) plt.loglog() plt.savefig("psd.png", dpi=300, transparent=True) plt.close()
def plot_asd(station, data): """ Plot Amplitude Spectral Density. AGG complexity starts to complain with large numbers of points. And we somehow invoke precision issues that need to be ameliorated. """ if station != 'fake': for d in data: d.x0 = Quantity(int(d.x0.value * 500), d.xunit) d.dx = Quantity(1, d.xunit) data.coalesce() for d in data: d.x0 = Quantity(d.x0.value / 500, d.xunit) d.dx = Quantity(0.002, d.xunit) # Initialize plotting functionality plot = FrequencySeriesPlot() # Loop over all the time series for d in data: # Generate 8 seconds per FFT with 4 second (50%) overlap spectrum = d.asd(8, 4) # Create plotting axis ax = plot.gca() # Plot square root of the spectrum ax.plot(numpy.sqrt(spectrum)) # Set x axis to log scale ax.set_xscale('log') ax.set_xlabel('Frequency [Hz]') # Set y axis to log scale ax.set_yscale('log') ax.set_ylabel('Amplitude [pT]') # Set x axis limits ax.set_xlim(1e-1, 500) x = ax.get_xticklabels() def myticks(x, pos): if x == 0: return "$0$" exponent = int(numpy.log10(x)) coeff = x / 10**exponent if coeff == 1: return r"$10^{{ {:2d} }}$".format(exponent) else: return r"${:2.0f} \times 10^{{ {:2d} }}$".format(coeff, exponent) ax.xaxis.set_major_formatter(matplotlib.ticker.FuncFormatter(myticks)) plt.tight_layout() # Save figure plot.savefig("asd.png", dpi=300, transparent=True)
def _draw(self): """Load all data, and generate this `SpectrumDataPlot` """ plot = self.plot = FrequencySeriesPlot( figsize=self.pargs.pop('figsize', [12, 6])) ax = plot.gca() ax.grid(b=True, axis='both', which='both') if self.state: self.pargs.setdefault( 'suptitle', '[%s-%s, state: %s]' % (self.span[0], self.span[1], label_to_latex(str(self.state)))) suptitle = self.pargs.pop('suptitle', None) if suptitle: plot.suptitle(suptitle, y=0.993, va='top') # get spectrum format: 'amplitude' or 'power' sdform = self.pargs.pop('format') # parse plotting arguments plotargs = self.parse_plot_kwargs() legendargs = self.parse_legend_kwargs() # add data sumdata = [] for i, (channel, pargs) in enumerate(zip(self.channels, plotargs)): if self.state and not self.all_data: valid = self.state else: valid = SegmentList([self.span]) data = get_spectrum(str(channel), valid, query=False, format=sdform, method=None)[0] if i: sumdata.append(data) # anticipate log problems if self.pargs['logx']: data = data[1:] if self.pargs['logy']: data.value[data.value == 0] = 1e-100 pargs.setdefault('zorder', -i) ax.plot_frequencyseries(data, **pargs) # assert all noise terms have the same resolution if any([x.dx != sumdata[0].dx for x in sumdata]): raise RuntimeError("Noise components have different resolutions, " "cannot construct sum of noises") # reshape noises if required n = max(x.size for x in sumdata) for i, d in enumerate(sumdata): if d.size < n: sumdata[i] = numpy.require(d, requirements=['O']) sumdata[i].resize((n, )) # plot sum of noises sumargs = self.parse_sum_params() sum_ = sumdata[0]**2 for d in sumdata[1:]: sum_ += d**2 sum_ **= (1 / 2.) ax.plot_frequencyseries(sum_, zorder=1, **sumargs) ax.lines.insert(1, ax.lines.pop(-1)) self.apply_parameters(ax, **self.pargs) plot.add_legend(ax=ax, **legendargs) plot.add_colorbar(ax=ax, visible=False) return self.finalize()
# method: sg = hoft.spectrogram2(fftlength=4, overlap=2)**(1 / 2.) # From this we can trivially extract the median, 5th and 95th percentiles: median = sg.percentile(50) min_ = sg.percentile(5) max_ = sg.percentile(95) # Finally, we can make plot, using # :meth:`~gwpy.plotter.FrequencySeriesAxes.plot_frequencyseries_mmm` to # display the 5th and 95th percentiles as a shaded region around the median: from gwpy.plotter import FrequencySeriesPlot plot = FrequencySeriesPlot() ax = plot.gca() ax.plot_mmm(median, min_=min_, max_=max_, color='gwpy:ligo-hanford') ax.set_xscale('log') ax.set_yscale('log') ax.set_xlim(10, 1500) ax.set_ylim(3e-24, 2e-20) ax.set_ylabel(r'Strain noise [1/\rtHz]') ax.set_title('LIGO-Hanford strain noise variation around GW170817', fontsize=16) plot.show() # Now we can see that the ASD varies by factors of a few across most of the # frequency band, with notable exceptions, e.g. around the 60-Hz power line # harmonics (60 Hz, 120 Hz, 180 Hz, ...) where the noise is very stable.
def _draw(self): """Load all data, and generate this `SpectrumDataPlot` """ plot = self.plot = FrequencySeriesPlot( figsize=self.pargs.pop('figsize', [12, 6])) ax = plot.gca() ax.grid(b=True, axis='both', which='both') if self.state: self.pargs.setdefault( 'suptitle', '[%s-%s, state: %s]' % (self.span[0], self.span[1], label_to_latex(str(self.state)))) suptitle = self.pargs.pop('suptitle', None) if suptitle: plot.suptitle(suptitle, y=0.993, va='top') # get spectrum format: 'amplitude' or 'power' sdform = self.pargs.pop('format') # parse plotting arguments plotargs = self.parse_plot_kwargs()[0] # add data sumdata = [] for i, channel in enumerate(self.channels): if self.state and not self.all_data: valid = self.state else: valid = SegmentList([self.span]) data = get_spectrum(str(channel), valid, query=False, format=sdform, method=None)[0] if i: sumdata.append(data) else: target = data # assert all noise terms have the same resolution if any([x.dx != target.dx for x in sumdata]): raise RuntimeError("Noise components have different resolutions, " "cannot construct sum of noises") # reshape noises if required n = target.size for i, d in enumerate(sumdata): if d.size < n: sumdata[i] = numpy.require(d, requirements=['O']) sumdata[i].resize((n, )) # calculate sum of noises sum_ = sumdata[0]**2 for d in sumdata[1:]: sum_ += d**2 sum_ **= (1 / 2.) # plot ratio of h(t) to sum of noises relative = sum_ / target ax.plot_frequencyseries(relative, **plotargs) # finalize plot self.apply_parameters(ax, **self.pargs) plot.add_colorbar(ax=ax, visible=False) return self.finalize()
from gwpy.plotter import FrequencySeriesPlot plot = FrequencySeriesPlot(whiteasd, dispasd, sep=True, sharex=True, label=None)
# We can now easily inject a loud sinusoid of unit amplitude at, say, # 30 Hz. To do this, we use :meth:`~gwpy.types.series.Series.inject`. import numpy from gwpy.frequencyseries import FrequencySeries signal = FrequencySeries(numpy.array([1.]), f0=30, df=noisefd.df) injfd = noisefd.inject(signal) # We can then visualize the data before and after injection in the frequency # domain: from gwpy.plotter import FrequencySeriesPlot plot = FrequencySeriesPlot(numpy.abs(noisefd), numpy.abs(injfd), sep=True, sharex=True, sharey=True) plot.show() # Finally, for completeness we can visualize the effect before and after # injection back in the time domain: from gwpy.plotter import TimeSeriesPlot inj = injfd.ifft() plot = TimeSeriesPlot(noise, inj, sep=True, sharex=True, sharey=True) plot.show() # We can see why sinusoids are easier to inject in the frequency domain: # they only require adding at a single frequency.
# and then applying our de-whitening filter in `ZPK <TimeSeries.zpk>` format # with five zeros at 100 Hz and five poles at 1 Hz (giving an overall DC # gain of 10 :sup:`-10`: hp = white.highpass(4) displacement = hp.zpk([100]*5, [1]*5, 1e-10) # We can visualise the impact of the whitening by calculating the ASD # `~gwpy.frequencyseries.FrequencySeries` before and after the filter, whiteasd = white.asd(8, 4) dispasd = displacement.asd(8, 4) # and plotting: from gwpy.plotter import FrequencySeriesPlot plot = FrequencySeriesPlot(whiteasd, dispasd, sep=True, sharex=True, label=None) # Here we have passed the two # `spectra <gwpy.frequencyseries.FrequencySeries>` in order, # then `sep=True` to display them on separate Axes, `sharex=True` to tie # the `~matplotlib.axis.XAxis` of each of the `~gwpy.plotter.FrequencySeriesAxes` # together, and `label=None` to remove any unwanted legends. # # Finally, we prettify our plot with some limits, and some labels: plot.text(0.95, 0.05, 'Preliminary', fontsize=40, color='gray', ha='right', rotation=45, va='bottom', alpha=0.5) # hide plot.axes[0].set_ylabel('ASD [whitened]') plot.axes[1].set_ylabel(r'ASD [m/\rtHz]') plot.axes[1].set_xlabel('Frequency [Hz]') plot.axes[1].set_ylim(1e-20, 1e-15) plot.axes[1].set_xlim(5, 4000) plot.show()
from gwpy.plotter import FrequencySeriesPlot plot = FrequencySeriesPlot() ax = plot.gca() ax.plot_mmm(median, min_=min_, max_=max_, color='gwpy:ligo-hanford') ax.set_xscale('log') ax.set_yscale('log') ax.set_xlim(10, 1500) ax.set_ylim(3e-24, 2e-20) ax.set_ylabel(r'Strain noise [1/\rtHz]') ax.set_title('LIGO-Hanford strain noise variation around GW170817', fontsize=16) plot.show()
# To inject a signal in the frequency domain, we need to take an FFT: noisefd = noise.fft() # We can now easily inject a loud sinusoid of unit amplitude at, say, # 30 Hz. To do this, we use :meth:`~gwpy.types.series.Series.inject`. import numpy from gwpy.frequencyseries import FrequencySeries signal = FrequencySeries(numpy.array([1.]), f0=30, df=noisefd.df) injfd = noisefd.inject(signal) # We can then visualize the data before and after injection in the frequency # domain: from gwpy.plotter import FrequencySeriesPlot plot = FrequencySeriesPlot(numpy.abs(noisefd), numpy.abs(injfd), sep=True, sharex=True, sharey=True) plot.show() # Finally, for completeness we can visualize the effect before and after # injection back in the time domain: from gwpy.plotter import TimeSeriesPlot inj = injfd.ifft() plot = TimeSeriesPlot(noise, inj, sep=True, sharex=True, sharey=True) plot.show() # We can see why sinusoids are easier to inject in the frequency domain: # they only require adding at a single frequency.