Source code for tools.ioObjects

#!/usr/bin/env python3

"""
.. module:: ioObjects
   :synopsis: Definitions of input/output parameters which are read from parameter.in.
    
.. moduleauthor:: Ursula Laa <ursula.laa@lpsc.in2p3.fr>    
.. moduleauthor:: Suchita Kulkarni <suchita.kulkarni@gmail.com>
.. moduleauthor:: Andre Lessa <lessa.a.p@gmail.com>

"""

import os
import pyslha
from smodels.base import lheReader
from smodels.base.physicsUnits import GeV, fb
from smodels.base.model import Model
from smodels.base.exceptions import SModelSBaseError as SModelSError
from smodels.base.smodelsLogging import logger
from smodels.base import runtime
from smodels import installation
from smodels.share.models.SMparticles import SMList, SMparticleList

SMpdgs = SMparticleList.pdg


[docs]class OutputStatus(object): """ Object that holds all status information and has a predefined printout. """ def __init__( self, status, inputFile, parameters, databaseVersion): """ Initialize output. If one of the checks failed, exit. :parameter status: status of input file :parameter inputFile: input file name :parameter parameters: input parameters :parameter databaseVersion: database version (string) """ try: filename=os.path.join ( installation.installDirectory(), 'smodels/version' ) with open( filename, 'r') as versionFile: version = versionFile.readline() self.smodelsVersion = version.replace('\n','') except IOError: self.smodelsVersion = None self.inputfile = inputFile.replace("//","/") self.parameters = parameters self.filestatus = status[0] self.warnings = status[1] self.databaseVersion = databaseVersion self.statusStrings = {-4: "#database not found", -3: "#no topology passed cut on production cross section", -2: "#bad input file, did not run decomposition", -1: "#could not run the decomposition", 0: "#no matching experimental results", 1: "#decomposition was successful"} self.status = 0 if not self.databaseVersion: self.status = -4 if self.filestatus < 0: self.status = -2
[docs] def updateStatus(self, status): """ Update status. :parameter status: new status flag """ self.status = status
[docs] def updateSLHAStatus(self, status): """ Update SLHA status. :parameter status: new SLHA status flag """ self.slhastatus = status return
[docs] def addWarning(self, warning): """ Append warning to warnings. :parameter warning: warning to be appended """ self.warnings += warning return
[docs]class FileStatus(object): """ Object to run several checks on the input file. It holds an LheStatus (SlhaStatus) object if inputType = lhe (slha) """ def __init__(self): self.filestatus = None self.status = 0, "File not checked\n"
[docs] def checkFile(self, inputFile): """ Run checks on the input file. :parameter inputFile: path to input file """ inputType = runtime.filetype( inputFile ) if inputType == 'lhe': self.filestatus = LheStatus(inputFile) self.status = self.filestatus.status elif inputType == 'slha': self.filestatus = SlhaStatus(inputFile) self.status = self.filestatus.status else: self.filestatus = None self.status = -5, 'Unknown input type: %s' % inputType
[docs]class LheStatus(object): """ Object to check if input lhe file contains errors. :ivar filename: path to input LHE file """ def __init__(self, filename): self.filename = filename self.status = self.evaluateStatus()
[docs] def evaluateStatus(self): """ run status check """ if not os.path.exists(self.filename): # set status flag to -3, as in slha checks for missing input file return -3, "Inputfile %s not found" % self.filename lhe = lheReader.LheReader(self.filename) nevents = lhe.metainfo["nevents"] totxsec = lhe.metainfo["totalxsec"] sqrts = lhe.metainfo["sqrts"] if (not type(sqrts) == type(1 * GeV)) or (not sqrts.asNumber()): return -1, "Center-of-mass energy not found in the input LHE file %s" % self.filename elif not nevents: return -1, "No events found in the input LHE file %s" % self.filename elif (not type(totxsec) == type(1 * fb)) or (not totxsec.asNumber()): return -1, "Total cross section not found in the input LHE file %s" % self.filename return 1, "Input file ok"
[docs]class SlhaStatus(object): """ An instance of this class represents the status of an SLHA file. The output status is: = 0 : the file is not checked, = 1: the check is ok = -1: case of a physical problem, e.g. charged LSP, = -2: case of formal problems, e.g. no cross sections """ def __init__(self, filename, findMissingDecayBlocks=True, findIllegalDecays=False, checkXsec=True): """ :parameter filename: path to input SLHA file :parameter findMissingDecayBlocks: if True add a warning for missing decay blocks :parameter findIllegalDecays: if True check if all decays are kinematically allowed :parameter checkXsec: if True check if SLHA file contains cross sections :parameter findLonglived: if True find stable charged particles and displaced vertices """ self.filename = filename self.slha = self.read() from smodels.tools.particlesLoader import load BSMList = load() if not self.slha: self.status = -3, "Could not read input SLHA file" return try: # Temporarily disable logger to avoid duplicated # messages logger.disabled = True model = Model(BSMList,SMList) model.updateParticles(filename) logger.disabled = False self.model = model self.illegalDecays = self.findIllegalDecay(findIllegalDecays) self.xsec = self.hasXsec(checkXsec) self.decayBlocksStatus = self.findMissingDecayBlocks(findMissingDecayBlocks) self.status = self.evaluateStatus() except (SModelSError,TypeError,IOError,ValueError,AttributeError) as e: self.status = -4, "Error checking SLHA file: "+str(e)
[docs] def read(self): """ Get pyslha output object. """ try: ret = pyslha.readSLHAFile(self.filename) except (pyslha.ParseError,IOError): return None if not ret.blocks["MASS"]: return None return ret
[docs] def evaluateStatus(self): """ Get status summary from all performed checks. :returns: a status flag and a message for explanation """ if not self.slha: return -3, "Could not read input slha file" ret = 0 warning = None retMes = "#Warnings:\n" st , message = self.decayBlocksStatus # add only warning, no negative staus flag in case of missing decay blocks if st < 0: warning = True retMes += message + "\n" for st, message in [self.xsec]: if st < 0: ret = -2 retMes = retMes + "#" + message + ".\n" elif st == 1 and not ret == -2: ret = 1 for st, message in [self.illegalDecays]: if st < 0: ret = -1 retMes = retMes + "#" + message + "\n" elif st == 1 and ret >= 0: ret = 1 if ret == 0: return 0, "No checks performed" if ret == -1: return -1, "#ERROR: special signatures in this point.\n" + retMes if ret == -2: return -2, retMes if not warning: retMes = "Input file ok" return ret, retMes
[docs] def emptyDecay(self, pid): """ Check if any decay is missing for the particle with pid :parameter pid: PID number of particle to be checked :returns: True if the decay block is missing or if it is empty, None otherwise """ if not abs(pid) in self.slha.decays: return True # consider missing decay block as empty if not self.slha.decays[abs(pid)].decays: return True return None
[docs] def findMissingDecayBlocks(self, findMissingBlocks): """ For all non-SMpdgs particles listed in mass block, check if decay block is written :returns: status flag and message """ if not findMissingBlocks: return 0, "Did not check for missing decay blocks" st = 1 missing = [] pids = self.slha.blocks["MASS"].keys() for pid in pids: if pid in SMpdgs: continue if not pid in self.slha.decays: missing.append(pid) st = -1 if st == 1: msg = "No missing decay blocks" else: msg = "# Missing decay blocks for %s" % str(missing) return st, msg
[docs] def findIllegalDecay(self, findIllegal): """ Find decays for which the sum of daughter masses excels the mother mass :parameter findIllegal: True if check should be run :returns: status flag and message """ if not findIllegal: return 0, "Did not check for illegal decays" st = 1 badDecay = "Illegal decay for PIDs " for particle, block in self.slha.decays.items(): if particle in SMpdgs : continue if not particle in self.slha.blocks["MASS"].keys(): continue mMom = abs(self.slha.blocks["MASS"][particle]) for dcy in block.decays: mDau = 0. for ptc in dcy.ids: ptc = abs(ptc) if ptc in SMpdgs: smParticle = self.model.getParticlesWith(pdg=ptc) if not smParticle: raise SModelSError("Particle with PDG = %i could not be found." %ptc) elif len(smParticle) != 1: raise SModelSError("Multiple particles defined with PDG = %i in model" %ptc) else: smParticle = smParticle[0] mDau += smParticle.mass/GeV elif ptc in self.slha.blocks["MASS"].keys(): mDau += abs(self.slha.blocks["MASS"][ptc]) else: return -2, "Unknown PID %s in decay of %s" % (str(ptc), str(particle) + ". Add " + str(ptc) + " to smodels/particle.py") if mDau > mMom: st = -1 if not str(particle) in badDecay: badDecay += str(particle) + " " if st == 1: badDecay = "No illegal decay blocks" return st, badDecay
[docs] def hasXsec(self, checkXsec): """ Check if XSECTION table is present in the slha file. :parameter checkXsec: set True to run the check :returns: status flag, message """ if not checkXsec: return 0, "Did not check for missing XSECTION table" with open(self.filename) as f: for line in f: if "XSECTION" in line: return 1, "XSECTION table present" msg = "XSECTION table is missing. Please include the cross section information and try again.\n" msg += "\n\t For MSSM models, it is possible to compute the MSSM cross sections" msg += " using Pythia through the command:\n\n" msg += "\t ./smodelsTools.py xseccomputer -p -f " + self.filename + " \n\n" msg += "\t For more options and information run: ./smodelsTools.py xseccomputer -h\n" logger.error(msg) return -1, msg