def generate_asd_plot(psddict, output_filename): """ Generate an ASD plot as used for upload to GraceDB. Parameters ---------- psddict: dictionary A dictionary keyed on ifo containing the PSDs as FrequencySeries objects output_filename: string The filename for the plot to be saved to Returns ------- None """ asd_fig, asd_ax = plt.subplots(1) for ifo in sorted(psddict.keys()): curr_psd = psddict[ifo] # Can't plot log(0) so start from point 1 asd_ax.loglog(curr_psd.sample_frequencies[1:], curr_psd[1:]**0.5 / DYN_RANGE_FAC, c=ifo_color(ifo), label=ifo) asd_ax.legend() asd_ax.set_xlim([10, 1300]) asd_ax.set_ylim([3E-24, 1E-20]) asd_ax.set_xlabel('Frequency (Hz)') asd_ax.set_ylabel('ASD') asd_fig.savefig(output_filename)
def upload(self, fname, gracedb_server=None, testing=True, extra_strings=None): """Upload this trigger to gracedb Parameters ---------- fname: str The name to give the xml file associated with this trigger gracedb_server: string, optional URL to the GraceDB web API service for uploading the event. If omitted, the default will be used. testing: bool Switch to determine if the upload should be sent to gracedb as a test trigger (True) or a production trigger (False). """ from ligo.gracedb.rest import GraceDb import matplotlib matplotlib.use('Agg') import pylab # first of all, make sure the event is saved on disk # as GraceDB operations can fail later self.save(fname) if self.snr_series is not None: if fname.endswith('.xml.gz'): snr_series_fname = fname.replace('.xml.gz', '.hdf') else: snr_series_fname = fname.replace('.xml', '.hdf') snr_series_plot_fname = snr_series_fname.replace('.hdf', '_snr.png') psd_series_plot_fname = snr_series_fname.replace('.hdf', '_psd.png') pylab.figure() for ifo in self.snr_series: curr_snrs = self.snr_series[ifo] curr_snrs.save(snr_series_fname, group='%s/snr' % ifo) pylab.plot(curr_snrs.sample_times, abs(curr_snrs), c=ifo_color(ifo), label=ifo) if ifo in self.ifos: snr = self.coinc_results['foreground/%s/%s' % (ifo, 'snr')] endt = self.coinc_results['foreground/%s/%s' % (ifo, 'end_time')] pylab.plot([endt], [snr], c=ifo_color(ifo), marker='x') pylab.legend() pylab.xlabel('GPS time (s)') pylab.ylabel('SNR') pylab.savefig(snr_series_plot_fname) pylab.close() pylab.figure() for ifo in self.snr_series: # Undo dynamic range factor curr_psd = self.psds[ifo].astype(numpy.float64) curr_psd /= pycbc.DYN_RANGE_FAC ** 2.0 curr_psd.save(snr_series_fname, group='%s/psd' % ifo) # Can't plot log(0) so start from point 1 pylab.loglog(curr_psd.sample_frequencies[1:], curr_psd[1:]**0.5, c=ifo_color(ifo), label=ifo) pylab.legend() pylab.xlim([20, 2000]) pylab.ylim([1E-24, 1E-21]) pylab.xlabel('Frequency (Hz)') pylab.ylabel('ASD') pylab.savefig(psd_series_plot_fname) gid = None try: # try connecting to GraceDB gracedb = GraceDb(gracedb_server) \ if gracedb_server is not None else GraceDb() # create GraceDB event group = 'Test' if testing else 'CBC' r = gracedb.createEvent(group, "pycbc", fname, "AllSky").json() gid = r["graceid"] logging.info("Uploaded event %s", gid) if self.is_hardware_injection: gracedb.writeLabel(gid, 'INJ') logging.info("Tagging event %s as an injection", gid) # upload PSDs. Note that the PSDs are already stored in the # original event file and we just upload a copy of that same file # here. This keeps things as they were in O2 and can be removed # after updating the follow-up infrastructure psd_fname = 'psd.xml.gz' if fname.endswith('.gz') else 'psd.xml' gracedb.writeLog(gid, "PyCBC PSD estimate from the time of event", psd_fname, open(fname, "rb").read(), "psd") logging.info("Uploaded PSDs for event %s", gid) # add other tags and comments gracedb.writeLog( gid, "Using PyCBC code hash %s" % pycbc_version.git_hash) extra_strings = [] if extra_strings is None else extra_strings for text in extra_strings: gracedb.writeLog(gid, text) # upload SNR series in HDF format and plots if self.snr_series is not None: gracedb.writeLog(gid, 'SNR timeseries HDF file upload', filename=snr_series_fname) gracedb.writeLog(gid, 'SNR timeseries plot upload', filename=snr_series_plot_fname, tag_name=['background'], displayName=['SNR timeseries']) gracedb.writeLog(gid, 'PSD plot upload', filename=psd_series_plot_fname, tag_name=['psd'], displayName=['PSDs']) except Exception as exc: logging.error('Something failed during the upload/annotation of ' 'event %s on GraceDB. The event may not have been ' 'uploaded!', fname) logging.error(str(exc)) return gid
def upload(self, fname, gracedb_server=None, testing=True, extra_strings=None): """Upload this trigger to gracedb Parameters ---------- fname: str The name to give the xml file associated with this trigger gracedb_server: string, optional URL to the GraceDB web API service for uploading the event. If omitted, the default will be used. testing: bool Switch to determine if the upload should be sent to gracedb as a test trigger (True) or a production trigger (False). """ from ligo.gracedb.rest import GraceDb import matplotlib matplotlib.use('Agg') import pylab # first of all, make sure the event is saved on disk # as GraceDB operations can fail later self.save(fname) if self.snr_series is not None: if fname.endswith('.xml.gz'): snr_series_fname = fname.replace('.xml.gz', '.hdf') else: snr_series_fname = fname.replace('.xml', '.hdf') snr_series_plot_fname = snr_series_fname.replace('.hdf', '_snr.png') psd_series_plot_fname = snr_series_fname.replace('.hdf', '_psd.png') pylab.figure() for ifo in sorted(self.snr_series): curr_snrs = self.snr_series[ifo] curr_snrs.save(snr_series_fname, group='%s/snr' % ifo) pylab.plot(curr_snrs.sample_times, abs(curr_snrs), c=ifo_color(ifo), label=ifo) if ifo in self.ifos: snr = self.coinc_results['foreground/%s/%s' % (ifo, 'snr')] endt = self.coinc_results['foreground/%s/%s' % (ifo, 'end_time')] pylab.plot([endt], [snr], c=ifo_color(ifo), marker='x') pylab.legend() pylab.xlabel('GPS time (s)') pylab.ylabel('SNR') pylab.savefig(snr_series_plot_fname) pylab.close() pylab.figure() for ifo in sorted(self.snr_series): # Undo dynamic range factor curr_psd = self.psds[ifo].astype(numpy.float64) curr_psd /= pycbc.DYN_RANGE_FAC ** 2.0 curr_psd.save(snr_series_fname, group='%s/psd' % ifo) # Can't plot log(0) so start from point 1 pylab.loglog(curr_psd.sample_frequencies[1:], curr_psd[1:]**0.5, c=ifo_color(ifo), label=ifo) pylab.legend() pylab.xlim([10, 1300]) pylab.ylim([3E-24, 1E-20]) pylab.xlabel('Frequency (Hz)') pylab.ylabel('ASD') pylab.savefig(psd_series_plot_fname) pylab.close() if self.probabilities is not None: prob_fname = fname.replace('.xml.gz', '_probs.json') prob_plot_fname = prob_fname.replace('.json', '.png') prob_plot = {k: v for (k, v) in self.probabilities.items() if v != 0.0} labels, sizes = zip(*prob_plot.items()) colors = [source_color(label) for label in labels] fig, ax = pylab.subplots() ax.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', textprops={'fontsize': 15}) ax.axis('equal') fig.savefig(prob_plot_fname) pylab.close() gid = None try: # try connecting to GraceDB gracedb = GraceDb(gracedb_server) \ if gracedb_server is not None else GraceDb() # create GraceDB event group = 'Test' if testing else 'CBC' r = gracedb.createEvent(group, "pycbc", fname, "AllSky").json() gid = r["graceid"] logging.info("Uploaded event %s", gid) if self.is_hardware_injection: gracedb.writeLabel(gid, 'INJ') logging.info("Tagging event %s as an injection", gid) # upload PSDs. Note that the PSDs are already stored in the # original event file and we just upload a copy of that same file # here. This keeps things as they were in O2 and can be removed # after updating the follow-up infrastructure psd_fname = 'psd.xml.gz' if fname.endswith('.gz') else 'psd.xml' gracedb.writeLog(gid, "PyCBC PSD estimate from the time of event", psd_fname, open(fname, "rb").read(), "psd") logging.info("Uploaded PSDs for event %s", gid) # add info for tracking code version version_str = 'Using PyCBC version {}{} at {}' version_str = version_str.format( pycbc_version.version, ' (release)' if pycbc_version.release else '', os.path.dirname(pycbc.__file__)) gracedb.writeLog(gid, version_str) extra_strings = [] if extra_strings is None else extra_strings for text in extra_strings: gracedb.writeLog(gid, text, tag_name=['analyst_comments']) # upload SNR series in HDF format and plots if self.snr_series is not None: gracedb.writeLog(gid, 'SNR timeseries HDF file upload', filename=snr_series_fname) gracedb.writeLog(gid, 'SNR timeseries plot upload', filename=snr_series_plot_fname, tag_name=['background'], displayName=['SNR timeseries']) gracedb.writeLog(gid, 'PSD plot upload', filename=psd_series_plot_fname, tag_name=['psd'], displayName=['PSDs']) # upload source probabilities in json format and plot if self.probabilities is not None: gracedb.writeLog(gid, 'source probabilities JSON file upload', filename=prob_fname, tag_name=['em_follow']) logging.info('Uploaded source probabilities for event %s', gid) gracedb.writeLog(gid, 'source probabilities plot upload', filename=prob_plot_fname, tag_name=['em_follow']) logging.info('Uploaded source probabilities pie chart for ' 'event %s', gid) except Exception as exc: logging.error('Something failed during the upload/annotation of ' 'event %s on GraceDB. The event may not have been ' 'uploaded!', fname) logging.error(str(exc)) return gid
"""This example shows how to determine when a detector is active.""" import matplotlib.pyplot as pp from pycbc import dq from pycbc.results import ifo_color start_time = 1126051217 end_time = start_time + 100000 # Get times that the Hanford detector has data hsegs = dq.query_flag('H1', 'DATA', start_time, end_time) # Get times that the Livingston detector has data lsegs = dq.query_flag('L1', 'DATA', start_time, end_time) pp.figure(figsize=[10, 2]) for seg in lsegs: start, end = seg pp.axvspan(start, end, color=ifo_color('L1'), ymin=0.1, ymax=0.4) for seg in hsegs: start, end = seg pp.axvspan(start, end, color=ifo_color('H1'), ymin=0.6, ymax=0.9) pp.xlabel('Time (s)') pp.show()
#!/usr/bin/env python import sys import numpy as np import h5py import pylab as pl import pycbc from pycbc.results import ifo_color pl.figure(figsize=(10, 8)) with h5py.File(sys.argv[1], 'r') as hf: for ifo in ['H1', 'L1', 'V1']: if ifo + '/psd' not in hf: continue df = hf[ifo + '/psd'].attrs['delta_f'] asd = hf[ifo + '/psd'][:]**0.5 / pycbc.DYN_RANGE_FAC f = np.arange(len(asd)) * df pl.loglog(f, asd, '-', label=ifo, color=ifo_color(ifo)) pl.title(sys.argv[1]) pl.xlim(10, 1024) pl.ylim(1e-24, 1e-19) pl.xlabel('Frequency [Hz]') pl.ylabel('Amplitude spectral density') pl.grid() pl.legend() pl.tight_layout() pl.savefig(sys.argv[2])
def upload(self, fname, gracedb_server=None, testing=True, extra_strings=None, search='AllSky'): """Upload this trigger to gracedb Parameters ---------- fname: str The name to give the xml file associated with this trigger gracedb_server: string, optional URL to the GraceDB web API service for uploading the event. If omitted, the default will be used. testing: bool Switch to determine if the upload should be sent to gracedb as a test trigger (True) or a production trigger (False). search: str String going into the "search" field of the GraceDB event. """ from ligo.gracedb.rest import GraceDb import matplotlib matplotlib.use('Agg') import pylab as pl # first of all, make sure the event is saved on disk # as GraceDB operations can fail later self.save(fname) gid = None try: # try connecting to GraceDB gracedb = GraceDb(gracedb_server) \ if gracedb_server is not None else GraceDb() # create GraceDB event group = 'Test' if testing else 'CBC' r = gracedb.createEvent(group, "pycbc", fname, search).json() gid = r["graceid"] logging.info("Uploaded event %s", gid) if self.is_hardware_injection: gracedb.writeLabel(gid, 'INJ') logging.info("Tagging event %s as an injection", gid) # add info for tracking code version gracedb_tag_with_version(gracedb, gid) extra_strings = [] if extra_strings is None else extra_strings for text in extra_strings: gracedb.writeLog(gid, text, tag_name=['analyst_comments']) except Exception as exc: logging.error( 'Something failed during the upload/annotation of ' 'event %s on GraceDB. The event may not have been ' 'uploaded!', fname) logging.error(str(exc)) # plot the SNR timeseries and noise PSDs if self.snr_series is not None: if fname.endswith('.xml.gz'): snr_series_fname = fname.replace('.xml.gz', '.hdf') else: snr_series_fname = fname.replace('.xml', '.hdf') snr_series_plot_fname = snr_series_fname.replace( '.hdf', '_snr.png') asd_series_plot_fname = snr_series_fname.replace( '.hdf', '_asd.png') pl.figure() ref_time = int(self.merger_time) for ifo in sorted(self.snr_series): curr_snrs = self.snr_series[ifo] curr_snrs.save(snr_series_fname, group='%s/snr' % ifo) pl.plot(curr_snrs.sample_times - ref_time, abs(curr_snrs), c=ifo_color(ifo), label=ifo) if ifo in self.ifos: base = 'foreground/{}/'.format(ifo) snr = self.coinc_results[base + 'snr'] mt = (self.coinc_results[base + 'end_time'] + self.time_offset) pl.plot([mt - ref_time], [snr], c=ifo_color(ifo), marker='x') pl.legend() pl.xlabel('GPS time from {:d} (s)'.format(ref_time)) pl.ylabel('SNR') pl.savefig(snr_series_plot_fname) pl.close() generate_asd_plot(self.psds, asd_series_plot_fname) # Additionally save the PSDs into the snr_series file for ifo in sorted(self.psds): # Undo dynamic range factor curr_psd = self.psds[ifo].astype(numpy.float64) curr_psd /= pycbc.DYN_RANGE_FAC**2.0 curr_psd.save(snr_series_fname, group='%s/psd' % ifo) if self.probabilities is not None: prob_fname = fname.replace('.xml.gz', '_probs.json') prob_plot_fname = prob_fname.replace('.json', '.png') prob_plot = { k: v for (k, v) in self.probabilities.items() if v != 0.0 } labels, sizes = zip(*prob_plot.items()) colors = [source_color(label) for label in labels] fig, ax = pl.subplots() ax.pie(sizes, labels=labels, colors=colors, autopct='%1.1f%%', textprops={'fontsize': 15}) ax.axis('equal') fig.savefig(prob_plot_fname) pl.close() # upload SNR series in HDF format and plots if gid is not None and self.snr_series is not None: try: gracedb.writeLog(gid, 'SNR timeseries HDF file upload', filename=snr_series_fname) gracedb.writeLog(gid, 'SNR timeseries plot upload', filename=snr_series_plot_fname, tag_name=['background'], displayName=['SNR timeseries']) gracedb.writeLog(gid, 'ASD plot upload', filename=asd_series_plot_fname, tag_name=['psd'], displayName=['ASDs']) except Exception as exc: logging.error('Failed to upload plots for %s', gid) logging.error(str(exc)) # upload source probabilities in JSON format and plot if gid is not None and self.probabilities is not None: try: gracedb.writeLog(gid, 'Source probabilities JSON file upload', filename=prob_fname, tag_name=['em_follow']) logging.info('Uploaded source probabilities for event %s', gid) gracedb.writeLog(gid, 'Source probabilities plot upload', filename=prob_plot_fname, tag_name=['em_follow']) logging.info( 'Uploaded source probabilities pie chart for ' 'event %s', gid) except Exception as exc: logging.error( 'Failed to upload source probability results for %s', gid) logging.error(str(exc)) return gid