diff --git a/analyses/pluginCMS/CMS_2017_I1605749.info b/analyses/pluginCMS/CMS_2017_I1605749.info --- a/analyses/pluginCMS/CMS_2017_I1605749.info +++ b/analyses/pluginCMS/CMS_2017_I1605749.info @@ -1,26 +1,26 @@ Name: CMS_2017_I1605749 Year: 2017 Summary: Measurements of jet charge with dijet events in pp collisions at $\sqrt{s}=8$ TeV Experiment: CMS Collider: LHC -SpiresID: 1605749 +InspireID: 1605749 Status: VALIDATED Authors: - - Debarati Roy + - Debarati Roy - Andreas Hinzmann - Nhan Viet Tran - Sunanda Banerjee References: - DOI:10.1007/JHEP10(2017)131 - arXiv:1706.05868 - CMS-SMP-15-003 RunInfo: pp QCD interactions at $\sqrt{s} = 8$ TeV. Data collected by CMS during the year 2012. Beams: [p+, p+] Energies: [8000] PtCuts: [400] NeedCrossSection: no Description: 'Jet charge is an estimator of the electric charge of a quark, antiquark, or gluon initiating a jet. It is based on the momentum-weighted sum of the electric charges of the jet constituents. Measurements of three charge observables of the leading jet in transverse momentum $p_\mathrm{T}$ are performed with dijet events. The analysis is carried out with data collected by the CMS experiment at the CERN LHC in proton-proton collisions at $\sqrt{s}=8\TeV$ corresponding to an integrated luminosity of 19.7 fb$^{-1}$. The results are presented in bins of the $p_\mathrm{T}$ of the leading jet.' diff --git a/doc/mk-analysis-html b/doc/mk-analysis-html --- a/doc/mk-analysis-html +++ b/doc/mk-analysis-html @@ -1,231 +1,231 @@ #! /usr/bin/env python ## Parse arguments import sys, os, re import optparse op = optparse.OptionParser() #op.add_option("--embed", dest="EMBED", action="store_true", default=False, help="do not generate , , and surrounging tags") opts, args = op.parse_args() ## Get output filename if not args: OUTFILE = "analyses.html" OUTDIR = "analyses" else: OUTFILE = args[0]+".html" OUTDIR = args[0] print("Using output file name '%s' and directory '%s'" % (OUTFILE, OUTDIR)) ## Add the rivet Python module build dir(s) to the Python module path, then import pybuild = os.path.abspath(os.path.join(os.getcwd(), "..", "pyext", "build")) pydirs = [os.path.join(pybuild, d) for d in os.listdir(pybuild) if re.match(r"lib\..*-.*-%d\.%d" % (sys.version_info[0], sys.version_info[1]), d)] sys.path = pydirs + sys.path import rivet ## Add info file locations from glob import glob dirpatt = os.path.join(os.getcwd(), "..", "analyses", "plugin*") for d in glob(dirpatt): #print(d) rivet.addAnalysisDataPath(os.path.abspath(d)) ## Get some strings of html ready. from rivet.util import htmlify foot = """\ """ head = '''\ Rivet analyses reference - +

Rivet analyses reference

''' ## Build analysis pages all_analyses = rivet.AnalysisLoader.analysisNames() ## Remove any existing directory with name OUTDIR, make new one. if os.path.exists(OUTDIR) and not os.path.realpath(OUTDIR) == os.getcwd(): import shutil shutil.rmtree(OUTDIR) try: os.makedirs(OUTDIR) except: print("Error: failed to make new directory '%s'" % OUTDIR) sys.exit(1) ## Find analysis source files ccpatt = os.path.join(os.getcwd(), "..", "analyses", "plugin*", "*.cc") ccfiles = glob(ccpatt) #print(ccfiles) summaries = {} pages = [] ## Use list(...) ctor for 2.3 compatibility for aname in sorted(list(all_analyses)): page = "" ana = rivet.AnalysisLoader.getAnalysis(aname) ## Summary and biblio links summaries[aname] = ana.summary() page += "

%s

\n" % (aname, aname) page += "%s
\n" % htmlify(ana.summary()) page += "Experiment: %s (%s)
\n" % (ana.experiment(), ana.collider()) if ana.inspireId(): spiresbase = "http://inspire-hep.net/record" page += "Inspire ID: %s
\n" % \ (spiresbase, ana.inspireId(), ana.inspireId()) elif ana.spiresId(): spiresbase = "http://inspire-hep.net/search?p=find+key" page += "Spires ID: %s
\n" % \ (spiresbase, ana.spiresId(), ana.spiresId()) page += "Status: %s
\n" % ana.status() ## Authors if ana.authors(): page += "Authors:\n" page += "
    \n" for a in ana.authors(): s = a import re if re.search(".* <.*@.*>", a): name = " ".join(a.split()[:-1]) email = a.split()[-1].replace("<", "").replace(">", "") #s = "%s" % (email, name) s = name page += "
  • %s
  • \n" % htmlify(s) page += "
\n" else: page += "No authors listed\n" ## References if ana.references(): page += "References:\n" page += "
    \n" for r in ana.references(): if r.startswith("arXiv:"): code = r.split()[0].replace("arXiv:", "") url = "http://arxiv.org/abs/" + code page += "
  • %s %s
  • \n" % ("arXiv:", htmlify(url), htmlify(code)) elif r.startswith("doi:"): code = r.replace("doi:", "") url = "http://dx.doi.org/" + code page += "
  • %s %s
  • \n" % ("DOI:", htmlify(url), htmlify(code)) else: page += "
  • %s
  • \n" % htmlify(r) page += "
\n" else: page += "No references listed
\n" ## Beams if ana.requiredBeams(): def pid_to_str(pid): if pid == 11: return "e-" elif pid == -11: return "e+" elif pid == 2212: return "p+" elif pid == -2212: return "p-" elif pid == 10000: return "*" else: return str(pid) beamstrs = [] for bp in ana.requiredBeams(): beamstrs.append(pid_to_str(bp[0]) + " " + pid_to_str(bp[1])) page += "Beams: %s
\n" % ", ".join(beamstrs) page += "Beam energies: " if ana.requiredEnergies(): page += "; ".join(["(%0.1f, %0.1f)" % (epair[0], epair[1]) for epair in ana.requiredEnergies()]) page += " GeV" else: page += "ANY" page += "
\n" ## Run info if ana.runInfo(): page += "Run details:\n" page += "
    \n" for l in ana.runInfo().split("\n*"): l = l.strip() if l.startswith("*"): l = l[1:].strip() page += "
  • %s
  • \n" % htmlify(l) page += "
\n" else: page += "
    No run details listed
\n" ## Description page += "\n

" + htmlify(ana.description(), para=True) + "

\n" ## Source code anaccfiles = [cc for cc in ccfiles if os.path.basename(cc).startswith(aname)] if anaccfiles: page += "Source code:\n" for cc in anaccfiles: page += "%s\n" % os.path.basename(cc) with open(cc, 'r') as f: src = f.read() try: import pygments from pygments.lexers import get_lexer_by_name from pygments.formatters import get_formatter_by_name lx = get_lexer_by_name("c++") fm = get_formatter_by_name("html", linenos=True, noclasses=True) page += pygments.highlight(src, lx, fm) except: page += "" + src.replace("\n", "
\n") + "
" # Write out HTML analysis file #print(aname) ANAFILE = os.path.join(OUTDIR, aname+'.html') f = open(ANAFILE, "wb") outstr = head + page + foot if type(u'') != str: outstr = unicode(outstr) f.write(outstr.encode(errors="ignore")) f.close() ## Write out HTML toc file(s) toc = "

Contents

\n" toc += "
    \n" for a in all_analyses: ## NB. initial links designed for linking from inside the OUTDIR toc += '
  • %s – %s
  • \n' % \ (a, OUTDIR, a, a, htmlify(summaries[a])) toc += "
\n" outstr = head + toc + foot ## Index file in dir f = open(os.path.join(OUTDIR, "index.html"), "wb") f.write(outstr.encode(errors="ignore")) f.close() ## External index file outstr = outstr.replace("../%s" % OUTDIR, OUTDIR) #< correct link depth if OUTFILE == "-": sys.stdout.write(outstr.encode(errors="ignore")) else: f = open(OUTFILE, "wb") f.write(outstr.encode(errors="ignore")) f.close() diff --git a/doc/mk-coverage-html b/doc/mk-coverage-html --- a/doc/mk-coverage-html +++ b/doc/mk-coverage-html @@ -1,351 +1,390 @@ #! /usr/bin/env python from __future__ import division, print_function """\ %prog [ ...] -TODO: get and write year of publication in table +TODO: + - do Rivet lookup in this script, not the JSON-maker + - get and write year of publication in table """ import argparse ap = argparse.ArgumentParser(usage=__doc__) ap.add_argument("JSONFILES", metavar="file", nargs="+", help="JSON Inspire xref file to read") ap.add_argument("-r", "--ranking", dest="RANKFILES", metavar="file", action="append", default=[], help="lists of Inspire IDs to exclude, suppress, and highlight") ap.add_argument("-R", "--reverse", dest="REVERSE", action="store_true", default=False, help="show list *reverse* ordered in Inspire ID") ap.add_argument("-s", "--only-searches", dest="ONLYSEARCHES", action="store_true", default=False, help="only show search analyses") ap.add_argument("-S", "--no-searches", dest="NOSEARCHES", action="store_true", default=False, help="exclude search analyses") ap.add_argument("-i", "--only-heavyion", dest="ONLYHEAVYION", action="store_true", default=False, help="only show heavy ion analyses") ap.add_argument("-I", "--no-heavyion", dest="NOHEAVYION", action="store_true", default=False, help="exclude heavy ion analyses") ap.add_argument("-o", "--outfile", dest="OUTFILE", default=None, help="output HTML filename") ap.add_argument("--basename", dest="BASENAME", default="rivet-coverage", help="the base name for output files [default=%(default)s]") ap.add_argument("--update-ranking", dest="UPDATERANK", action="store_true", default=False, help="update the per-experiment ranking files") ap.add_argument("-v", "--verbose", dest="VERBOSE", action="store_true", default=False, help="print debug info to the terminal") args = ap.parse_args() import datetime now = datetime.datetime.now() EXPTS = ["ALICE", "ATLAS", "CMS", "LHCb", "Other"] + +## Add the rivet Python module build dir(s) to the Python module path, then import +import os, sys, re +pybuild = os.path.abspath(os.path.join(os.getcwd(), "..", "pyext", "build")) +pydirs = [os.path.join(pybuild, d) for d in os.listdir(pybuild) + if re.match(r"lib\..*-.*-%d\.%d" % (sys.version_info[0], sys.version_info[1]), d)] +sys.path = pydirs + sys.path +import rivet + +## Add info file locations +from glob import glob +dirpatt = os.path.join(os.getcwd(), "..", "analyses", "plugin*") +for d in glob(dirpatt): + #print(d) + rivet.addAnalysisDataPath(os.path.abspath(d)) + +## Rivet analyses to cross-reference +ranas = {} +for aname in rivet.AnalysisLoader.analysisNames(): + ana = rivet.AnalysisLoader.getAnalysis(aname) + # TODO: all anas *should* have an Inspire ID... + try: + # print(aname, ":", ana.inspireId(), ":") + ranas.setdefault(int(ana.inspireId()), []).append(ana.name()) + except: + pass + + ## Read data from JSON files records = {} import json for jsonfile in args.JSONFILES: with open(jsonfile) as jf: recs = json.load(jf) if args.VERBOSE: print("Reading {} records from {}".format(len(recs), jsonfile)) records.update(recs) records = {int(k) : v for k, v in records.items()} -print("Read total of {} records".format(len(records))) +if args.VERBOSE: + print("Read total of {} records".format(len(records))) ## Read Inspire IDs from ranking files blacklist, greylist, hotlist = [], [], [] assigned = {} for rankfilestr in args.RANKFILES: for rankfile in rankfilestr.split(" "): with open(rankfile) as rf: if args.VERBOSE: print("Reading rankings from {}".format(rankfile)) for line in rf: line = line.strip() if not line or line.startswith("#"): continue tokens = line.split() ins = int(tokens[0]) code = tokens[1] if code == "X": blacklist.append(ins) elif code == "?": greylist.append(ins) elif code == "!": hotlist.append(ins) # Detect an optional assigned email address last = tokens[-1] if "@" in last: if last.startswith("<") and last.endswith(">"): last = last[1:-1] assigned[ins] = last ## Add rankings/tags to the record for ins, rec in records.items(): ## Sanitise title and experiment rec[0] = (rec[0] or "[NO TITLE]").replace("\n", " ") rec[1] = (rec[1] or "UNKNOWN").upper().split()[0].strip() ## Ranking code = "default" - if rec[6]: #< Rivet analyses + if ins in ranas: code = "rivet" elif ins in greylist: code = "grey" elif ins in blacklist: code = "black" elif ins in hotlist: code = "hot" ## Tags title = rec[0] or "" if "search" in title.lower(): code += " search" if "Pb" in title or "Xe" in title: code += " heavyion" rm = False rm |= args.ONLYSEARCHES and not "search" in code rm |= args.NOSEARCHES and "search" in code rm |= args.ONLYHEAVYION and not "heavyion" in code rm |= args.NOHEAVYION and "heavyion" in code if rm: del records[ins] else: rec.append(code) ## Group and count records by experiment (and update rank file if requested) ex_records = {} ex_ntots, ex_ndefaults, ex_nurgents, ex_nwanteds, ex_ntargets, ex_nrivets = {}, {}, {}, {}, {}, {} for ex in EXPTS: if ex != "Other": ex_records[ex] = {ins : rec for ins, rec in records.items() if rec[1].upper() == ex.upper()} else: namedexpts = [e.upper() for e in EXPTS[:-1]] ex_records[ex] = {ins : rec for ins, rec in records.items() if rec[1].upper() not in namedexpts} ex_ntots[ex] = len(ex_records[ex]) ex_nrivets[ex] = len([ins for ins, rec in ex_records[ex].items() if "rivet" in rec[-1]]) ex_ndefaults[ex] = len([ins for ins, rec in ex_records[ex].items() if "default" in rec[-1]]) ex_nurgents[ex] = len([ins for ins, rec in ex_records[ex].items() if "hot" in rec[-1]]) ex_nwanteds[ex] = ex_ndefaults[ex] + ex_nurgents[ex] ex_ntargets[ex] = ex_nwanteds[ex] + ex_nrivets[ex] if args.VERBOSE: print(ex, "#urgent/#wanted =", ex_nurgents[ex], "/", ex_nwanteds[ex]) if args.UPDATERANK: if args.ONLYSEARCHES or args.NOSEARCHES or args.ONLYHEAVYION or args.NOHEAVYION: print("Won't update rank lists while search/HI/experiment filtering is enabled") sys.exit(1) rfname = "{}-{}.rank".format(args.BASENAME, ex.lower()) print("Writing updated rank file to {}".format(rfname)) syms = { "default" : ".", "rivet" : ".", "grey" : "?", "black" : "X", "hot" : "!" } with open(rfname, "w") as rf: for ins, rec in sorted(ex_records[ex].items()): rankcode = rec[-1].split()[0] # line = u"{} {} {}\n".format(ins.encode("UTF-8"), syms[code], rec[3].encode("UTF-8")) line = u"{} {} {}".format(ins, syms[rankcode], rec[0]) # print(assigned.get(ins)) if ins in assigned: #print(ins, rec[0], assigned[ins]) line += " <{}>".format(assigned[ins]) line += "\n" rf.write(line.encode("UTF-8")) ntot = len(records) nrivet = len([ins for ins, rec in records.items() if "rivet" in rec[-1]]) ndefault = len([ins for ins, rec in records.items() if "default" in rec[-1]]) nurgent = len([ins for ins, rec in records.items() if "hot" in rec[-1]]) nwanted = ndefault + nurgent ntarget = nwanted + nrivet ## Register filter strings excls = [] if args.ONLYSEARCHES: excls.append("searches only") if args.NOSEARCHES: excls.append("no searches") if args.ONLYHEAVYION: excls.append("heavy ion only") if args.NOHEAVYION: excls.append("no heavy ion") ## Web page rendering import html OUT = html.HTML("html") title = "Rivet LHC analysis coverage" exclstr = " ({})".format(", ".join(excls)) if excls else "" title += exclstr head = OUT.head(newlines=True) head.meta(charset="utf-8") head.title(title) head.link("", rel="stylesheet", href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css") head.script("MathJax.Hub.Config({ tex2jax: {inlineMath: [['$','$']]} });", type="text/x-mathjax-config") head.script("", type="text/javascript", src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.4/MathJax.js?config=TeX-MML-AM_CHTML", async="async") head.script("", type="text/javascript", src="https://code.jquery.com/jquery-3.3.1.js", integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60=", crossorigin="anonymous") head.script("", type="text/javascript", src="https://code.jquery.com/ui/1.12.1/jquery-ui.js", integrity="sha256-T0Vest3yCU7pafRw9r+settMBX6JkKN06dqBnpQ8d30=", crossorigin="anonymous") head.script(""" $(document).ready( function(){ $("#blacktoggle").click( function(){ var b = $("#blacktoggle"); var t = b.text(); b.text(t.indexOf("Show") != -1 ? t.replace("Show", "Hide") : t.replace("Hide", "Show") ); $(".black").toggle(100); }); $("#greytoggle").click( function(){ var b = $("#greytoggle"); var t = b.text(); b.text(t.indexOf("Show") != -1 ? t.replace("Show", "Hide") : t.replace("Hide", "Show") ); $(".grey").toggle(100); }); $("#tabs").tabs(); }); """) style = head.style(newlines="True") style += "html { font-family: sans; font-size: large; color: #333; }" style += "body { padding: 2em; }" style += "table { margin: 2em 0 2em 0; border: 0; border-collapse: collapse; text-align: left; }" style += "table.list { border-top: 3px solid black; border-bottom: 3px solid black; }" style += "table.list thead { border-bottom: 1px solid #333; }" style += "table.key { border: 1px solid #333; margin: 0; }" style += "td { padding: 15px; }" style += "tr.ana { border-top: 1px solid #ccc; }" style += "tr.ana td { padding-bottom: 1em; padding-top: 1em; }" style += "a { color: #339; }" style += "button { margin: 1em; }" # style += ".row { margin: 1em 0 3em 0; }" # style += ".row:after { content: ''; display: table; clear: both; }" # style += ".col { float: left; width: 50%; }" style += "button { border: none; margin: 0 1em 1em 0; border-radius: 1ex; color: #333; background: #ddf; padding: 1ex; }" style += "button:hover { background: #cce; }" style += "button:active { color: white; }" style += "#tabs { border: 0; }" style += ".rivet { background: #cfc; }" style += ".hot { background: #fbb; }" style += ".default { background: #fee; }" style += ".grey { color: #666; background: #ddd; font-size: normal; display: none; }" style += ".grey a { color: #669; }" style += ".black { color: #eee; background: #333; display: none; }" style += ".black a { color: #99c; }" style += ".hot.assigned { background: repeating-linear-gradient(135deg, #fbb, #fbb 10px, #bd7 10px, #bd7 20px); }" style += ".default.assigned { background: repeating-linear-gradient(135deg, #fee, #fee 10px, #de9 10px, #de9 20px); }" style += ".grey.assigned { background: repeating-linear-gradient(135deg, #ddd, #ddd 10px, #dfd 10px, #dfd 20px); }" body = OUT.html.body(newlines=True) body.h1(title) body.p().b("Rivet analyses exist for {}/{} papers = {:.0f}%. {} priority analyses required.".format(nrivet, ntarget, 100*nrivet/ntarget, nurgent)) body.p("Total number of Inspire papers scanned = {}, at {}".format(ntot, now.strftime("%Y-%m-%d"))) body.p("Breakdown by identified experiment (in development):") t = body.table(klass="list") th = t.thead(newlines=True) r = th.tr(klass="thead") r.td().b("Key") for ex in EXPTS: r.td().b(ex) # tb = t.tbody(newlines=True) r = tb.tr(klass="default") r.td().b("Rivet wanted (total):") for ex in EXPTS: r.td("{}".format(ex_nwanteds[ex])) # r = tb.tr(klass="hot") r.td().b("Rivet REALLY wanted:") for ex in EXPTS: r.td("{}".format(ex_nurgents[ex])) r = tb.tr(klass="rivet") # r.td().b("Rivet provided:") for ex in EXPTS: # txt = "{}".format(ex_nrivets[ex]) # if ex_ntargets[ex]: # txt += " / {:d} = {:.0f}%".format(ex_ntargets[ex], 100*ex_nrivets[ex]/ex_ntargets[ex]) # r.td(txt) b = r.td().b("{}".format(ex_nrivets[ex])) if ex_ntargets[ex]: b.span("/{:d} = ".format(ex_ntargets[ex]), style="color: #777") b += "{:.0f}%".format(100*ex_nrivets[ex]/ex_ntargets[ex]) body.button("Show greylist", id="greytoggle") body.button("Show blacklist", id="blacktoggle") #body.input(klass="search", placeholder="Search") #body.button("Sort by name", klass="sort", data-sort="name") tabs = body.div(id="tabs") u = tabs.ul() for ex in EXPTS: u.li().a(ex, href="#{}expt".format(ex.lower())) for ex in EXPTS: d = tabs.div(id="{}expt".format(ex.lower())) t = d.table(klass="list").tbody(newlines=True) for i, (ins, rec) in enumerate(sorted(ex_records[ex].items(), reverse=args.REVERSE)): expt = rec[1] code = rec[-1] if ins in assigned: code += " assigned" if expt: code += " {}expt".format(expt.lower()) cell = t.tr(klass=code+" ana", newlines=True).td(newlines=False) + # Title summ = u"" summ += u"{}: {}".format(expt, rec[0]) - # summ += rec[0] - # if expt != "UNKNOWN": - # #summ += " " - # summ += " [{}]".format(expt) cell.b(summ) cell.br() - if len(rec) == 9: # Report numbers - nums = u", ".join(rec[7]) if rec[7] else u"" - cell.span(nums) - cell.br() + ## Inspire ID + cell.span("Inspire ID: {} ".format(ins)) + + ## Report numbers + if rec[7]: + cell.span(u" Report IDs: " + u", ".join(rec[7])) + cell.br() + cell.span("Links: ") + ## Inspire link cell.a("Inspire", href="http://inspirehep.net/record/{}".format(ins)) # Inspire cell += " " - if rec[2]: # DOI + ## DOI link + if rec[2]: cell.a("DOI/journal", href="http://dx.doi.org/{}".format(rec[2])) cell += " " - if rec[3]: # CDS + ## CDS link + if rec[3]: cell.a("CDS", href="https://cds.cern.ch/record/{}".format(rec[3])) cell += " " - if rec[4]: # arXiv + ## arXiv link + if rec[4]: cell.a("arXiv", href="https://arxiv.org/abs/{}".format(rec[4])) cell += " " - if rec[5]: # HepData + ## HepData link + if rec[5]: cell.a("HepData", href="https://hepdata.net/record/{}".format(rec[5])) cell += " " - if rec[6]: # Rivet - anas = u", ".join(rec[6]) if rec[6] else u"" - cell.a(anas, href="https://rivet.hepforge.org/analyses/{}.html".format(rec[6][0])) + ## Rivet links + if ins in ranas: + anas = u", ".join(ranas[ins]) + cell.a(anas, href="https://rivet.hepforge.org/analyses/{}.html".format(ranas[ins][0])) + ## In-progress/assignment if ins in assigned: cell.a("IN PROGRESS: assigned to {}".format(assigned[ins]), href="mailto:{}".format(assigned[ins])) ## Time-created footer body.p("Generated at {}".format(now.strftime("%c"))) body.p("Generated from JSON files extracted from Inspire ({} papers in total):".format(ntot)) body.p(", ".join(args.JSONFILES), style="font-family: monospace; font-size: smaller") ## Write out outfile = args.OUTFILE if not outfile: outfile = args.BASENAME exclparts = [e.replace(" ", "") for e in excls] if exclparts: outfile += "-" + "-".join(exclparts) if not outfile.endswith(".html"): outfile += ".html" print("Writing output to {} {}".format(outfile, exclstr)) with open(outfile, "wb") as hf: a = unicode(OUT) hf.write(a.encode("UTF-8"))