How To: Run SModelS as a python library¶

In [1]:
# Set up the path to SModelS installation folder
import sys; sys.path.append("."); import importlib; importlib.import_module("smodels_paths") if importlib.util.find_spec("smodels_paths") else None
In [2]:
from smodels.base import runtime
#Define your model (list of rEven and rOdd particles)
runtime.modelFile = 'smodels.share.models.mssm' 

from smodels.decomposition import decomposer
from smodels.base.physicsUnits import fb, GeV, TeV
from smodels.matching.theoryPrediction import theoryPredictionsFor
from smodels.experiment.databaseObj import Database
from smodels.tools import coverage
from smodels.base.smodelsLogging import setLogLevel
from smodels.share.models.mssm import BSMList                                                   
from smodels.share.models.SMparticles import SMList                                           
from smodels.base.model import Model
setLogLevel("info")

Main input:¶

In [3]:
model = Model(BSMparticles=BSMList, SMparticles=SMList)
 
slhafile = 'inputFiles/slha/lightEWinos.slha'
model.updateParticles ( inputFile = slhafile )
INFO in model.updateParticles() in 428: Loaded 62 BSM particles

Decompose the input model:¶

In [4]:
# Set main options for decomposition
sigmacut = 0.1 * fb
mingap = 5. * GeV
# Decompose model (use slhaDecomposer for SLHA input or lheDecomposer for LHE input)
toplist = decomposer.decompose(model, sigmacut, massCompress=True, invisibleCompress=True, minmassgap=mingap)

# Access basic information from decomposition, using the topology list and topology objects:
print( "\n Decomposition Results: " )
print( "\t  Total number of topologies: %i " %len(toplist) )
nel = len(toplist.getSMSList())
print( "\t  Total number of elements = %i " %nel )
 Decomposition Results: 
	  Total number of topologies: 39 
	  Total number of elements = 6055 

Load the Database of experimental results:¶

In [5]:
# Set the path to the database
database = Database("official")
# Load the experimental results to be used.
# In this case, all results are employed.
listOfExpRes = database.getExpResults( analysisIDs = [ "ATLAS-SUSY-2015-06" ])

# Print basic information about the results loaded.
# Count the number of loaded UL and EM experimental results:
nUL, nEM = 0, 0
for exp in listOfExpRes:
    # expType = exp.getValuesFor('dataType')[0]
    expType = exp.datasets[0].dataInfo.dataType
    if expType == 'upperLimit':
        nUL += 1
    elif  expType == 'efficiencyMap':
        nEM += 1
# print("\n Loaded Database with %i UL results and %i EM results " %(nUL,nEM))
INFO in databaseObj.loadBinaryFile() in 551: loading binary db file /home/lessa/.cache/smodels/official300.pcl format version 214
INFO in databaseObj.loadBinaryFile() in 558: Loaded database from /home/lessa/.cache/smodels/official300.pcl in 2.0 secs.

Match the decomposed simplified models with the experimental database of constraints:¶

In [6]:
# Compute the theory predictions for each experimental result and print them:
print("\n Theory Predictions and Constraints:")
rmax = 0.
bestResult = None
allPredictions = theoryPredictionsFor(database, toplist, combinedResults=False)
predsDict = {}
for tp in allPredictions:
    anaID = tp.analysisId()
    if anaID not in predsDict:
        predsDict[anaID] = []
    predsDict[anaID].append(tp)


for anaID,predictions in predsDict.items():
    if not predictions:
        continue  # Skip if there are no constraints from this result
    print('\n %s ' % anaID)
    for theoryPrediction in predictions:
        dataset = theoryPrediction.dataset
        datasetID = theoryPrediction.dataId()
        txnames = sorted([str(txname) for txname in theoryPrediction.txnames])
        print("------------------------")
        print("Dataset = ", datasetID)  # Analysis name
        print("TxNames = ", txnames)
        print("Theory Prediction = ", theoryPrediction.xsection)  # Signal cross section
        print("Condition Violation = ", theoryPrediction.conditions)  # Condition violation values

        # Get the corresponding upper limit:
        print("UL for theory prediction = ", theoryPrediction.upperLimit)

        # Compute the r-value
        r = theoryPrediction.getRValue()
        print("r = %1.3E" % r)
        # Compute likelihoods for EM-type results:
        if dataset.getType() == 'efficiencyMap':
            theoryPrediction.computeStatistics()
            print('L_BSM, L_SM, L_max = %1.3E, %1.3E, %1.3E' % (theoryPrediction.likelihood(),
                  theoryPrediction.lsm(), theoryPrediction.lmax()))
        if r > rmax:
            rmax = r
            bestResult = anaID

# Print the most constraining experimental result
print( "\nThe largest r-value (theory/upper limit ratio) is ",rmax )
if rmax > 1.:
    print( "(The input model is likely excluded by %s)" %bestResult )
else:
    print( "(The input model is not excluded by the simplified model results)" )
 Theory Predictions and Constraints:

 ATLAS-SUSY-2015-06 
------------------------
Dataset =  SR5j
TxNames =  ['T1']
Theory Prediction =  2.76E-06 [pb]
Condition Violation =  None
UL for theory prediction =  1.79E+00 [fb]
r = 1.544E-03
L_BSM, L_SM, L_max = 7.191E-03, 7.215E-03, 7.215E-03

The largest r-value (theory/upper limit ratio) is  0.0015440823356560514
(The input model is not excluded by the simplified model results)

Check for simplified models in the input model which were not tested by the Database:¶

In [7]:
#Find out missing topologies for sqrts=8*TeV:             
uncovered = coverage.Uncovered(toplist,sqrts=8.*TeV)
#First sort coverage groups by label                                          
groups = sorted(uncovered.groups[:], key = lambda g: g.label)
#Print uncovered cross-sections:                             
for group in groups:
    print("\nTotal cross-section for %s (fb): %10.3E\n" %(group.description,group.getTotalXSec()))

missingTopos = uncovered.getGroup('missing (prompt)')
#Print some of the missing topologies:
if missingTopos.finalStateSMS:
    print('Missing topologies (up to 3):' )
    for genEl in missingTopos.finalStateSMS[:3]:
        print('Element:', genEl)
        print('\tcross-section (fb):', genEl.missingX)
else:
    print("No missing topologies found\n")

missingDisplaced = uncovered.getGroup('missing (displaced)')
#Print elements with displaced decays:                              
if missingDisplaced.finalStateSMS:
    print('\nElements with displaced vertices (up to 2):' )
    for genEl in missingDisplaced.finalStateSMS[:2]:                                    
        print('Element:', genEl)                                                          
        print('\tcross-section (fb):', genEl.missingX)                                    
else:                                                                                     
    print("\nNo displaced decays")
Total cross-section for missing topologies (fb):  3.672E+03


Total cross-section for missing topologies with displaced decays (fb):  0.000E+00


Total cross-section for missing topologies with prompt decays (fb):  3.672E+03


Total cross-section for topologies outside the grid (fb):  1.530E+03

Missing topologies (up to 3):
Element: PV > (jet,jet,MET), (nu,l,MET)
	cross-section (fb): 644.0092445884675
Element: PV > (jet,jet,MET), (nu,ta,MET)
	cross-section (fb): 321.1539651599444
Element: PV > (jet,jet,MET), (b,b,MET)
	cross-section (fb): 274.0877573459048

No displaced decays
In [ ]: