36 from matplotlib
import figure
37 from matplotlib.backends.backend_agg
import FigureCanvasAgg
as FigureCanvas
38 from matplotlib
import ticker
40 from gstlal
import plotutil
41 from glue.ligolw
import lsctables
42 from gstlal
import reference_psd
45 def summarize_coinc_xmldoc(coinc_xmldoc):
46 coinc_event, = lsctables.CoincTable.get_table(coinc_xmldoc)
47 coinc_inspiral, = lsctables.CoincInspiralTable.get_table(coinc_xmldoc)
48 offset_vector = lsctables.TimeSlideTable.get_table(coinc_xmldoc).as_dict()[coinc_event.time_slide_id]
if coinc_event.time_slide_id
is not None else None 51 sngl_inspirals = dict((row.ifo, row)
for row
in lsctables.SnglInspiralTable.get_table(coinc_xmldoc))
53 mass1 = sngl_inspirals.values()[0].mass1
54 mass2 = sngl_inspirals.values()[0].mass2
56 mass1, mass2 = mass2, mass1
57 end_time = coinc_inspiral.end
58 on_instruments = coinc_inspiral.ifos
59 logging.info(
"%g Msun -- %g Msun event in %s at %.2f GPS" % (mass1, mass2,
", ".join(sorted(sngl_inspirals)), float(end_time)))
61 return sngl_inspirals, mass1, mass2, end_time, on_instruments
64 def axes_plot_cummulative_snr(axes, psds, coinc_xmldoc):
65 sngl_inspirals, mass1, mass2, end_time, on_instruments = summarize_coinc_xmldoc(coinc_xmldoc)
67 axes.grid(which =
"both", linestyle =
"-", linewidth = 0.2)
70 for instrument, sngl_inspiral
in sngl_inspirals.items():
71 logging.info(
"found %s event with SNR %g" % (instrument, sngl_inspirals[instrument].snr))
73 if instrument
not in psds:
74 logging.info(
"no PSD for %s" % instrument)
76 psd = psds[instrument]
78 logging.info(
"no PSD for %s" % instrument)
80 psd_data = psd.data.data
81 f = psd.f0 + numpy.arange(len(psd_data)) * psd.deltaF
82 logging.info(
"found PSD for %s spanning [%g Hz, %g Hz]" % (instrument, f[0], f[-1]))
92 inspiral_spectrum_x, inspiral_spectrum_y = horizon_distance(psd, sngl_inspiral.snr)[1]
93 lo = int(round((inspiral_spectrum_x[0] - psd.f0) / psd.deltaF))
94 hi = int(round((inspiral_spectrum_x[-1] - psd.f0) / psd.deltaF)) + 1
96 psd_data = psd_data[lo:hi]
99 snr2 = (inspiral_spectrum_y / psd_data).cumsum() * psd.deltaF
100 axes.semilogx(f, snr2**.5, color = plotutil.colour_from_instruments([instrument]), alpha = 0.8, linestyle =
"-", label =
"%s SNR = %.3g" % (instrument, sngl_inspiral.snr))
102 axes.set_ylim([0., axes.get_ylim()[1]])
104 axes.set_title(
r"Cumulative SNRs for $%.3g\,\mathrm{M}_{\odot}$--$%.3g\,\mathrm{M}_{\odot}$ Merger Candidate at %.2f GPS" % (mass1, mass2, float(end_time)))
105 axes.set_xlabel(
r"Frequency (Hz)")
106 axes.set_ylabel(
r"Cumulative SNR")
107 axes.legend(loc =
"upper left")
110 def latex_horizon_distance(Mpc):
113 return "%s Gpc" % plotutil.latexnumber(
"%.4g" % (Mpc * 1e-3))
116 return "%s Mpc" % plotutil.latexnumber(
"%.4g" % Mpc)
119 return "%s kpc" % plotutil.latexnumber(
"%.4g" % (Mpc * 1e3))
122 return "%s pc" % plotutil.latexnumber(
"%.4g" % (Mpc * 1e6))
127 Places a PSD plot into a matplotlib Axes object. 129 @param axes An Axes object into which the plot will be placed. 131 @param psds A dictionary of PSDs as REAL8FrequencySeries keyed by 134 @param coinc_xmldoc An XML document containing a single event with all 135 of the metadata as would be uploaded to gracedb. This is optional. 138 if coinc_xmldoc
is not None:
139 sngl_inspirals, mass1, mass2, end_time, on_instruments = summarize_coinc_xmldoc(coinc_xmldoc)
144 mass1, mass2, end_time = 1.4, 1.4,
None 145 on_instruments = set(psds)
147 axes.grid(which =
"both", linestyle =
"-", linewidth = 0.2)
150 min_psds, max_psds = [], []
151 min_fs, max_fs = [], []
152 for instrument, psd
in sorted(psds.items()):
155 psd_data = psd.data.data
156 f = psd.f0 + numpy.arange(len(psd_data)) * psd.deltaF
157 logging.info(
"found PSD for %s spanning [%g Hz, %g Hz]" % (instrument, f[0], f[-1]))
165 if instrument
in on_instruments:
168 label =
"%s (%s Horizon)" % (instrument, latex_horizon_distance(horizon_distance(psd, 8.)[0]))
172 label =
"%s (Off, Last Seen With %s Horizon)" % (instrument, latex_horizon_distance(horizon_distance(psd, 8.)[0]))
173 axes.loglog(f, psd_data, color = plotutil.colour_from_instruments([instrument]), alpha = alpha, linestyle = linestyle, label = label)
174 if instrument
in sngl_inspirals:
175 logging.info(
"found %s event with SNR %g" % (instrument, sngl_inspirals[instrument].snr))
176 inspiral_spectrum = horizon_distance(psd, sngl_inspirals[instrument].snr)[1]
177 axes.loglog(inspiral_spectrum[0], inspiral_spectrum[1], color = plotutil.colour_from_instruments([instrument]), dashes = (5, 2), alpha = 0.8, label =
"SNR = %.3g" % sngl_inspirals[instrument].snr)
179 min_psds.append(psd_data[int((10.0 - psd.f0) / psd.deltaF) : int((900 - psd.f0) / psd.deltaF)].min())
181 max_psds.append(psd_data[int((1.0 - psd.f0) / psd.deltaF) : int((900 - psd.f0) / psd.deltaF)].max())
184 axes.set_xlim((6.0, max(max_fs)))
186 axes.set_xlim((6.0, 3000.0))
188 axes.set_ylim((10.**math.floor(math.log10(min(min_psds) / 3.)), 10.**math.ceil(math.log10(max(max_psds)))))
191 axes.yaxis.set_major_locator(ticker.LogLocator(10., subs = (1.0,)))
192 axes.yaxis.set_minor_locator(ticker.LogLocator(10., subs = (0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9)))
194 title =
r"Strain Noise Spectral Density for $%.3g\,\mathrm{M}_{\odot}$--$%.3g\,\mathrm{M}_{\odot}$ Merger Candidate" % (mass1, mass2)
195 if end_time
is not None:
196 title +=
r" at %.2f GPS" % float(end_time)
197 axes.set_title(title)
198 axes.set_xlabel(
r"Frequency (Hz)")
199 axes.set_ylabel(
r"Spectral Density ($\mathrm{strain}^2 / \mathrm{Hz}$)")
200 axes.legend(loc =
"upper right")
203 def plot_psds(psds, coinc_xmldoc = None, plot_width = 640):
205 Produces a matplotlib figure of PSDs. 207 @param psds A dictionary of PSDs as REAL8FrequencySeries keyed by 210 @param coinc_xmldoc An XML document containing a single event with all 211 of the metadata as would be uploaded to gracedb. This is optional. 213 @param plot_width How wide to make the figure object in pixels 214 (ignored if axes is provided). 216 fig = figure.Figure()
218 fig.set_size_inches(plot_width / float(fig.get_dpi()), int(round(plot_width / plotutil.golden_ratio)) / float(fig.get_dpi()))
220 fig.tight_layout(pad = .8)
226 Produces a matplotlib figure of cumulative SNRs. 228 @param psds A dictionary of PSDs as REAL8FrequencySeries keyed by 231 @param coinc_xmldoc An XML document containing a single event with all 232 of the metadata as would be uploaded to gracedb. 234 @param plot_width How wide to make the figure object in pixels 235 (ignored if axes is provided). 237 fig = figure.Figure()
239 fig.set_size_inches(plot_width / float(fig.get_dpi()), int(round(plot_width / plotutil.golden_ratio)) / float(fig.get_dpi()))
240 axes_plot_cummulative_snr(fig.gca(), psds, coinc_xmldoc)
241 fig.tight_layout(pad = .8)
def axes_plot_psds(axes, psds, coinc_xmldoc=None)
def plot_psds(psds, coinc_xmldoc=None, plot_width=640)
def plot_cumulative_snrs(psds, coinc_xmldoc, plot_width=640)