Source code for tools.printers.summaryPrinter

"""
.. module:: summaryPrinter
   :synopsis: Class for describing a summary printer in text format.

.. moduleauthor:: Andre Lessa <lessa.a.p@gmail.com>

"""

import os
from smodels.matching.theoryPrediction import TheoryPredictionList,\
         TheoryPrediction,TheoryPredictionsCombiner
from smodels.tools.ioObjects import OutputStatus
from smodels.tools.coverage import Uncovered
from smodels.base.physicsUnits import fb, TeV
from smodels.base.smodelsLogging import logger
from smodels.tools.printers.txtPrinter import TxTPrinter
import numpy as np
import unum
from typing import Optional

[docs]class SummaryPrinter(TxTPrinter): """ Printer class to handle the printing of one single summary output. It uses the facilities of the TxTPrinter. """ def __init__( self, output : str = 'stdout', filename : Optional[os.PathLike] = None, outputFormat : str = 'version3' ): """ :param output: one of: stdout, file """ TxTPrinter.__init__(self, output, filename, outputFormat) self.name = "summary" self.printingOrder = [ OutputStatus, TheoryPredictionList, TheoryPredictionsCombiner, TheoryPrediction, Uncovered] self.toPrint = [None]*len(self.printingOrder)
[docs] def setOutPutFile( self, filename : os.PathLike, overwrite : bool = True, silent : bool = False ): """ Set the basename for the text printer. The output filename will be filename.smodels. :param filename: Base filename :param overwrite: If True and the file already exists, it will be removed. :param silent: dont comment removing old files """ self.filename = filename + '.smodels' if overwrite and os.path.isfile(self.filename): if not silent: logger.warning("Removing old output file " + self.filename) os.remove(self.filename)
def _formatTheoryPredictionList(self, obj) -> str: """ Format data of the TheoryPredictionList object. :param obj: A TheoryPredictionList object to be printed. """ obj.sortTheoryPredictions() if hasattr(self, "expandedsummary") and not self.expandedsummary: theoPredictions = [obj._theoryPredictions[0]] else: theoPredictions = obj._theoryPredictions output = "" maxr = {"obs": -1., "exp": -1, "anaid": "?"} maxcoll = {"CMS": {"obs": -1., "exp": -1, "anaid": "?"}, "ATLAS": {"obs": -1., "exp": -1, "anaid": "?"}} for theoPred in obj._theoryPredictions: r = theoPred.getRValue(evaluationType=False) r_expected = theoPred.getRValue(evaluationType=self.getTypeOfExpected()) expResult = theoPred.expResult coll = "ATLAS" if "ATLAS" in expResult.globalInfo.id else "CMS" if (r_expected is not None) and (r_expected > maxcoll[coll]["exp"]): maxcoll[coll] = {"obs": r, "exp": r_expected, "anaid": expResult.globalInfo.id} if (r is not None) and (r > maxr["obs"]): maxr = {"obs": r, "exp": r_expected, "anaid": expResult.globalInfo.id} output += "#Analysis Sqrts Cond_Violation Theory_Value(fb) Exp_limit(fb) r r_expected" output += "\n\n" for theoPred in theoPredictions: expResult = theoPred.expResult ul = theoPred.getUpperLimit(evaluationType=False) uls = str(ul) if isinstance(ul, unum.Unum): uls = f"{ul.asNumber(fb):10.3E}" signalRegion = theoPred.dataset.getID() if signalRegion is None: signalRegion = '(UL)' value = theoPred.xsection r = theoPred.getRValue(evaluationType=False) r_expected = theoPred.getRValue(evaluationType=self.getTypeOfExpected()) if r is not None: rs = f"{r:10.3E}" else: rs = "NaN" # r = None means the calculation failed if r_expected is not None: rs_expected = f"{r_expected:10.3E}" else: rs_expected = "N/A" # r_exp could not be available output += "%19s " % (expResult.globalInfo.id) # ana # output += "%4s " % (expResult.globalInfo.sqrts/ TeV) # sqrts # sqrts output += f"{expResult.globalInfo.sqrts.asNumber(TeV):2.2E} " output += "%5s " % theoPred.getmaxCondition() # condition violation # theory cross section , expt upper limit output += f"{value.asNumber(fb):10.3E} {uls} " output += f"{rs} {rs_expected}" output += "\n" output += " Signal Region: "+signalRegion+"\n" txWeightsDict = theoPred.getTxNamesWeights(sort=True) txnameStr_list = list(dict.fromkeys([tx.txName for tx in txWeightsDict])) txnameStr = ', '.join(txnameStr_list) txnameStr = txnameStr.replace( "'", "").replace("[", "").replace("]", "") output += " Txnames: " + txnameStr + "\n" # Get TxNames final states: fStates = [] for txname in txWeightsDict: for sms in txname.smsMap: fs = sms.getFinalStateStr() if fs not in fStates: fStates.append(fs) max_length = 3 fStates_str = ', '.join(fStates[:max_length]) if len(fStates) > max_length: fStates_str += f',...({len(fStates)-max_length:d} more)' if self.outputFormat != 'version2': output += " Final States: " + fStates_str + "\n" nll = theoPred.nll ( ) if nll is not None: nllmin = theoPred.nll_min( ) nllsm = theoPred.nllsm( ) lvals = [nll, nllmin, nllsm] for i, lv in enumerate(lvals): if isinstance(lv, (float, np.floating)): lv = f"{lv:10.3E}" else: lv = str(lv) lvals[i] = lv nll, nllmin, nllsm = lvals[:] if nll == nllmin == nllsm == "None": output += " Likelihoods: nll, nll_min, nll_SM = N/A\n" else: output += f" Likelihoods: nll, nll_min, nll_SM = {nll}, {nllmin}, {nllsm}\n" if theoPred is not obj[-1]: output += 80 * "-" + "\n" output += "\n \n" output += 80 * "=" + "\n" output += f"The highest r value is = {maxr['obs']:.5f} from {maxr['anaid']}" if maxr["exp"] is not None and maxr["exp"] >= 0.0: output += f" (r_expected={maxr['exp']:.5f})" else: output += " (r_expected not available)" output += "\n" for coll, values in maxcoll.items(): if values["obs"] == None or values["obs"] < 0.0: continue output += "%s analysis with highest available r_expected: %s, r_expected=%.5f, r_obs=%.5f\n" % \ (coll, values["anaid"], values["exp"], values["obs"]) return output def _formatTheoryPrediction(self,obj) -> str: return self._formatTheoryPredictionsCombiner(obj) def _formatTheoryPredictionsCombiner(self, obj) -> str: """ Format data of the TheoryPredictionsCombiner object. :param obj: A TheoryPredictionsCombiner object to be printed. """ output = "===================================================== \n" # Get list of analyses used in combination: expIDs = obj.analysisId() # Get r-value: r = obj.getRValue() r_expected = obj.getRValue(evaluationType=self.getTypeOfExpected()) # Get likelihoods: nllsm = obj.nllsm( ) nll = obj.nll( ) nllmin = obj.nll_min( ) # Get sorted txnames txnames = [] for tx in obj.getTxNamesWeights(sort=True): if tx.txName not in txnames: txnames.append(tx.txName) output += f"Combined Analyses: {expIDs}\n" output += f"Txnames: {', '.join(txnames)}\n" output += f"Likelihoods: nll, nll_min, nll_SM = {nll:.3f}, {nllmin:.3f}, {nllsm:.3f}\n" if r is not None: output += f"combined r-value: {r:10.3E}\n" else: output += "combined r-value: NaN (failed to compute r-value)\n" if r_expected is not None: output += f"combined r-value (expected): {r_expected:10.3E}\n" else: output += "combined r-value (expected): NaN (failed to compute r-value)\n" output += "\n===================================================== \n" output += "\n" return output