3 # Copyright (C) 2012 Kipp Cannon, Chad Hanna, Drew Keppel
5 # This program is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by the
7 # Free Software Foundation; either version 2 of the License, or (at your
8 # option) any later version.
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 # Public License for more details.
15 # You should have received a copy of the GNU General Public License along
16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 # A program to request some followup data from a running gstlal_inspiral job based on gracedb submissions notified by lvalert
24 from pylal
import rate
25 os.environ[
"MPLCONFIGDIR"] =
"/tmp"
30 from glue.ligolw
import utils
32 from gstlal
import far
34 from glue.ligolw
import ligolw, table, lsctables, param, array
35 array.use_in(ligolw.LIGOLWContentHandler)
36 param.use_in(ligolw.LIGOLWContentHandler)
37 lsctables.use_in(ligolw.LIGOLWContentHandler)
42 from ligo.gracedb.rest
import GraceDb
44 from ligo.lvalert.utils
import get_LVAdata_from_stdin
46 def get_filename(gracedb_client, graceid, filename, retries = 3, retry_delay = 10.0, ignore_404 = False):
47 for i in range(retries):
48 logging.info(
"retrieving \"%s\" for %s" % (filename, graceid))
49 response = gracedb_client.files(graceid, filename)
50 if response.status == httplib.OK:
52 if response.status == httplib.NOT_FOUND and ignore_404:
53 logging.warning(
"retrieving \"%s\" for %s: (%d) %s. skipping ..." % (filename, graceid, response.status, response.reason))
55 logging.warning(
"retrieving \"%s\" for %s: (%d) %s. pausing ..." % (filename, graceid, response.status, response.reason))
56 time.sleep(retry_delay)
57 raise Exception(
"retrieving \"%s\" for %s: (%d) %s" % (filename, graceid, response.status, response.reason))
60 if len(sys.argv) == 1:
61 lvalert_data = get_LVAdata_from_stdin(sys.stdin, as_dict = True)
62 logging.info(
"%(alert_type)s-type alert for event %(uid)s" % lvalert_data)
63 logging.info(
"lvalert data: %s" % repr(lvalert_data))
64 filename = os.path.split(urlparse.urlparse(lvalert_data[
"file"]).path)[-1]
65 if filename not in (u
"coinc.xml",) and
"_CBC_" not in filename:
66 logging.info(
"filename is not 'coinc.xml'. skipping")
68 gid = str(lvalert_data[
"uid"])
78 filename = get_filename(gracedb, gid,
"coinc.xml", retries = 3, retry_delay = 10.0, ignore_404 = False)
79 xmldoc, checksum = utils.load_fileobj(filename, contenthandler = ligolw.LIGOLWContentHandler)
80 coinc_inspiral_row = lsctables.table.get_table(xmldoc, lsctables.CoincInspiralTable.tableName)[0]
81 sngl_inspiral_table = lsctables.table.get_table(xmldoc, lsctables.SnglInspiralTable.tableName)
82 process = lsctables.table.get_table(xmldoc, lsctables.ProcessTable.tableName)
83 params = lsctables.table.get_table(xmldoc, lsctables.ProcessParamsTable.tableName)
84 snr_chisq_dict = dict(((ifo,(None,None)) for ifo in [
'H1',
'L1',
'V1']))
85 for r in sngl_inspiral_table:
86 snr_chisq_dict[r.ifo] = (r.snr, r.chisq)
88 if r.program ==
"gstlal_inspiral" and r.param ==
"--likelihood-file":
90 if r.program ==
"gstlal_inspiral" and r.param ==
"--job-tag":
93 if r.program ==
"gstlal_inspiral":
96 url = open(
"%s_registry.txt" % tag).readline().strip()
102 #FIXME don
't hardcode port number
103 t,snr = numpy.loadtxt(urllib.urlopen("%ssnr_history.txt" % url), unpack = True)
104 t -= coinc_inspiral_row.get_end()
106 pylab.semilogy(t, snr)
108 pylab.xlabel('Time from event (s)
')
109 fname = '%s/%s_snrtime.png
' % (gid, gid)
110 pylab.ylim([min(snr), max(snr)])
111 pylab.xlim([min(t), max(t)])
114 gracedb.writeLog(gid, "SNR vs time", filename = fname, filecontents = open(fname).read(), tagname = "background")
120 likelihood_data = far.parse_likelihood_control_doc(utils.load_filename(path, contenthandler = far.ThincaCoincParamsDistributions.LIGOLWContentHandler))[0]
122 counts = likelihood_data.background_rates
123 inj = likelihood_data.injection_rates
125 bgcol = (224/255.,224/255.,224/255.)
127 likely = copy.deepcopy(inj)
128 for i, ifo in enumerate(['H1
', 'L1
', 'V1
']):
129 snrm, chisqm = snr_chisq_dict[ifo]
132 likely[ifo+"_snr_chi"].array /= counts[ifo+"_snr_chi"].array
133 for name, obj in (("background", counts),):
134 fig = pylab.figure(figsize=(6,4), facecolor = 'g
')
135 fig.patch.set_alpha(0.0)
136 H1 = obj[ifo+"_snr_chi"].array
137 snr = obj[ifo+"_snr_chi"].bins[0].centres()[1:-1]
138 chi = obj[ifo+"_snr_chi"].bins[1].centres()[1:-1]
140 ax = pylab.subplot(111)
141 pylab.pcolormesh(snr, chi, numpy.log10(H1.T +1)[1:-1,1:-1])
142 if snrm is not None and chisqm is not None:
143 pylab.plot(snrm, chisqm / snrm / snrm, 'ko
', mfc = 'None
', ms = 14, mew=4)
144 if "Log" in str(obj[ifo+"_snr_chi"].bins[0]):
146 if "Log" in str(obj[ifo+"_snr_chi"].bins[1]):
150 pylab.ylabel('reduced chi^2 / SNR^2
')
151 pylab.ylim([0.001, 1])
153 pylab.title('%s: %s log base 10 (number + 1)
' % (ifo, name))
154 pylab.grid(color=(0.1,0.4,0.5), linewidth=2)
155 fname = '%s/%s_%s_snrchi.png
' % (gid, gid, ifo)
157 gracedb.writeLog(gid, "%s SNR/Chisq" % ifo, filename = fname, filecontents = open(fname).read(), tagname = "background")
163 # FIXME currently broken
166 for r in sngl_inspiral_table:
167 cachefile = "%s/%sframes.cache" % (gid, r.ifo)
168 subprocess.call(["createframecache.pl", cachefile, "/scratch/llcache/llhoft/%s" % r.ifo])
169 conffile = "%s/%sconfig.txt" % (gid, r.ifo)
170 f = open(conffile , "w")
171 channel = "%s:%s" % (r.ifo, r.channel)
176 frameType: '%s_llhoft
'
177 sampleFrequency: 16384
178 searchFrequencyRange: [10 2048]
179 #searchChirpRange: [+0 +0]
182 searchMaximumEnergyLoss: 0.2
183 searchWindowDuration: 0.25
184 whiteNoiseFalseRate: 1e-3
186 plotFrequencyRange: []
187 plotNormalizedEnergyRange: [0 25.5]
189 } """ % (channel, channel, channel, r.ifo))
192 tstr = str(r.get_end())
194 # actually run the scan
195 subprocess.call(["dmt_wscan", str(r.get_end()), conffile, cachefile, gid, "1", "1"])
197 # upload some plots to gracedb
198 for f in glob.glob("%s/*_spectrogram_autoscaled.png" % gid):
199 gracedb.writeLog(gid, "DMT omega scan", filename = f, filecontents = open(f).read(), tagname = "background")