27The KNOwn Pulsar pipelinE - lalpulsar_knope_collate_results
30from __future__
import print_function, division
40from configparser
import ConfigParser
50from lalpulsar
import git_version
54__author__ =
"Matthew Pitkin <matthew.pitkin@ligo.org>"
55__version__ =
"git id {}".
format(git_version.id)
56__date__ = git_version.date
65 <meta http-equiv="Content-Type" content=
"text/html; charset=utf-8"/>
66 <meta name=
"description" content=
"Known pulsar search results"/>
67 <meta charset=
"UTF-8">
69 <title>Known pulsar search results</title>
71 <link rel=
"stylesheet" type=
"text/css" href=
"{cssfile}"/>
76<h1>Results table {nsources}</h1>
78<!-- The table of pulsars
and results -->
84<!-- Footnotes
from the table -->
99if __name__ == "__main__":
100 description = """This script will collate results pages from multiple pulsars into a signal table."""
101 epilog =
"""An example configuration file could contain the following:
103# a section containing output information
105path = path_to_output_directory
109path = path_to_input_directory
113detectors = [
'H1',
'L1',
'Joint']
115sort_direction = ascending
116results = [
'h0ul',
'ell']
117parameters = [
'f0rot',
'ra',
'dec']
120 parser = argparse.ArgumentParser(
121 description=description,
123 formatter_class=argparse.RawDescriptionHelpFormatter,
125 parser.add_argument("inifile", help=
"The configuration (.ini) file")
128 opts = parser.parse_args()
130 inifile = opts.inifile
137 "Error... cannot parse configuration file '%s'" % inifile, file=sys.stderr
143 outpath = cp.get(
"output",
"path")
146 "Error... no output directory 'path' specified in [output] section.",
152 if not os.access(outpath, os.W_OK)
and not os.path.isdir(
159 "Error... cannot make output directory '%s'." % outpath, file=sys.stderr
165 inpath = cp.get(
"input",
"path")
168 "Error... no input directory 'path' specified in [input] section.",
173 if not os.path.isdir(inpath):
174 print(
"Error... input path '%s' does not exist." % inpath, file=sys.stderr)
179 sorttype = cp.get(
"general",
"sort_value")
196 "Error... sorting can only be on either 'name', 'freq', 'ra', 'dec', 'sdlim', 'hul', 'ell', 'sdrat' or 'dist'.",
203 sortdirection = cp.get(
"general",
"sort_direction")
204 if sortdirection ==
"ascending":
206 elif sortdirection ==
"descending":
215 ifos = ast.literal_eval(cp.get(
"general",
"detectors"))
217 print(
"Error... could not parse list of detectors to include.", file=sys.stderr)
223 ol.upper()
for ol
in ast.literal_eval(cp.get(
"general",
"results"))
226 outputlims = [
"H0UL"]
231 ov.upper()
for ov
in ast.literal_eval(cp.get(
"general",
"parameters"))
234 outputvals = [
"F0ROT"]
241 resdirs = os.listdir(inpath)
242 if len(resdirs) == 0:
244 "Error... the input directory '%s' contains no other directories." % inpath,
251 os.path.join(inpath, rd)
253 if os.path.isfile(os.path.join(inpath, rd,
"{}.ini".
format(rd)))
255 totalsources = len(sourcedirs)
261 if ".json" == os.path.splitext(fd)[-1]:
262 jsonfile = os.path.join(d, fd)
269 fp = open(jsonfile,
"r")
270 pdata = json.load(fp)
274 "Warning... could not read JSON file '%s'. Skipping this directory."
280 if "Pulsar data" not in pdata:
282 "Warning... no 'Pulsar data' field in JSON file '%s'. Skipping this directory."
288 if "PSR" not in pdata:
290 "Warning... no 'PSR' pulsar name field in JSON file '%s'. Skipping this directory."
300 "Warning... no key for detector '%s' in JSON file '%s'. Skipping this directory."
309 resultsdata[pdata[
"PSR"]] = pdata
310 resultsdata[pdata[
"PSR"]][
"path"] = os.path.relpath(
315 if len(resultsdata) == 0:
316 print(
"Error... no reults were found!", file=sys.stderr)
320 if "freq" == sorttype:
322 (resultsdata[pname][
"Pulsar data"][
"F0"], pname)
for pname
in resultsdata
324 elif "dec" == sorttype:
326 (resultsdata[pname][
"Pulsar data"][
"DEC"], pname)
for pname
in resultsdata
328 elif "dist" == sorttype:
330 (resultsdata[pname][
"Pulsar data"][
"DIST"], pname)
for pname
in resultsdata
332 elif "sdlim" == sorttype:
334 (resultsdata[pname][
"Pulsar data"][
"spin-down limit"], pname)
335 for pname
in resultsdata
342 min([resultsdata[pname][ifo][
"Upper limits"][
"H0"]
for ifo
in ifos]),
345 for pname
in resultsdata
352 min([resultsdata[pname][ifo][
"Upper limits"][
"ELL"]
for ifo
in ifos]),
355 for pname
in resultsdata
364 resultsdata[pname][ifo][
"Upper limits"][
"spin-down ratio"]
370 for pname
in resultsdata
373 sortlist = [(pname, pname)
for pname
in resultsdata]
376 p[1]
for p
in sorted(sortlist, reverse=reverse)
380 numprepars = 1 + len(outputvals)
381 numlims = len(outputlims)
384 showbci = showbcin = 0
385 if "BCI" in outputlims:
388 outputlims.pop(outputlims.index(
"BCI"))
390 if "BCIN" in outputlims:
393 outputlims.pop(outputlims.index(
"BCIN"))
398 ltable =
latextable(ncolumns=(numprepars + numlims * nifos + showbci + showbcin))
399 ltable.set_caption(
"Limits on the gravitational wave amplitude for known pulsars")
403 ltable.addrow(underline=
True)
404 restable.adddata(
"", dataclass=
"bottomborder", header=
True, colspan=numprepars)
405 ltable.adddata(
"~", multicolumn=numprepars)
409 ncolspan += showbci + showbcin
414 datastyle=
"text-align:center; border-left:1px solid #000; border-bottom:1px solid #000",
417 ltable.adddata(ifo, multicolumn=ncolspan)
421 ltable.addrow(underline=
True)
422 restable.adddata(
"Pulsar", dataclass=
"bottomborder", header=
True)
423 ltable.adddata(
"Pulsar")
424 for prepar
in outputvals:
425 restable.adddata(paramhtmldict[prepar], dataclass=
"bottomborder", header=
True)
426 ltable.adddata(paramlatexdict[prepar])
429 dataclass =
"leftborder"
430 datastyle =
"border-bottom:1px solid #000"
431 for ol
in outputlims:
433 cr = list(resultsdata.values())[0][ifo][
"Upper limits"][
437 paramhtmldict[ol].
format(cr),
442 ltable.adddata(paramlatexdict[ol].
format(cr))
450 ltable.adddata(paramlatexdict[ol])
451 dataclass =
"bottomborder"
458 paramhtmldict[
"BCI"],
463 ltable.adddata(paramlatexdict[
"BCI"])
466 paramhtmldict[
"BCIN"],
471 ltable.adddata(paramlatexdict[
"BCIN"])
482 "SDLIM":
"spin-down limit",
483 "SDRAT":
"spin-down ratio",
484 "BSN":
"Signal vs Noise",
485 "BCI":
"Coherent vs Incoherent",
486 "BCIN":
"Coherent vs Incoherent or Noise",
494 for pname
in sortedlist:
498 pulsar = resultsdata[pname]
502 atag(os.path.join(pulsar[
"path"], pname +
".html"), linktext=pname).text
505 re.sub(
r"\-",
"\\\\textminus", pname)
508 for prepar
in outputvals:
513 if "SDLIM" in prepar:
515 pulsar[
"Pulsar data"][
"P1_I"] !=
None
518 pulsar[
"Pulsar data"][
"P1_I"] > 0.0
520 htmlsdtag =
htmltag(
"sup", tagtext=
"†").text
521 latexsdtag =
r"$\dagger$"
523 elif pulsar[
"Pulsar data"][
"ASSOC"] !=
None:
524 if "GC" in pulsar[
"Pulsar data"][
"ASSOC"]:
525 htmlsdtag =
htmltag(
"sup", tagtext=
"‡").text
526 latexsdtag =
r"$\ddagger$"
529 if prepar
in convdict:
530 pn = convdict[prepar]
533 if pn
in pulsar[
"Pulsar data"]:
534 preval = pulsar[
"Pulsar data"][pn]
539 disphtmlfunc = paramhtmldispfunc.__dict__[prepar]
540 displatexfunc = paramlatexdispfunc.__dict__[prepar]
547 restable.adddata(prevalhtml + htmlsdtag)
548 ltable.adddata(prevallatex + latexsdtag)
551 dataclass =
"leftborder"
553 for limpar
in outputlims:
554 if limpar
in convdict:
555 ln = convdict[limpar]
559 section =
"Upper limits"
563 section =
"Bayes factors"
565 if ln
in pulsar[ifo][section]:
566 limval = pulsar[ifo][section][ln]
573 limval = limval / np.log(10.0)
574 disphtmlfunc = paramhtmldispfunc.__dict__[limpar]
575 displatexfunc = paramlatexdispfunc.__dict__[limpar]
582 restable.adddata(limvalhtml, dataclass=dataclass)
584 ltable.adddata(limvallatex)
588 for bu, show
in [(
"BCI", showbci), (
"BCIN", showbcin)]:
591 if bn
in pulsar[ifo][
"Bayes factors"]:
592 bval = pulsar[ifo][
"Bayes factors"][bn]
597 bval = bval / np.log(10.0)
598 disphtmlfunc = paramhtmldispfunc.__dict__[bu]
599 displatexfunc = paramlatexdispfunc.__dict__[bu]
606 restable.adddata(bvalhtml, dataclass=dataclass)
608 ltable.adddata(bvallatex)
610 htmlinput[
"nsources"] =
"(%d/%d sources)" % (cursources, totalsources)
611 htmlinput[
"resultstable"] = restable.tabletext
614 if dagger
or ddagger:
615 htmlfootnotes =
htmltag(
"div", tagclass=
"footnotes")
617 htmlfootnotes +=
htmltag(
"sup", tagtext=
"†").text
618 htmlfootnotes +=
" The spin-down limit was calculated using a spin-down "
619 htmlfootnotes +=
atag(
620 "http://www.atnf.csiro.au/research/pulsar/psrcat/psrcat_help.html?type=normal&highlight=p1_i#p1_i",
621 linktext=
"corrected",
623 htmlfootnotes +=
" for proper motion effects.\n"
624 htmlfootnotes +=
"<br />\n"
625 ltable.set_postamble(
626 "$\\dagger$ The pulsar's spin-down is corrected for proper motion effects. \\\\\n"
629 htmlfootnotes +=
htmltag(
"sup", tagtext=
"‡").text
630 htmlfootnotes +=
" The spin-down limit was calculated using a characteristic spin-down age of 10<sup>9</sup> years.\n"
631 ltable.set_postamble(
633 +
"$\\ddagger$ The pulsar's spin-down is calculated using a characteristic spin-down age of $10^9$ years.\n"
635 htmlinput[
"footnotes"] = htmlfootnotes.text
637 htmlinput[
"footnotes"] =
""
640 cssfile = os.path.join(outpath,
"table.css")
641 fp = open(cssfile,
"w")
642 fp.write(results_table_css)
645 htmlinput[
"cssfile"] = os.path.basename(cssfile)
648 now = datetime.datetime.now()
651 htmlinput[
"footer"] =
"{} - {}<br><br>Command lines used:<br>{}<br>{}<br>".
format(
652 __author__, now.strftime(
"%a %d %b %Y"),
" ".join(sys.argv), __version__
657 htmlfile = os.path.join(outpath,
"index.html")
658 fp = open(htmlfile,
"w")
659 fp.write(htmlpage.format(**htmlinput))
662 print(
"Error... there was a problem outputting the html page.", file=sys.stderr)
667 latexfile = os.path.join(outpath,
"resultstable.tex")
668 fp = open(latexfile,
"w")
669 fp.write(ltable.tabletext)
673 "Error... there was a problem outputting the LaTeX table.", file=sys.stderr
Class to make and return a html table.
A class to create a html tag.
Class to make a return a LaTeX table.