class TxName(object):
    """
    Holds the information related to one txname in the Txname.txt
    file (constraint, condition,...) as well as the data.
    """
    def __init__(self, path, globalObj, infoObj):
        self.path = path
        self.globalInfo = globalObj
        self._infoObj = infoObj
        self.txnameData = None
        self.txnameDataExp = None  ## expected Data
        self._topologyList = TopologyList()

        logger.debug('Creating object based on txname file: %s' % self.path)
        #Open the info file and get the information:
        if not os.path.isfile(path):
            logger.error("Txname file %s not found" % path)
            raise SModelSError()
        txtFile = open(path, 'r')
        txdata = txtFile.read()
        txtFile.close()
        if not "txName" in txdata: raise TypeError
        if not 'upperLimits' in txdata and not 'efficiencyMap' in txdata:
            raise TypeError
        txfile = open(self.path)
        content = concatenateLines(txfile.readlines())
        txfile.close()

        #Get tags in info file:
        tags = [line.split(':', 1)[0].strip() for line in content]
        data = None
        expectedData = None
        dataType = None
        for i, tag in enumerate(tags):
            if not tag: continue
            line = content[i]
            value = line.split(':', 1)[1].strip()
            if tags.count(tag) == 1:
                if ';' in value: value = value.split(';')
                if tag == 'upperLimits' or tag == 'efficiencyMap':
                    data = value
                    dataType = tag
                elif tag == 'expectedUpperLimits':
                    expectedData = value
                    dataType = 'upperLimits'
                else:
                    self.addInfo(tag, value)
            else:
                logger.info("Ignoring unknown field %s found in file %s" \
                             % (tag, self.path))
                continue
        ident = self.globalInfo.id + ":" + dataType[0] + ":" + str(
            self._infoObj.dataId)
        ident += ":" + self.txName
        self.txnameData = TxNameData(data, dataType, ident)
        if expectedData:
            self.txnameDataExp = TxNameData(expectedData, dataType, ident)

        #Builds up a list of elements appearing in constraints:
        elements = []
        if hasattr(self, 'constraint'):
            elements += [Element(el) for el in elementsInStr(self.constraint)]
        if hasattr(self, 'condition') and self.condition:
            conds = self.condition
            if not isinstance(conds, list): conds = [conds]
            for cond in conds:
                for el in elementsInStr(cond):
                    newEl = Element(el)
                    if not newEl in elements: elements.append(newEl)

        # Builds up TopologyList with all the elements appearing in constraints
        # and conditions:
        for el in elements:
            el.sortBranches()
            self._topologyList.addElement(el)

    def __str__(self):
        return self.txName

    def __lt__(self, other):
        """ sort by txName """
        return self.txName < other.txName

    def getValueFor(self, massarray, expected=False):
        """ 
        Access txnameData and txnameDataExp to get value for 
        massarray.

        :param massarray: mass array values (with units), i.e.
                          [[100*GeV,10*GeV],[100*GeV,10*GeV]]
        :param expected: query self.txnameDataExp
        """
        if not expected:
            return self.txnameData.getValueFor(massarray)
        else:
            if not self.txnameDataExp:
                return None
            else:
                return self.txnameDataExp.getValueFor(massarray)

    def addInfo(self, tag, value):
        """
        Adds the info field labeled by tag with value value to the object.
        
        :param tag: information label (string)
        :param value: value for the field in string format
        """

        if tag == 'constraint' or tag == 'condition':
            if isinstance(value, list):
                value = [val.replace("'", "") for val in value]
            else:
                value = value.replace("'", "")

        try:
            setattr(self, tag,
                    eval(value, {
                        'fb': fb,
                        'pb': pb,
                        'GeV': GeV,
                        'TeV': TeV
                    }))
        except SyntaxError:
            setattr(self, tag, value)
        except NameError:
            setattr(self, tag, value)
        except TypeError:
            setattr(self, tag, value)

    def getInfo(self, infoLabel):
        """
        Returns the value of info field.
        
        :param infoLabel: label of the info field (string). It must be an attribute of
                          the TxNameInfo object
        """

        if hasattr(self, infoLabel): return getattr(self, infoLabel)
        else: return False

    def hasElementAs(self, element):
        """
        Verify if the conditions or constraint in Txname contains the element.
        Check both branch orderings.
        
        :param element: Element object
        :return: A copy of the element on the correct branch ordering appearing
                in the Txname constraint or condition.
        """

        for el in self._topologyList.getElements():
            if element.particlesMatch(el, branchOrder=True):
                return element.copy()
            else:
                elementB = element.switchBranches()
                if elementB.particlesMatch(el, branchOrder=True):
                    return elementB
        return False

    def getEfficiencyFor(self, mass):
        """
        For upper limit results, checks if the input mass falls inside the
        upper limit grid.  If it does, returns efficiency = 1, else returns
        efficiency = 0.  For efficiency map results, checks if the mass falls
        inside the efficiency map grid.  If it does, returns the corresponding
        efficiency value, else returns efficiency = 0.

        :param element: Element object
        :return: efficiency (float)
        """

        #Check if the element appears in Txname:
        val = self.txnameData.getValueFor(mass)
        if type(val) == type(fb):
            return 1.  #The element has an UL, return 1
        elif val is None or math.isnan(val):
            return 0.  #The element mass is outside the data grid
        elif type(val) == type(1.):
            return val  #The element has an eff
        else:
            logger.error("Unknown txnameData value: %s" % (str(type(val))))
            raise SModelSError()
    def __init__(self, path, globalObj, infoObj):
        self.path = path
        self.globalInfo = globalObj
        self._infoObj = infoObj
        self.txnameData = None
        self.txnameDataExp = None  ## expected Data
        self._topologyList = TopologyList()

        logger.debug('Creating object based on txname file: %s' % self.path)
        #Open the info file and get the information:
        if not os.path.isfile(path):
            logger.error("Txname file %s not found" % path)
            raise SModelSError()
        txtFile = open(path, 'r')
        txdata = txtFile.read()
        txtFile.close()
        if not "txName" in txdata: raise TypeError
        if not 'upperLimits' in txdata and not 'efficiencyMap' in txdata:
            raise TypeError
        txfile = open(self.path)
        content = concatenateLines(txfile.readlines())
        txfile.close()

        #Get tags in info file:
        tags = [line.split(':', 1)[0].strip() for line in content]
        data = None
        expectedData = None
        dataType = None
        for i, tag in enumerate(tags):
            if not tag: continue
            line = content[i]
            value = line.split(':', 1)[1].strip()
            if tags.count(tag) == 1:
                if ';' in value: value = value.split(';')
                if tag == 'upperLimits' or tag == 'efficiencyMap':
                    data = value
                    dataType = tag
                elif tag == 'expectedUpperLimits':
                    expectedData = value
                    dataType = 'upperLimits'
                else:
                    self.addInfo(tag, value)
            else:
                logger.info("Ignoring unknown field %s found in file %s" \
                             % (tag, self.path))
                continue
        ident = self.globalInfo.id + ":" + dataType[0] + ":" + str(
            self._infoObj.dataId)
        ident += ":" + self.txName
        self.txnameData = TxNameData(data, dataType, ident)
        if expectedData:
            self.txnameDataExp = TxNameData(expectedData, dataType, ident)

        #Builds up a list of elements appearing in constraints:
        elements = []
        if hasattr(self, 'constraint'):
            elements += [Element(el) for el in elementsInStr(self.constraint)]
        if hasattr(self, 'condition') and self.condition:
            conds = self.condition
            if not isinstance(conds, list): conds = [conds]
            for cond in conds:
                for el in elementsInStr(cond):
                    newEl = Element(el)
                    if not newEl in elements: elements.append(newEl)

        # Builds up TopologyList with all the elements appearing in constraints
        # and conditions:
        for el in elements:
            el.sortBranches()
            self._topologyList.addElement(el)
Beispiel #3
0
    def testUncovered(self):

        topolist = TopologyList()

        # prompt
        b1 = Branch()
        b1.evenParticles = [[b,t]]
        b1.oddParticles = [st1,n1]
        b1.setInfo()
        el1 = Element()
        el1.branches=[b1,b1]

        # long-lived
        b3 = Branch()
        b3.evenParticles = []
        b3.oddParticles = [gluino]
        b4 = Branch()
        b4.evenParticles = [[b,t]]
        b4.oddParticles = [st1,n1]
        b3.setInfo()
        b4.setInfo()
        el2 = Element()
        el2.branches=[b3,b4]

        # prompt and displaced
        b5 = Branch()
        b5.evenParticles = [[t],[b,t]]
        b5.oddParticles = [st2,st1,n1]
        b6 = Branch()
        b6.evenParticles = [[b,t]]
        b6.oddParticles = [st1,n1]
        b5.setInfo()
        b6.setInfo()
        el3 = Element()
        el3.branches=[b5,b6]

        w1 = XSectionList()
        w1.xSections.append(XSection())
        w1.xSections[0].info = XSectionInfo()
        w1.xSections[0].info.sqrts = 8.*TeV
        w1.xSections[0].info.label = '8 TeV'
        w1.xSections[0].info.order = 0
        w1.xSections[0].value = 10.*fb
        el1.weight = w1
        el2.weight = w1
        el3.weight = w1

        topolist.addElement(el1)
        topolist.addElement(el2)
        topolist.addElement(el3)
        topolist._setElementIds()
        uncovered = Uncovered(topolist,groupFilters=filters,groupFactors=factors)
        longLived = uncovered.getGroup('missing non-MET (prompt)')

        MET = uncovered.getGroup('missing MET (prompt)')
        displaced = uncovered.getGroup('missing (displaced)')

        self.assertEqual(len(longLived.generalElements), 1)
        self.assertEqual(len(displaced.generalElements), 1)
        self.assertEqual(len(MET.generalElements), 2)

        self.assertAlmostEqual(longLived.generalElements[0].missingX, 10.)
        self.assertAlmostEqual(displaced.generalElements[0].missingX, 9.96109334317542,places=4)
        self.assertAlmostEqual(MET.generalElements[0].missingX, 10.)
        self.assertAlmostEqual(MET.generalElements[1].missingX, 0.03890665682,places=4)
Beispiel #4
0
    def testTopologyList(self):

        top1 = Topology(elements=[el1.copy()])
        top2 = Topology(elements=[el2.copy()])
        topL1 = TopologyList(topologies=[top1])
        topL2 = TopologyList(topologies=[top2])

        self.assertEqual(len(topL1) == len(topL2) == 1, True)
        self.assertEqual(top1 < top2, False)  #Bigger by number of vertices

        topL = TopologyList()
        topL.addList(topL1)
        topL.add(top2)
        self.assertEqual(len(topL) == 2, True)
        self.assertEqual(
            topL.describe() == "TopologyList:\n[2][2]\n[1,2][2]\n", True)
        topL.addElement(el1B.copy())
        self.assertEqual(topL.getTotalWeight()[0].value == 34. * fb, True)
Beispiel #5
0
    def testUncoveredTree(self):

        p1 = Particle(Z2parity=-1, label='p1', pdg=10001, mass=100.*GeV,
              eCharge=0., colordim=1, totalwidth=0*GeV)
        p2 = Particle(Z2parity=-1, label='p2', pdg=10002, mass=200.*GeV,
              eCharge=0., colordim=1, totalwidth=1e-15*GeV)
        xsecA = XSection()
        xsecA.value = 10.*fb
        xsecA.info.sqrts = 13.*TeV
        xsecA.info.label = 'wA'
        xsecA.info.order = 0
        xsecB = XSection()
        xsecB.value = 5.*fb
        xsecB.info.sqrts = 13.*TeV
        xsecB.info.label = 'wb'
        xsecB.info.order = 0

        #Element family-tree: A0->A1+B1, A1->A2
        #Mother A
        elA = Element()
        elA.label = 'A0'
        elA.testedBy = ['prompt','displaced']
        elA.coveredBy = ['prompt','displaced']
        elA.weight.add(xsecA)
        elA.motherElements = [elA]

        #Daughters:
        elA1 = Element()
        elA1.label = 'A1'
        elA1.testedBy = []
        elA1.coveredBy = []
        elA1.weight.add(xsecA)
        elA1.motherElements = [elA1,elA]
        elB1 = Element()
        elB1.label = 'B1'
        elB1.testedBy = []
        elB1.coveredBy = []
        elB1.weight.add(xsecA)
        elB1.motherElements = [elB1,elA]
        elA2 = Element()
        elA2.label = 'A2'
        elA2.testedBy = []
        elA2.coveredBy = []
        elA2.weight.add(xsecA)
        elA2.motherElements = [elA2,elA1]

        #Element family-tree: a0->a1+b1
        #Mother B
        ela = Element()
        ela.label = 'a0'
        ela.testedBy = []
        ela.coveredBy = []
        ela.weight.add(xsecB)
        ela.motherElements = [ela]
        #Daughters:
        ela1 = Element()
        ela1.label = 'a1'
        ela1.testedBy = []
        ela1.coveredBy = []
        ela1.weight.add(xsecB)
        ela1.motherElements = [ela1,ela]
        elb1 = Element()
        elb1.label = 'b1'
        elb1.testedBy = []
        elb1.coveredBy = []
        elb1.weight.add(xsecB)
        elb1.motherElements = [elb1,ela]

        #Merged element = (A2+b1)
        elCombined = Element()
        xsec = XSection()
        xsec.value = 15.*fb
        xsec.info.sqrts = 13.*TeV
        xsec.info.label = 'wA+wB'
        xsec.info.order = 0
        elCombined.label = 'A2+b1'
        elCombined.testedBy = []
        elCombined.coveredBy = []
        elCombined.weight.add(xsec)
        elCombined.motherElements = [elCombined,elA2,elb1]

        topoList = TopologyList()
        topoList.topos.append(Topology())
        elList = [elA,elA1,elA2,elB1,ela,elb1,ela1,elCombined]
        #Set odd particles (important for sorting the elements)
        for el in elList:
            for branch in el.branches:
                branch.oddParticles = [p1]
        elB1.branches[0].oddParticles = [p2,p1]
        ela1.branches[1].oddParticles = [p2,p1]
        elb1.branches[1].oddParticles = [p2,p1]
        ela.branches[0].oddParticles = [p2,p2,p1]

        #make sure the ordering in elList is not important:
        random.shuffle(elList)
        topoList.topos[0].elementList = elList[:]
        topoList._setElementIds()

        #Test if the family tree is being retrieved correctly and in the correct ordering (mother before grandmother,...):
        elListAncestors = {'A0' : [], 'A1' : ['A0'], 'A2' : ['A1','A0'], 'B1' : ['A0'],'A2+b1' : ['A2','b1','A1','a0','A0'],
                           'b1' : ['a0'], 'a1' : ['a0'] , 'a0' : []}
        for el in elList:
            ancestors = [mom.label for mom in el.getAncestors()]
            self.assertEqual(ancestors,elListAncestors[el.label])
        # A2+b1--> b1 is not tested, A2 is tested because its grandmother is tested
        missingTopos = Uncovered(topoList).getGroup('missing (all)')
        self.assertEqual(len(missingTopos.generalElements),1) #Only elCombined should appear (it is smaller than a1)
        self.assertAlmostEqual(missingTopos.generalElements[0].missingX,5.) #Only the fraction of the cross-section from elB is not missing
        self.assertEqual(len(missingTopos.generalElements[0]._contributingElements),1) #Only elCombined should appear
        self.assertTrue(missingTopos.generalElements[0]._contributingElements[0] is elCombined)
Beispiel #6
0
    def __init__(self, path, globalObj, infoObj):
        self.path = path
        self.globalInfo = globalObj
        self._infoObj = infoObj
        self.txnameData = None
        self.txnameDataExp = None ## expected Data
        self._topologyList = TopologyList()

        logger.debug('Creating object based on txname file: %s' %self.path)
        #Open the info file and get the information:
        if not os.path.isfile(path):
            logger.error("Txname file %s not found" % path)
            raise SModelSError()
        txtFile = open(path,'r')
        txdata = txtFile.read()
        txtFile.close()
        if not "txName" in txdata: raise TypeError
        if not 'upperLimits' in txdata and not 'efficiencyMap' in txdata:
            raise TypeError
        content = concatenateLines(txdata.split("\n"))

        #Get tags in info file:
        tags = [line.split(':', 1)[0].strip() for line in content]
        data = None
        expectedData = None
        dataType = None
        for i,tag in enumerate(tags):
            if not tag: continue
            line = content[i]
            value = line.split(':',1)[1].strip()
            if tags.count(tag) != 1:
                logger.info("Duplicated field %s found in file %s" \
                             % (tag, self.path))
            if ';' in value: value = value.split(';')
            if tag == 'upperLimits' or tag == 'efficiencyMap':
                data = value
                dataType = tag
            elif tag == 'expectedUpperLimits':
                expectedData = value
                dataType = 'upperLimits'
            else:
                self.addInfo(tag,value)

        ident = self.globalInfo.id+":"+dataType[0]+":"+ str(self._infoObj.dataId)
        ident += ":" + self.txName
        self.txnameData = TxNameData(data, dataType, ident )
        if expectedData:
            self.txnameDataExp = TxNameData( expectedData, dataType, ident )

        #Builds up a list of elements appearing in constraints:
        if hasattr(self,'finalState'):
            finalState = self.finalState
        else:
            finalState = ["MET","MET"]        
        elements = []
        if hasattr(self,'constraint'):
            elements += [Element(el,finalState) for el in elementsInStr(str(self.constraint))]
        if hasattr(self,'condition') and self.condition:
            conds = self.condition
            if not isinstance(conds,list): conds = [conds]
            for cond in conds:
                for el in elementsInStr(str(cond)):
                    newEl = Element(el,finalState)
                    if not newEl in elements: elements.append(newEl)

        # Builds up TopologyList with all the elements appearing in constraints
        # and conditions:
        for el in elements:
            self._topologyList.addElement(el)
Beispiel #7
0
class TxName(object):
    """
    Holds the information related to one txname in the Txname.txt
    file (constraint, condition,...) as well as the data.
    """

    def __init__(self, path, globalObj, infoObj):
        self.path = path
        self.globalInfo = globalObj
        self._infoObj = infoObj
        self.txnameData = None
        self.txnameDataExp = None ## expected Data
        self._topologyList = TopologyList()

        logger.debug('Creating object based on txname file: %s' %self.path)
        #Open the info file and get the information:
        if not os.path.isfile(path):
            logger.error("Txname file %s not found" % path)
            raise SModelSError()
        txtFile = open(path,'r')
        txdata = txtFile.read()
        txtFile.close()
        if not "txName" in txdata: raise TypeError
        if not 'upperLimits' in txdata and not 'efficiencyMap' in txdata:
            raise TypeError
        content = concatenateLines(txdata.split("\n"))

        #Get tags in info file:
        tags = [line.split(':', 1)[0].strip() for line in content]
        data = None
        expectedData = None
        dataType = None
        for i,tag in enumerate(tags):
            if not tag: continue
            line = content[i]
            value = line.split(':',1)[1].strip()
            if tags.count(tag) != 1:
                logger.info("Duplicated field %s found in file %s" \
                             % (tag, self.path))
            if ';' in value: value = value.split(';')
            if tag == 'upperLimits' or tag == 'efficiencyMap':
                data = value
                dataType = tag
            elif tag == 'expectedUpperLimits':
                expectedData = value
                dataType = 'upperLimits'
            else:
                self.addInfo(tag,value)

        ident = self.globalInfo.id+":"+dataType[0]+":"+ str(self._infoObj.dataId)
        ident += ":" + self.txName
        self.txnameData = TxNameData(data, dataType, ident )
        if expectedData:
            self.txnameDataExp = TxNameData( expectedData, dataType, ident )

        #Builds up a list of elements appearing in constraints:
        if hasattr(self,'finalState'):
            finalState = self.finalState
        else:
            finalState = ["MET","MET"]        
        elements = []
        if hasattr(self,'constraint'):
            elements += [Element(el,finalState) for el in elementsInStr(str(self.constraint))]
        if hasattr(self,'condition') and self.condition:
            conds = self.condition
            if not isinstance(conds,list): conds = [conds]
            for cond in conds:
                for el in elementsInStr(str(cond)):
                    newEl = Element(el,finalState)
                    if not newEl in elements: elements.append(newEl)

        # Builds up TopologyList with all the elements appearing in constraints
        # and conditions:
        for el in elements:
            self._topologyList.addElement(el)

    def hasOnlyZeroes ( self ):
        ozs = self.txnameData.onlyZeroValues()
        if self.txnameDataExp:
            e_ozs = self.txnameDataExp.onlyZeroValues()
            if ozs and e_ozs:
                return True
            if (ozs and not e_ozs) or (e_ozs and not ozs):
                logger.warning ( "%s is weird. One of the (expected, observed) results is zeroes-only, the other one isnt." )
                return False
        return ozs


    def __str__(self):
        return self.txName

    def __lt__ ( self, other ):
        """ sort by txName """
        return self.txName < other.txName

    def getValueFor(self,massarray,expected=False ):
        """ 
        Access txnameData and txnameDataExp to get value for 
        massarray.

        :param massarray: mass array values (with units), i.e.
                          [[100*GeV,10*GeV],[100*GeV,10*GeV]]
        :param expected: query self.txnameDataExp
        """
        if not expected:
            return self.txnameData.getValueFor( massarray )
        else:
            if not self.txnameDataExp:
                return None
            else:
                return self.txnameDataExp.getValueFor( massarray )


    def addInfo(self,tag,value):
        """
        Adds the info field labeled by tag with value value to the object.
        
        :param tag: information label (string)
        :param value: value for the field in string format
        """

        if tag == 'constraint' or tag == 'condition':
            if isinstance(value,list):
                value = [val.replace("'","") for val in value]
            else:
                value = value.replace("'","")

        if tag == 'constraint' or tag == 'condition':
            if isinstance(value,list):
                value = [val.replace("'","") for val in value]
            else:
                value = value.replace("'","")
            setattr(self,tag,value) #Make sure constraints/conditions are not evaluated
        else:
            try:
                setattr(self,tag,eval(value, unitsDict))
            except SyntaxError:
                setattr(self,tag,value)
            except NameError:
                setattr(self,tag,value)
            except TypeError:
                setattr(self,tag,value)


    def getInfo(self, infoLabel):
        """
        Returns the value of info field.
        
        :param infoLabel: label of the info field (string). It must be an attribute of
                          the TxNameInfo object
        """

        if hasattr(self,infoLabel): return getattr(self,infoLabel)
        else: return False

    def hasElementAs(self,element):
        """
        Verify if the conditions or constraint in Txname contains the element.
        Check both branch orderings.
        
        :param element: Element object
        :return: A copy of the element on the correct branch ordering appearing
                in the Txname constraint or condition.
        """

        #Stores all orderings of elements which matches the txname
        matches = []
        for el in self._topologyList.getElements():
            if element.particlesMatch(el,branchOrder=True):
                matches.append(element.copy())
            else:
                elementB = element.switchBranches()
                if elementB.particlesMatch(el,branchOrder=True):
                    matches.append(elementB.copy())
        
        #No elements matched:
        if not matches:
            return False
        else: #If more than one element ordering matches, return the one with largest mass (relevant for clustering)
            matches = sorted(matches, key = lambda el: el.getMasses(),reverse=True)
            return matches[0]

    def hasLikelihood ( self ):
        """ can I construct a likelihood for this map? 
        True for all efficiency maps, and for upper limits maps
        with expected Values. """
        if self._infoObj.dataType == "efficiencyMap":
            return True
        if self.txnameDataExp != None:
            return True
        return False

    def getEfficiencyFor(self,mass):
        """
        For upper limit results, checks if the input mass falls inside the
        upper limit grid.  If it does, returns efficiency = 1, else returns
        efficiency = 0.  For efficiency map results, checks if the mass falls
        inside the efficiency map grid.  If it does, returns the corresponding
        efficiency value, else returns efficiency = 0.

        :param element: Element object
        :return: efficiency (float)
        """

        #Check if the element appears in Txname:
        val = self.txnameData.getValueFor(mass)
        if isinstance(val,unum.Unum):
            return 1.  #The element has an UL, return 1
        elif val is None or math.isnan(val):
            return 0.  #The element mass is outside the data grid
        elif isinstance(val,float):
            return val  #The element has an eff
        else:
            logger.error("Unknown txnameData value: %s" % (str(type(val))))
            raise SModelSError()
Beispiel #8
0
    def __init__(self, path, globalObj, infoObj, databaseParticles):
        self.path = path
        self.globalInfo = globalObj
        self._infoObj = infoObj
        self.txnameData = None
        self.txnameDataExp = None  ## expected Data
        self._topologyList = TopologyList()
        self.finalState = ['MET', 'MET']  #default final state
        self.intermediateState = None  #default intermediate state

        logger.debug('Creating object based on txname file: %s' % self.path)
        #Open the info file and get the information:
        if not os.path.isfile(path):
            logger.error("Txname file %s not found" % path)
            raise SModelSError()
        txtFile = open(path, 'r')
        txdata = txtFile.read()
        txtFile.close()
        if not "txName" in txdata: raise TypeError
        if not 'upperLimits' in txdata and not 'efficiencyMap' in txdata:
            raise TypeError
        content = concatenateLines(txdata.split("\n"))

        #Get tags in info file:
        tags = [line.split(':', 1)[0].strip() for line in content]
        data = None
        expectedData = None
        dataType = None
        for i, tag in enumerate(tags):
            if not tag: continue
            line = content[i]
            value = line.split(':', 1)[1].strip()
            if tags.count(tag) != 1:
                logger.info("Duplicated field %s found in file %s" \
                             % (tag, self.path))
            if ';' in value: value = value.split(';')
            if tag == 'upperLimits':
                data = value
                dataType = 'upperLimit'
            elif tag == 'expectedUpperLimits':
                expectedData = value
                dataType = 'upperLimit'
            elif tag == 'efficiencyMap':
                data = value
                dataType = 'efficiencyMap'
            else:
                self.addInfo(tag, value)

        ident = self.globalInfo.id + ":" + dataType[0] + ":" + str(
            self._infoObj.dataId)
        ident += ":" + self.txName

        #Get detector size (if not found in self, look for it in datasetInfo or globalInfo).
        #If not defined anywhere, set it to None and default values will be used for reweighting.
        self.Leff_inner = self.fetchAttribute('Leff_inner', fillvalue=None)
        self.Leff_outer = self.fetchAttribute('Leff_outer', fillvalue=None)

        self.txnameData = TxNameData(data,
                                     dataType,
                                     ident,
                                     Leff_inner=self.Leff_inner,
                                     Leff_outer=self.Leff_outer)
        if expectedData:
            self.txnameDataExp = TxNameData(expectedData,
                                            dataType,
                                            ident,
                                            Leff_inner=self.Leff_inner,
                                            Leff_outer=self.Leff_outer)

        #Builds up a list of elements appearing in constraints:
        elements = []
        if not databaseParticles:
            raise SModelSError(
                "Database particles is empty. Can not create TxName object.")
        if hasattr(self, 'constraint'):
            elements += [
                Element(el, self.finalState, self.intermediateState,
                        databaseParticles)
                for el in elementsInStr(str(self.constraint))
            ]

        if any((elA == elB and not elA is elB) for elA in elements
               for elB in elements):
            txt = "Duplicate elements in constraint: %s in %s" % \
                  ( self.constraint, self.globalInfo.id )
            logger.error(txt)
            raise SModelSError(txt)

        if hasattr(self, 'condition') and self.condition:
            conds = self.condition
            if not isinstance(conds, list): conds = [conds]
            for cond in conds:
                for el in elementsInStr(str(cond)):
                    newEl = Element(el, self.finalState,
                                    self.intermediateState, databaseParticles)
                    if not newEl in elements:
                        elements.append(newEl)

        # Builds up TopologyList with all the elements appearing in constraints
        # and conditions:
        for el in elements:
            self._topologyList.addElement(el)
Beispiel #9
0
class TxName(object):
    """
    Holds the information related to one txname in the Txname.txt
    file (constraint, condition,...) as well as the data.
    """
    def __init__(self, path, globalObj, infoObj, databaseParticles):
        self.path = path
        self.globalInfo = globalObj
        self._infoObj = infoObj
        self.txnameData = None
        self.txnameDataExp = None  ## expected Data
        self._topologyList = TopologyList()
        self.finalState = ['MET', 'MET']  #default final state
        self.intermediateState = None  #default intermediate state

        logger.debug('Creating object based on txname file: %s' % self.path)
        #Open the info file and get the information:
        if not os.path.isfile(path):
            logger.error("Txname file %s not found" % path)
            raise SModelSError()
        txtFile = open(path, 'r')
        txdata = txtFile.read()
        txtFile.close()
        if not "txName" in txdata: raise TypeError
        if not 'upperLimits' in txdata and not 'efficiencyMap' in txdata:
            raise TypeError
        content = concatenateLines(txdata.split("\n"))

        #Get tags in info file:
        tags = [line.split(':', 1)[0].strip() for line in content]
        data = None
        expectedData = None
        dataType = None
        for i, tag in enumerate(tags):
            if not tag: continue
            line = content[i]
            value = line.split(':', 1)[1].strip()
            if tags.count(tag) != 1:
                logger.info("Duplicated field %s found in file %s" \
                             % (tag, self.path))
            if ';' in value: value = value.split(';')
            if tag == 'upperLimits':
                data = value
                dataType = 'upperLimit'
            elif tag == 'expectedUpperLimits':
                expectedData = value
                dataType = 'upperLimit'
            elif tag == 'efficiencyMap':
                data = value
                dataType = 'efficiencyMap'
            else:
                self.addInfo(tag, value)

        ident = self.globalInfo.id + ":" + dataType[0] + ":" + str(
            self._infoObj.dataId)
        ident += ":" + self.txName

        #Get detector size (if not found in self, look for it in datasetInfo or globalInfo).
        #If not defined anywhere, set it to None and default values will be used for reweighting.
        self.Leff_inner = self.fetchAttribute('Leff_inner', fillvalue=None)
        self.Leff_outer = self.fetchAttribute('Leff_outer', fillvalue=None)

        self.txnameData = TxNameData(data,
                                     dataType,
                                     ident,
                                     Leff_inner=self.Leff_inner,
                                     Leff_outer=self.Leff_outer)
        if expectedData:
            self.txnameDataExp = TxNameData(expectedData,
                                            dataType,
                                            ident,
                                            Leff_inner=self.Leff_inner,
                                            Leff_outer=self.Leff_outer)

        #Builds up a list of elements appearing in constraints:
        elements = []
        if not databaseParticles:
            raise SModelSError(
                "Database particles is empty. Can not create TxName object.")
        if hasattr(self, 'constraint'):
            elements += [
                Element(el, self.finalState, self.intermediateState,
                        databaseParticles)
                for el in elementsInStr(str(self.constraint))
            ]

        if any((elA == elB and not elA is elB) for elA in elements
               for elB in elements):
            txt = "Duplicate elements in constraint: %s in %s" % \
                  ( self.constraint, self.globalInfo.id )
            logger.error(txt)
            raise SModelSError(txt)

        if hasattr(self, 'condition') and self.condition:
            conds = self.condition
            if not isinstance(conds, list): conds = [conds]
            for cond in conds:
                for el in elementsInStr(str(cond)):
                    newEl = Element(el, self.finalState,
                                    self.intermediateState, databaseParticles)
                    if not newEl in elements:
                        elements.append(newEl)

        # Builds up TopologyList with all the elements appearing in constraints
        # and conditions:
        for el in elements:
            self._topologyList.addElement(el)

    def hasOnlyZeroes(self):
        ozs = self.txnameData.onlyZeroValues()
        if self.txnameDataExp:
            e_ozs = self.txnameDataExp.onlyZeroValues()
            if ozs and e_ozs:
                return True
            if (ozs and not e_ozs) or (e_ozs and not ozs):
                logger.warning(
                    "%s is weird. One of the (expected, observed) results is zeroes-only, the other one isnt."
                )
                return False
        return ozs

    def fetchAttribute(self, attr, fillvalue=None):
        """
        Auxiliary method to get the attribute from self. If
        not found, look for it in datasetInfo and if still not found
        look for it in globalInfo.
        If not found in either of the above, return fillvalue.

        :param attr: Name of attribute (string)
        :param fillvalue: Value to be returned if attribute is not found.

        :return: Value of the attribute or fillvalue, if attribute was not found.
        """

        if hasattr(self, attr):
            return getattr(self, attr)
        elif hasattr(self._infoObj, attr):
            return getattr(self._infoObj, attr)
        elif hasattr(self.globalInfo, attr):
            return getattr(self.globalInfo, attr)
        else:
            return fillvalue

    def __str__(self):
        return self.txName

    def __repr__(self):
        return self.__str__()

    def __lt__(self, other):
        """ sort by txName """
        return self.txName < other.txName

    def getULFor(self, element, expected=False):
        """
        Returns the upper limit (or expected) for element (only for upperLimit-type).
        Includes the lifetime reweighting (ul/reweight).
        If called for efficiencyMap results raises an error.
        If a mass array is given as input, no lifetime reweighting will be applied.

        :param element: Element object or mass array (with units)
        :param expected: look in self.txnameDataExp, not self.txnameData
        """
        if hasattr(self, "dbClient"):
            ## we have a databaseClient, so we send the request
            ## over the network
            # query = "obs:ATLAS-SUSY-2013-05:ul:T2bb:[[300,100],[300,100]]"
            query = "obs:"
            if expected:
                query = "exp:"
            query += self.globalInfo.id + ":ul:"
            query += self.txName + ":"
            query += self.getMassVectorFromElement(element)
            logger.info ( "sending ul query %s to %s:%d" % \
                          ( query, self.dbClient.servername, self.dbClient.port ) )
            from smodels.tools.physicsUnits import fb
            return self.dbClient.query(query)

        if not self.txnameData.dataType == 'upperLimit':
            logger.error("getULFor method can only be used in UL-type data.")
            raise SModelSError()

        if not expected:
            ul = self.txnameData.getValueFor(element)
        else:
            if not self.txnameDataExp:
                return None
            else:
                ul = self.txnameDataExp.getValueFor(element)

        return ul

    def addInfo(self, tag, value):
        """
        Adds the info field labeled by tag with value value to the object.

        :param tag: information label (string)
        :param value: value for the field in string format
        """

        if tag == 'constraint' or tag == 'condition':
            if isinstance(value, list):
                value = [val.replace("'", "") for val in value]
            else:
                value = value.replace("'", "")
            if value == 'None':
                setattr(self, tag, eval(value))
            else:
                setattr(
                    self, tag,
                    value)  #Make sure constraints/conditions are not evaluated
        else:
            try:
                setattr(self, tag, eval(value, unitsDict))
            except SyntaxError:
                setattr(self, tag, value)
            except NameError:
                setattr(self, tag, value)
            except TypeError:
                setattr(self, tag, value)

    def getInfo(self, infoLabel):
        """
        Returns the value of info field.

        :param infoLabel: label of the info field (string). It must be an attribute of
                          the TxNameInfo object
        """

        if hasattr(self, infoLabel): return getattr(self, infoLabel)
        else: return False

    def hasElementAs(self, element):
        """
        Verify if the conditions or constraint in Txname contains the element.
        Check both branch orderings. If both orderings match, returns the one
        with the highest mass array.

        :param element: Element object
        :return: A copy of the element on the correct branch ordering appearing
                in the Txname constraint or condition.
        """

        #Stores all orderings of elements which matches the txname
        matches = []
        for el in self._topologyList.getElements():
            #Compare branches:
            for branchesA in itertools.permutations(element.branches):
                branchesA = list(branchesA)
                if branchesA == el.branches:
                    newEl = element.copy()
                    newEl.branches = [br.copy() for br in branchesA]
                    matches.append(newEl)

        #No elements matched:
        if not matches:
            return False
        elif len(matches) == 1:
            return matches[0]
        else:  #If more than one element ordering matches, return the one with largest mass (relevant for clustering)
            matches = sorted(matches, key=lambda el: el.mass, reverse=True)
            return matches[0]

    def hasLikelihood(self):
        """ can I construct a likelihood for this map?
        True for all efficiency maps, and for upper limits maps
        with expected Values. """
        if self._infoObj.dataType == "efficiencyMap":
            return True
        if self.txnameDataExp != None:
            return True
        return False

    def getMassVectorFromElement(self, element):
        """
        given element, extract the mass vector for the server query.
        element can be list of masses or "Element"

        :returns: eg [[300,100],[300,100]]
        """
        if type(element) == list:
            return str(element).replace(" [GeV]", "").replace(" ", "")
        from smodels.theory.clusterTools import AverageElement
        if type(element) == AverageElement:
            # ret += str(element.mass).replace(" [GeV]","").replace(" ","")
            return str(element.mass).replace(" [GeV]", "").replace(" ", "")
        ret = "["
        for i, br in enumerate(element.branches):
            ret += str(br.mass).replace(" [GeV]", "").replace(" ", "")
            if i + 1 < len(element.branches):
                ret += ","
        ret += "]"
        # print ( "getMassVectorFromElement returning", ret )
        return ret

    def getQueryStringForElement(self, element):
        ## we have a databaseClient, so we send the request
        ## over the network
        # query = "obs:ATLAS-SUSY-2013-05:ul:T2bb:[[300,100],[300,100]]"
        query = "obs:"
        #if expected:
        #    query = "exp:"
        query += self.globalInfo.id + ":"
        dId = self._infoObj.dataId
        if dId == None:
            dId = "ul"
        query += dId + ":"
        query += self.txName + ":"
        query += self.getMassVectorFromElement(element)
        return query

    def getEfficiencyFor(self, element):
        """
        For upper limit results, checks if the input element falls inside the
        upper limit grid and has a non-zero reweigthing factor.
        If it does, returns efficiency = 1, else returns
        efficiency = 0.  For efficiency map results, returns the
        signal efficiency including the lifetime reweighting.
        If a mass array is given as input, no lifetime reweighting will be applied.

        :param element: Element object or mass array with units.
        :return: efficiency (float)
        """

        if self.txnameData.dataType == 'efficiencyMap':
            if hasattr(self, "dbClient"):
                query = self.getQueryStringForElement(element)
                logger.info ( "sending em query %s to %s:%d" % \
                              ( query, self.dbClient.servername, self.dbClient.port ) )
                #print ( "query will be", query )
                #return 0.001
                eff = self.dbClient.query(query)
            else:
                eff = self.txnameData.getValueFor(element)

            if not eff or math.isnan(eff):
                eff = 0.  #Element is outside the grid or has zero efficiency
        elif self.txnameData.dataType == 'upperLimit':
            if hasattr(self, "dbClient"):
                query = self.getQueryStringForElement(element)
                logger.info ( "sending query %s to %s:%d" % \
                              ( query, self.dbClient.servername, self.dbClient.port ) )
                #print ( "query will be", query )
                #return 0.001
                ul = self.dbClient.query(query)
            else:
                ul = self.txnameData.getValueFor(element)
            if isinstance(element, Element):
                element._upperLimit = ul  #Store the upper limit for convenience
            if ul is None:
                eff = 0.  #Element is outside the grid or the decays do not correspond to the txname
            else:
                eff = 1.
        else:
            logger.error("Unknown txnameData type: %s" %
                         self.txnameData.dataType)
            raise SModelSError()

        return eff