23 from __future__
import print_function, division
33 from six.moves.configparser
import ConfigParser
43 from lalpulsar
import git_version
47 __author__ =
"Matthew Pitkin <matthew.pitkin@ligo.org>"
48 __version__ =
"git id {}".format(git_version.id)
49 __date__ = git_version.date
58 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
59 <meta name="description" content="Known pulsar search results"/>
60 <meta charset="UTF-8">
62 <title>Known pulsar search results</title>
64 <link rel="stylesheet" type="text/css" href="{cssfile}"/>
69 <h1>Results table {nsources}</h1>
71 <!-- The table of pulsars and results -->
72 <div class="tablediv">
77 <!-- Footnotes from the table -->
92 if __name__ ==
"__main__":
93 description =
"""This script will collate results pages from multiple pulsars into a signal table."""
94 epilog =
"""An example configuration file could contain the following:
96 # a section containing output information
98 path = path_to_output_directory # the path to the output directory to contain the page [required]
100 # a section containing input directory information
102 path = path_to_input_directory # the path to the directory in which the individual results page directories live [required]
104 # a section containing general information for the output table
106 detectors = ['H1', 'L1', 'Joint'] # a list of detctors (including 'Joint') whose results will be output
107 sort_value = name # the pulsar parameter on which to sort the results (default: 'name') [Allowed: 'name', 'freq', 'ra', 'dec', 'sdlim', 'hul', 'ell', 'sdrat', 'dist']
108 sort_direction = ascending # sort in ascending or decending order (default: 'ascending')
109 results = ['h0ul', 'ell'] # a list of result parameters to output (default: ['h0ul'] - the h0 upper limit) [Allowed: 'h0ul', 'ell', 'sdrat', 'q22', 'bsn', 'bci', 'bcin', 'C21ul', 'C22ul']
110 parameters = ['f0rot', 'ra', 'dec'] # a list of pulsar parameters to output (default: ['f0rot'] - the pulsar's rotation frequency) [Allowed: 'f0rot', 'f0gw', 'f1rot', 'f1gw', 'sdlim', 'ra', 'dec', 'dist']
113 parser = argparse.ArgumentParser(
114 description=description,
116 formatter_class=argparse.RawDescriptionHelpFormatter,
118 parser.add_argument(
"inifile", help=
"The configuration (.ini) file")
121 opts = parser.parse_args()
123 inifile = opts.inifile
130 "Error... cannot parse configuration file '%s'" % inifile, file=sys.stderr
136 outpath = cp.get(
"output",
"path")
139 "Error... no output directory 'path' specified in [output] section.",
145 if not os.access(outpath, os.W_OK)
and not os.path.isdir(
152 "Error... cannot make output directory '%s'." % outpath, file=sys.stderr
158 inpath = cp.get(
"input",
"path")
161 "Error... no input directory 'path' specified in [input] section.",
166 if not os.path.isdir(inpath):
167 print(
"Error... input path '%s' does not exist." % inpath, file=sys.stderr)
172 sorttype = cp.get(
"general",
"sort_value")
189 "Error... sorting can only be on either 'name', 'freq', 'ra', 'dec', 'sdlim', 'hul', 'ell', 'sdrat' or 'dist'.",
196 sortdirection = cp.get(
"general",
"sort_direction")
197 if sortdirection ==
"ascending":
199 elif sortdirection ==
"descending":
208 ifos = ast.literal_eval(cp.get(
"general",
"detectors"))
210 print(
"Error... could not parse list of detectors to include.", file=sys.stderr)
216 ol.upper()
for ol
in ast.literal_eval(cp.get(
"general",
"results"))
219 outputlims = [
"H0UL"]
224 ov.upper()
for ov
in ast.literal_eval(cp.get(
"general",
"parameters"))
227 outputvals = [
"F0ROT"]
234 resdirs = os.listdir(inpath)
235 if len(resdirs) == 0:
237 "Error... the input directory '%s' contains no other directories." % inpath,
244 os.path.join(inpath, rd)
246 if os.path.isfile(os.path.join(inpath, rd,
"{}.ini".format(rd)))
248 totalsources = len(sourcedirs)
254 if ".json" == os.path.splitext(fd)[-1]:
255 jsonfile = os.path.join(d, fd)
262 fp = open(jsonfile,
"r")
263 pdata = json.load(fp)
267 "Warning... could not read JSON file '%s'. Skipping this directory."
273 if "Pulsar data" not in pdata:
275 "Warning... no 'Pulsar data' field in JSON file '%s'. Skipping this directory."
281 if "PSR" not in pdata:
283 "Warning... no 'PSR' pulsar name field in JSON file '%s'. Skipping this directory."
293 "Warning... no key for detector '%s' in JSON file '%s'. Skipping this directory."
302 resultsdata[pdata[
"PSR"]] = pdata
303 resultsdata[pdata[
"PSR"]][
"path"] = os.path.relpath(
308 if len(resultsdata) == 0:
309 print(
"Error... no reults were found!", file=sys.stderr)
313 if "freq" == sorttype:
315 (resultsdata[pname][
"Pulsar data"][
"F0"], pname)
for pname
in resultsdata
317 elif "dec" == sorttype:
319 (resultsdata[pname][
"Pulsar data"][
"DEC"], pname)
for pname
in resultsdata
321 elif "dist" == sorttype:
323 (resultsdata[pname][
"Pulsar data"][
"DIST"], pname)
for pname
in resultsdata
325 elif "sdlim" == sorttype:
327 (resultsdata[pname][
"Pulsar data"][
"spin-down limit"], pname)
328 for pname
in resultsdata
335 min([resultsdata[pname][ifo][
"Upper limits"][
"H0"]
for ifo
in ifos]),
338 for pname
in resultsdata
345 min([resultsdata[pname][ifo][
"Upper limits"][
"ELL"]
for ifo
in ifos]),
348 for pname
in resultsdata
357 resultsdata[pname][ifo][
"Upper limits"][
"spin-down ratio"]
363 for pname
in resultsdata
366 sortlist = [(pname, pname)
for pname
in resultsdata]
369 p[1]
for p
in sorted(sortlist, reverse=reverse)
373 numprepars = 1 + len(outputvals)
374 numlims = len(outputlims)
377 showbci = showbcin = 0
378 if "BCI" in outputlims:
381 outputlims.pop(outputlims.index(
"BCI"))
383 if "BCIN" in outputlims:
386 outputlims.pop(outputlims.index(
"BCIN"))
391 ltable =
latextable(ncolumns=(numprepars + numlims * nifos + showbci + showbcin))
392 ltable.set_caption(
"Limits on the gravitational wave amplitude for known pulsars")
396 ltable.addrow(underline=
True)
397 restable.adddata(
"", dataclass=
"bottomborder", header=
True, colspan=numprepars)
398 ltable.adddata(
"~", multicolumn=numprepars)
402 ncolspan += showbci + showbcin
407 datastyle=
"text-align:center; border-left:1px solid #000; border-bottom:1px solid #000",
410 ltable.adddata(ifo, multicolumn=ncolspan)
414 ltable.addrow(underline=
True)
415 restable.adddata(
"Pulsar", dataclass=
"bottomborder", header=
True)
416 ltable.adddata(
"Pulsar")
417 for prepar
in outputvals:
418 restable.adddata(paramhtmldict[prepar], dataclass=
"bottomborder", header=
True)
419 ltable.adddata(paramlatexdict[prepar])
422 dataclass =
"leftborder"
423 datastyle =
"border-bottom:1px solid #000"
424 for ol
in outputlims:
426 cr = list(resultsdata.values())[0][ifo][
"Upper limits"][
430 paramhtmldict[ol].format(cr),
435 ltable.adddata(paramlatexdict[ol].format(cr))
443 ltable.adddata(paramlatexdict[ol])
444 dataclass =
"bottomborder"
451 paramhtmldict[
"BCI"],
456 ltable.adddata(paramlatexdict[
"BCI"])
459 paramhtmldict[
"BCIN"],
464 ltable.adddata(paramlatexdict[
"BCIN"])
475 "SDLIM":
"spin-down limit",
476 "SDRAT":
"spin-down ratio",
477 "BSN":
"Signal vs Noise",
478 "BCI":
"Coherent vs Incoherent",
479 "BCIN":
"Coherent vs Incoherent or Noise",
487 for pname
in sortedlist:
491 pulsar = resultsdata[pname]
495 atag(os.path.join(pulsar[
"path"], pname +
".html"), linktext=pname).text
498 re.sub(
r"\-",
"\\\\textminus", pname)
501 for prepar
in outputvals:
506 if "SDLIM" in prepar:
508 pulsar[
"Pulsar data"][
"P1_I"] !=
None
511 pulsar[
"Pulsar data"][
"P1_I"] > 0.0
513 htmlsdtag =
htmltag(
"sup", tagtext=
"†").text
514 latexsdtag =
r"$\dagger$"
516 elif pulsar[
"Pulsar data"][
"ASSOC"] !=
None:
517 if "GC" in pulsar[
"Pulsar data"][
"ASSOC"]:
518 htmlsdtag =
htmltag(
"sup", tagtext=
"‡").text
519 latexsdtag =
r"$\ddagger$"
522 if prepar
in convdict:
523 pn = convdict[prepar]
526 if pn
in pulsar[
"Pulsar data"]:
527 preval = pulsar[
"Pulsar data"][pn]
532 disphtmlfunc = paramhtmldispfunc.__dict__[prepar]
533 displatexfunc = paramlatexdispfunc.__dict__[prepar]
540 restable.adddata(prevalhtml + htmlsdtag)
541 ltable.adddata(prevallatex + latexsdtag)
544 dataclass =
"leftborder"
546 for limpar
in outputlims:
547 if limpar
in convdict:
548 ln = convdict[limpar]
552 section =
"Upper limits"
556 section =
"Bayes factors"
558 if ln
in pulsar[ifo][section]:
559 limval = pulsar[ifo][section][ln]
566 limval = limval / np.log(10.0)
567 disphtmlfunc = paramhtmldispfunc.__dict__[limpar]
568 displatexfunc = paramlatexdispfunc.__dict__[limpar]
575 restable.adddata(limvalhtml, dataclass=dataclass)
577 ltable.adddata(limvallatex)
581 for bu, show
in [(
"BCI", showbci), (
"BCIN", showbcin)]:
584 if bn
in pulsar[ifo][
"Bayes factors"]:
585 bval = pulsar[ifo][
"Bayes factors"][bn]
590 bval = bval / np.log(10.0)
591 disphtmlfunc = paramhtmldispfunc.__dict__[bu]
592 displatexfunc = paramlatexdispfunc.__dict__[bu]
599 restable.adddata(bvalhtml, dataclass=dataclass)
601 ltable.adddata(bvallatex)
603 htmlinput[
"nsources"] =
"(%d/%d sources)" % (cursources, totalsources)
604 htmlinput[
"resultstable"] = restable.tabletext
607 if dagger
or ddagger:
608 htmlfootnotes =
htmltag(
"div", tagclass=
"footnotes")
610 htmlfootnotes +=
htmltag(
"sup", tagtext=
"†").text
611 htmlfootnotes +=
" The spin-down limit was calculated using a spin-down "
612 htmlfootnotes +=
atag(
613 "http://www.atnf.csiro.au/research/pulsar/psrcat/psrcat_help.html?type=normal&highlight=p1_i#p1_i",
614 linktext=
"corrected",
616 htmlfootnotes +=
" for proper motion effects.\n"
617 htmlfootnotes +=
"<br />\n"
618 ltable.set_postamble(
619 "$\\dagger$ The pulsar's spin-down is corrected for proper motion effects. \\\\\n"
622 htmlfootnotes +=
htmltag(
"sup", tagtext=
"‡").text
623 htmlfootnotes +=
" The spin-down limit was calculated using a characteristic spin-down age of 10<sup>9</sup> years.\n"
624 ltable.set_postamble(
626 +
"$\\ddagger$ The pulsar's spin-down is calculated using a characteristic spin-down age of $10^9$ years.\n"
628 htmlinput[
"footnotes"] = htmlfootnotes.text
630 htmlinput[
"footnotes"] =
""
633 cssfile = os.path.join(outpath,
"table.css")
634 fp = open(cssfile,
"w")
635 fp.write(results_table_css)
638 htmlinput[
"cssfile"] = os.path.basename(cssfile)
641 now = datetime.datetime.now()
644 htmlinput[
"footer"] =
"{} - {}<br><br>Command lines used:<br>{}<br>{}<br>".format(
645 __author__, now.strftime(
"%a %d %b %Y"),
" ".join(sys.argv), __version__
650 htmlfile = os.path.join(outpath,
"index.html")
651 fp = open(htmlfile,
"w")
652 fp.write(htmlpage.format(**htmlinput))
655 print(
"Error... there was a problem outputting the html page.", file=sys.stderr)
660 latexfile = os.path.join(outpath,
"resultstable.tex")
661 fp = open(latexfile,
"w")
662 fp.write(ltable.tabletext)
666 "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.