Revision 6e053776a85e84f8665f99053ebacccb4e6eced1 authored by Collin Capano on 17 March 2020, 11:11:22 UTC, committed by GitHub on 17 March 2020, 11:11:22 UTC
* make add_input a public method * add separate funtions for pp plots and injection recovery * first stab at updating injection workflow * add function to create pp summary table; update the workflow * make default distribution section in create injections be 'prior' * use function for boiler-plate workflow options * set config-files in create injection node; whitespace * fix bug in setting injection file * fix some typos; use pp_summary_table to determine whether to do pp test * try to make pp jobs their own sub workflow * try not using any container workflow * fix bugs in figuring out dependencies for sub workflows * fix pp test page layout * make inj recovery plots have the same aspect ratio as pp plots * ensure pp params are enclosed in quotes * python 3: fix issue saving approximant to injection file * save metadata with inj recovery plots, and use bbox inches tight * whitespace * another fix to making the workflow dependencies * move function to add workflow cli group to workflow/core.py
1 parent 3c48bfd
pycbc_make_grb_summary_page
#!/usr/bin/env python
# Copyright (C) 2015 Andrew R. Williamson
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# =============================================================================
# Preamble
# =============================================================================
from __future__ import (division, print_function)
import os,sys,datetime,re,glob,shutil
from argparse import ArgumentParser
import random
import string
from pycbc.workflow.core import make_external_call
from pycbc.results.legacy_grb import *
from glue import markup
from pylal import grbsummary,rate,antenna,git_version
from lal.gpstime import gps_to_utc,LIGOTimeGPS
__author__ = "Andrew Williamson <andrew.williamson@ligo.org>"
__version__ = "git id %s" % git_version.id
__date__ = git_version.date
def parse_command_line():
parser = ArgumentParser()
parser.add_argument("-g", "--grb-name", type=str, default=None,
help="GRB name.")
parser.add_argument("-f", "--config-file", type=str,
default=None, help="location of the run ini file")
parser.add_argument("-i", "--ifo-tag", type=str, default=None,
help="The ifo tag, H1L1 or H1L1V1 for instance")
parser.add_argument("-t", "--start-time", type=int, default=None,
help="GPS time of the GRB trigger")
parser.add_argument("-r", "--ra", type=float, default=None,
help="Right ascension of external trigger")
parser.add_argument("-d", "--dec", type=float, default=None,
help="Declination of external trigger")
parser.add_argument("-o", "--output-path", type=str, default=os.getcwd(),
help="Post processing output directory")
parser.add_argument("-w", "--html-path", type=str, default=None,
help="Final web directory")
parser.add_argument("-s", "--seg-plot", type=str, default=None,
help="Path to segments plot")
parser.add_argument("-D", "--exclusion-injections", type=str, default=None,
help="A comma seperated list of the detection injection"
" run names.")
parser.add_argument("-T", "--tuning-injections", type=str, default=None,
help="A comma seperated list of the tuning injection "
"run names.")
parser.add_argument("-O", "--open-box", action="store_true",
help ="Use to show onsource results")
parser.add_argument("-S", "--time-slides", action="store_true",
help ="If run featured time slides")
parser.add_argument("-G", "--sky-grid", default=False,
help="Include sky grid information")
parser.add_argument("-M", "--mass-bins", type=str, default="0.0-8.0",
help="comma separated list of dash-separated pairs "
"of m_low-m_high mass bins")
parser.add_argument("-n", "--ipn", default=False,
help="Include ipn information")
parser.add_argument("-e", "--ipn-error", type=float, default=None,
help="size of the IPN error box")
args = parser.parse_args()
if not args.config_file:
parser.error("must provide --config-file")
if not args.ifo_tag:
parser.error("must provide --ifo-tag")
if not args.html_path:
parser.error("must provide --html-path")
return args
# =============================================================================
# Main function
# =============================================================================
def build_grb_results_page(args, inifile, outdir, htmldir, ifoTag,
detectionInjList=[], tuningInjList=[],
open_box=False, grid=False, ipn=False,
massBins = [('0','8.0')]):
"""
Builds the result webpage for a PyGRB workflow and places it in an
output directory along with the workflow result plots and other outputs.
Parameters
----------
args : argparse
Parsed argparse command line arguments.
inifile : file
The parsed configuration file used to generate the workflow.
outdir : directory
The directory containing the post processing outputs, where the .html file
will be written to.
htmldir : directory
The web-accessible directory where all final workflow outputs will be
copied to.
ifoTag : str
The string representing all interferometers used in the analysis.
detectionInjList : list
List of tags of the detection injection sets.
tuningInjList : list
List of tags of the tuning injection sets.
open_box : boolean
If true, generates the open box webpage. Otherwise a closed box page is
generated.
grid : boolean
If true, uses sky grid information.
ipn : boolean
If true, a page for an IPN GRB is generated.
massBins : list
A list of tuples, each tuple representing the upper and lower bounds of
a bin in mass parameter space, used to split the triggers into mass bins.
"""
# get entry information
ifos = args.ifo_tag
GRBnum = args.grb_name
os.chdir(outdir)
# get sections
#injList = glob.glob('injections*')
trials = sorted(glob.glob('OFFTRIAL_*'))
# initialise page
title = 'PyGRB + coh_PTF: A targeted, coherent CBC-GRB search\nGRB: %s'\
% GRBnum
if open_box:
title += '\nOPEN BOX PAGE'
else:
title += '\nCLOSED BOX PAGE'
banner = write_banner(title)
js = 'coh_PTF_html_summary.js'
script = {js:'javascript'}
css = 'coh_PTF_html_summary.css'
webpage = initialize_page(title, css, script, header=banner())
#if open_box:
# webpage.add('<img src="https://www.lsc-group.phys.uwm.edu/ligovirgo/cbc/public/segments/S5/OpenBox.jpg">')
#else:
# webpage.add('<img src="https://www.lsc-group.phys.uwm.edu/ligovirgo/cbc/public/segments/S5/thomasLegacy.jpg">')
# set divs
webpage.div(id="maintab")
webpage.div(id="content")
# write summary section
secname = 'Summary information'
i = 0
webpage.input(id="input_%s" % i, type="button", class_="h2",
onclick="toggleVisible('%s');" % i, value=secname)
webpage.div(id="div_%s" % i, style="display: none;")
# copy over segment plot
if os.path.isfile(args.seg_plot):
shutil.copy(args.seg_plot, outdir)
segplot = '%s/%s' % (outdir, os.path.basename(args.seg_plot))
else:
segplot = None
print('WARNING: Cannot find segments availability plot.', file=sys.stderr)
# get sky error from config
if grid:
err = args.sky_error
else:
err = None
if args.ipn:
ipnerr = args.ipn_error
webpage = write_summary(webpage, args, ifos, None, args.ipn, ipnerr)
webpage = write_antenna(webpage, args, segplot, None, args.ipn)
else:
webpage = write_summary(webpage, args, ifos, err, None, None)
webpage = write_antenna(webpage, args, segplot, grid, None)
# add links
inilink = os.path.basename(inifile)
inilinktext = 'ini-file used'
webpage.add(inilinktext)
webpage.a(href=inilink)
webpage.add('here')
webpage.a.close()
webpage.br()
webpage.div.close()
# copy over config file
if not os.path.isfile('%s/%s' % (outdir, os.path.basename(inifile))) or \
not os.path.samefile(inifile, '%s/%s'
% (outdir, os.path.basename(inifile))):
shutil.copy(inifile, outdir)
# add off source trig plots
secname = 'Offsource triggers versus time'
i += 1
webpage.input(id="input_%s" % i, type="button", class_="h2",
onclick="toggleVisible('%s');" % i, value=secname)
webpage.div(id="div_%s" % i, style="display: none;")
webpage = write_offsource(webpage, args, GRBnum)
webpage.div.close()
# add signal consistency plots
secname = 'Signal consistency plots'
i += 1
webpage.input(id="input_%s" % i, type="button", class_="h2",
onclick="toggleVisible('%s');" % i, value=secname)
webpage.div(id="div_%s" % i, style="display: none;")
webpage.h3()
webpage.add('Chi squared tests')
webpage.h3.close()
webpage.h4()
webpage.add('Plot key')
webpage.h4.close()
webpage.add('Blue crosses: Background triggers')
webpage.br()
webpage.add('Red crosses: Injections triggers')
webpage.br()
webpage.add('Black line: Veto line, shaded region indicates vetoed area')
webpage.br()
webpage.add('Yellow lines: Contours of new SNR')
webpage = write_chisq(webpage, tuningInjList, GRBnum)
webpage.h3()
webpage.add('Individual detector and null SNRs')
webpage.h3.close()
webpage.h4()
webpage.add('Plot key')
webpage.h4.close()
webpage.add('Blue crosses: Background triggers')
webpage.br()
webpage.add('Red crosses: Injections triggers')
webpage.br()
webpage.add('Black line: Veto line, shaded region indicates vetoed area')
webpage.h5()
webpage.add('For the null stat plot')
webpage.h5.close()
webpage.add('Green line: Above this triggers have reduced detection '
'statistic')
webpage.br()
webpage.add('Magenta line: On this line the statistic is reduced by a '
'factor of two')
webpage.h5()
webpage.add('For the single detector plots')
webpage.h5.close()
webpage.add('The cut is only applied to the two most sensitive detectors, '
'this can vary with mass and sky location, which is shown on '
'the plots')
webpage.br()
webpage.add('Green line: This indicates the expected SNR for optimally '
'oriented injections')
webpage.br()
webpage.add('Magenta and cyan lines: Show 1 and 2 sigma errors on the '
'green line')
webpage = write_inj_snrs(webpage, ifos, tuningInjList, GRBnum)
webpage.div.close()
# add found/missed plots
if detectionInjList:
secname = 'Found/missed injections'
i += 1
webpage.input(id="input_%s" % i, type="button", class_="h2",
onclick="toggleVisible('%d');" % i, value=secname)
webpage.div(id="div_%s" % i, style="display: none;")
webpage.h3()
webpage.add('A key for these plots')
webpage.h3.close()
webpage.add('Black cross indicates no trigger was found coincident '
'with the injection')
webpage.br()
webpage.add('Red cross indicates a trigger was found coincident with '
'the injection but it was vetoed')
webpage.br()
webpage.add('Green cross indicates that a trigger was found '
'coincident with the injection and it was louder than all '
'events in the offsource')
webpage.br()
webpage.add('Coloured circle indicates that a trigger was found '
'coincident with the injection but it was not louder than '
'all offsource events. The colour bar gives the FAP of '
'the trigger.')
webpage = write_found_missed(webpage, args, detectionInjList)
webpage.div.close()
if tuningInjList and grid:
# add injection recovery plots
secname = 'Injection recovery'
i += 1
webpage.input(id="input_%s" % i, type="button", class_="h2",
onclick="toggleVisible('%d');" % i, value=secname)
webpage.div(id="div_%s" % i, style="display: none;")
webpage = write_recovery(webpage, detectionInjList)
webpage.div.close()
if tuningInjList and ipn:
# add injection recovery plots
secname = 'Injection recovery'
i += 1
webpage.input(id="input_%s" % i, type="button", class_="h2",
onclick="toggleVisible('%d');" % i, value=secname)
webpage.div(id="div_%s" % i, style="display: none;")
webpage = write_recovery(webpage, detectionInjList)
webpage.div.close()
# add loudest off source events
secname = 'Loudest offsource events'
i += 1
webpage.input(id="input_%s" % i, type="button", class_="h2",
onclick="toggleVisible('%s');" % i, value=secname)
webpage.div(id="div_%s" % i, style="display: none;")
webpage = write_loudest_events(webpage, massBins)
webpage.div.close()
# write trial results
for ii,trial in zip(range(len(trials)),trials):
reduced = False
secname = 'Results for %s' % trial.replace('_',' ').title()
i += 1
webpage.input(id="input_%s" % i, type="button", class_="h2",
onclick="toggleVisible('%s');" % i, value=secname)
webpage.div(id="div_%s" % i, style="display: none;")
webpage = write_exclusion_distances(webpage, trial, detectionInjList,
massBins, reduced=reduced,
onsource=False)
webpage.div.close()
if open_box:
trial = 'ONSOURCE'
webpage.hr(class_="long", style="margin-top: 20px;")
# add on source trig plots
secname = 'Full data triggers versus time'
i += 1
webpage.input(id="input_%s" % i, type="button", class_="h2",
onclick="toggleVisible('%s');" % i, value=secname)
webpage.div(id="div_%s" % i, style="display: none;")
webpage = write_offsource(webpage, args, GRBnum, onsource=True)
webpage.div.close()
# write on source events
trial = 'ONSOURCE'
secname = 'Results for %s' % trial.replace('_',' ').title()
i += 1
webpage.input(id="input_%s" % i, type="button", class_="h2",
onclick="toggleVisible('%s');" % i, value=secname)
webpage.div(id="div_%s" % i, style="display: none;")
webpage = write_exclusion_distances(webpage, trial, detectionInjList,
massBins, reduced=False,
onsource=False)
webpage.div.close()
webpage.div.close()
webpage.div.close()
webpage.div.close()
webpage.body.close()
webpage.html.close()
file = open('%s/summary.html' % outdir, 'w')
file.write(webpage())
file.close()
if open_box:
suffix = "_OPEN"
else:
suffix = "_CLOSED"
html_path = htmldir + "/" + os.path.basename(htmldir) + suffix
if os.path.isdir(html_path):
warn = "WARNING: %s already exists! " % html_path
html_path += "_"
html_path += ''.join(random.choice(\
string.ascii_uppercase + string.digits) for _ in range(8))
warn += "Placing output page in %s." % html_path
sys.stdout.write(warn)
shutil.copytree(outdir, html_path)
shutil.copy2('%s/coh_PTF_html_summary.css' % os.path.dirname(outdir),
html_path)
shutil.copy2('%s/coh_PTF_html_summary.js' % os.path.dirname(outdir),
html_path)
#####################
# MAIN BODY OF CODE #
#####################
args = parse_command_line()
inifile = os.path.abspath(args.config_file)
outdir = os.path.abspath(args.output_path)
htmldir = os.path.abspath(args.html_path)
ifoTag = args.ifo_tag
grid = args.sky_grid
ipn = args.ipn
massBins = map(lambda p: map(float, p.split('-')),
args.mass_bins.split(','))
detInjsList = []
tunInjsList = []
if args.exclusion_injections:
detInjsList = args.exclusion_injections.split(",")
if args.tuning_injections:
tunInjsList = args.tuning_injections.split(",")
build_grb_results_page(args, inifile, outdir, htmldir, ifoTag,
detectionInjList=detInjsList,
tuningInjList=tunInjsList, open_box=args.open_box,
grid=grid, ipn=ipn, massBins = massBins)
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...