Ejemplo n.º 1
0
 def _getMaxInternalDist(self):
     """
     Return the maximum distance between any pair of elements belonging
     to the cluster as well as the cluster center and any element.
     
     """
     dmax = 0.
     if self.avgPosition == None:
         self.avgPosition = self._getAvgPosition()
     for iel in self:
         dmax = max(dmax, distance(self.positionMap[iel], self.avgPosition))
         dmax = max(dmax, self._getDistanceTo(iel))
     return dmax
Ejemplo n.º 2
0
 def _getMaxInternalDist(self):
     """
     Return the maximum distance between any pair of elements belonging
     to the cluster as well as the cluster center and any element.
     
     """
     dmax = 0.
     if self.avgPosition == None:
         self.avgPosition = self._getAvgPosition()
     for iel in self:
         dmax = max(dmax, distance(self.positionMap[iel], self.avgPosition))
         dmax = max(dmax, self._getDistanceTo(iel))
     return dmax
Ejemplo n.º 3
0
def _getGoodElements(elements, analysis, maxDist):
    """
    Get the list of elements which have masses satisfying the analysis conditions
    and that lie inside the analysis upper limit grid.
    
    Most analyses require equal branch masses.
    For such analyses good masses are defined as those where both branches in the element have identical
    mass arrays or where the distance between the two mass arrays is smaller than maxDist.
    e.g. if the element mass array is [[m1,m2] , [m3,m4]] (branch1 = [m1,m2], branch2 = [m3,m4]),
    then the mass is "good" if m1=m3 and m3=m4 or if the mass distance between [[m1,m2],[m1,m2]]
    and [[m3,m4],[m3,m4]] is smaller than maxDist.
    If the element has a good mass, its mass is replaced by the mass average of [[m1,m2],[m1,m2]]
    and [[m3,m4],[m3,m4]].
    For the anlyses where there is no such requirement, return the original list of elements
    with masses lying inside the analysis grid.
        
    :parameter elements: list of all elements to be clustered
    :parameter analysis: analysis to which the cluster applies (ULanalysis object)
    :parameter maxDist: maximum mass distance for clustering two elements
    
    :returns: list with a copy of the elements with good masses, with their masses replaced by
    the branch average (if equal branch masses are required by the analysis)
    """
    goodElements = []
    branchCondition = analysis.getBranchCondition()

    for element in elements:
        mass = element.getMasses()
        goodmass = None
        if mass[0] != mass[1] and (not branchCondition
                                   or branchCondition == "equal branches"):
            mass1 = [mass[0], mass[0]]
            mass2 = [mass[1], mass[1]]
            mP1 = massPosition(mass1, analysis)
            mP2 = massPosition(mass2, analysis)
            if type(mP1) == type(None) or type(mP2) == type(None):
                continue
            if distance(mP1, mP2) < maxDist:
                goodmass = massAvg([mass1, mass2], method='harmonic')
        else:
            p = massPosition(mass, analysis)
            if type(p) == type(fb): goodmass = mass

        if goodmass and type(massPosition(goodmass, analysis)) == type(fb):
            goodElements.append(element.copy())
            goodElements[-1].setMasses(goodmass)

    return goodElements
Ejemplo n.º 4
0
def _getGoodElements(elements, analysis, maxDist):
    """
    Get the list of elements which have masses satisfying the analysis conditions
    and that lie inside the analysis upper limit grid.
    
    Most analyses require equal branch masses.
    For such analyses good masses are defined as those where both branches in the element have identical
    mass arrays or where the distance between the two mass arrays is smaller than maxDist.
    e.g. if the element mass array is [[m1,m2] , [m3,m4]] (branch1 = [m1,m2], branch2 = [m3,m4]),
    then the mass is "good" if m1=m3 and m3=m4 or if the mass distance between [[m1,m2],[m1,m2]]
    and [[m3,m4],[m3,m4]] is smaller than maxDist.
    If the element has a good mass, its mass is replaced by the mass average of [[m1,m2],[m1,m2]]
    and [[m3,m4],[m3,m4]].
    For the anlyses where there is no such requirement, return the original list of elements
    with masses lying inside the analysis grid.
        
    :parameter elements: list of all elements to be clustered
    :parameter analysis: analysis to which the cluster applies (ULanalysis object)
    :parameter maxDist: maximum mass distance for clustering two elements
    
    :returns: list with a copy of the elements with good masses, with their masses replaced by
    the branch average (if equal branch masses are required by the analysis)
    """
    goodElements = []    
    branchCondition = analysis.getBranchCondition()   
    
    for element in elements:
        mass = element.getMasses()
        goodmass = None
        if mass[0] != mass[1] and (not branchCondition or branchCondition == "equal branches"):
            mass1 = [mass[0], mass[0]]
            mass2 = [mass[1], mass[1]]
            mP1 = massPosition(mass1, analysis)
            mP2 = massPosition(mass2, analysis)
            if type(mP1)==type(None) or type(mP2)==type(None):
                continue
            if distance(mP1, mP2) < maxDist:
                goodmass = massAvg([mass1, mass2], method='harmonic')
        else:
            p=massPosition(mass, analysis)
            if type(p)==type(fb): goodmass = mass

        if goodmass and type(massPosition(goodmass, analysis))==type(fb):
            goodElements.append(element.copy())
            goodElements[-1].setMasses(goodmass)

    return goodElements
Ejemplo n.º 5
0
    def _getDistanceTo(self, obj):
        """
        Return the maximum distance between any elements belonging to the
        cluster and the object obj.
        
        obj can be a position in upper limit space or an element index.
        
        """
        dmax = 0.
        if type(obj) == type(int()) and obj >= 0:
            pos = self.positionMap[obj]
        elif type(obj) == type(fb):
            pos = obj
        else:
            logger.error("Unknown object type (must be an element index or "
                         "position)")
            import sys
            sys.exit()

        for jel in self:
            dmax = max(dmax, distance(pos, self.positionMap[jel]))
        return dmax
Ejemplo n.º 6
0
    def _getDistanceTo(self, obj):
        """
        Return the maximum distance between any elements belonging to the
        cluster and the object obj.
        
        obj can be a position in upper limit space or an element index.
        
        """
        dmax = 0.
        if type(obj) == type(int()) and obj >= 0:
            pos = self.positionMap[obj]
        elif type(obj) == type(fb):
            pos = obj
        else:
            logger.error("Unknown object type (must be an element index or "
                         "position)")
            import sys
            sys.exit()

        for jel in self:
            dmax = max(dmax, distance(pos, self.positionMap[jel]))
        return dmax
Ejemplo n.º 7
0
def _doCluster(elements, analysis, maxDist):
    """
    Cluster algorithm to cluster elements.
    
    :parameter elements: list of all elements to be clustered
    :parameter analysis: analysis to which the cluster applies (ULanalysis object)
    :parameter maxDist: maximum mass distance for clustering two elements
    
    :returns: a list of ElementCluster objects containing the elements
    belonging to the cluster    
    """
    # First build the element:mass, element:position in UL space
    # and element:maxWeight (in fb) dictionaries
    #(Combine elements with identical masses)
    massMap = {}
    posMap = {}
    weightMap = {}
    for iel, el in enumerate(elements):
        if not el.getMasses() in massMap.values():
            massMap[iel] = el.getMasses()
            posMap[iel] = massPosition(massMap[iel], analysis)
            weightMap[iel] = el.weight.getMaxXsec() / fb
        else:
            j = massMap.keys()[massMap.values().index(el.getMasses())]
            weightMap[j] += el.weight.getMaxXsec() / fb

    # Start with maximal clusters
    clusterList = []
    for iel in posMap:
        indices = [iel]
        for jel in posMap:
            if distance(posMap[iel], posMap[jel]) <= maxDist:
                indices.append(jel)
        indexCluster = IndexCluster(massMap, posMap, weightMap, set(indices),
                                    analysis)
        clusterList.append(indexCluster)

    #Split the maximal clusters until all elements inside each cluster are
    #less than maxDist apart from each other and the cluster average position
    #is less than maxDist apart from all elements
    finalClusters = []
    newClusters = True
    while newClusters:
        newClusters = []
        for indexCluster in clusterList:
            # cluster is good
            if indexCluster._getMaxInternalDist() < maxDist:
                if not indexCluster in finalClusters:
                    finalClusters.append(indexCluster)
                continue
            # Distance to cluster center (average)
            distAvg = indexCluster._getDistanceTo(indexCluster.avgPosition)
            #Loop over cluster elements and if element distance or cluster
            #average distance falls outside the cluster, remove element
            for iel in indexCluster:
                dist = indexCluster._getDistanceTo(iel)
                if max(dist, distAvg) > maxDist:
                    newcluster = indexCluster.copy()
                    newcluster.remove(iel)
                    if not newcluster in newClusters:
                        newClusters.append(newcluster)

        clusterList = newClusters
        # Check for oversized list of indexCluster (too time consuming)
        if len(clusterList) > 100:
            logger.warning("ElementCluster failed, using unclustered masses")
            finalClusters = []
            clusterList = []

    # finalClusters = finalClusters + clusterList
    # Add clusters of individual masses (just to be safe)
    for iel in massMap:
        finalClusters.append(
            IndexCluster(massMap, posMap, weightMap, set([iel]), analysis))

    # Clean up clusters (remove redundant clusters)
    for ic, clusterA in enumerate(finalClusters):
        if clusterA is None:
            continue
        for jc, clusterB in enumerate(finalClusters):
            if clusterB is None:
                continue
            if ic != jc and clusterB.indices.issubset(clusterA.indices):
                finalClusters[jc] = None
    while finalClusters.count(None) > 0:
        finalClusters.remove(None)

    # Transform index clusters to element clusters:
    clusterList = []
    for indexCluster in finalClusters:
        cluster = ElementCluster()
        masses = [massMap[iel] for iel in indexCluster]
        for el in elements:
            if el.getMasses() in masses:
                cluster.elements.append(el)
        clusterList.append(cluster)

    return clusterList
Ejemplo n.º 8
0
def _doCluster(elements, analysis, maxDist):
    """
    Cluster algorithm to cluster elements.
    
    :parameter elements: list of all elements to be clustered
    :parameter analysis: analysis to which the cluster applies (ULanalysis object)
    :parameter maxDist: maximum mass distance for clustering two elements
    
    :returns: a list of ElementCluster objects containing the elements
    belonging to the cluster    
    """
    # First build the element:mass, element:position in UL space
    # and element:maxWeight (in fb) dictionaries
    #(Combine elements with identical masses)
    massMap = {}
    posMap = {}
    weightMap = {}
    for iel, el in enumerate(elements):
        if not el.getMasses() in massMap.values():
            massMap[iel] = el.getMasses()
            posMap[iel] = massPosition(massMap[iel], analysis)
            weightMap[iel] = el.weight.getMaxXsec() / fb
        else:
            j = massMap.keys()[massMap.values().index(el.getMasses())] 
            weightMap[j] += el.weight.getMaxXsec() / fb

    # Start with maximal clusters
    clusterList = []
    for iel in posMap:
        indices = [iel]
        for jel in posMap:            
            if distance(posMap[iel], posMap[jel]) <= maxDist:
                indices.append(jel)        
        indexCluster = IndexCluster(massMap, posMap, weightMap, set(indices), analysis)
        clusterList.append(indexCluster)

    #Split the maximal clusters until all elements inside each cluster are
    #less than maxDist apart from each other and the cluster average position
    #is less than maxDist apart from all elements
    finalClusters = []
    newClusters = True
    while newClusters:
        newClusters = []
        for indexCluster in clusterList:
            # cluster is good
            if indexCluster._getMaxInternalDist() < maxDist:
                if not indexCluster in finalClusters:
                    finalClusters.append(indexCluster)
                continue
            # Distance to cluster center (average)
            distAvg = indexCluster._getDistanceTo(indexCluster.avgPosition)
            #Loop over cluster elements and if element distance or cluster
            #average distance falls outside the cluster, remove element
            for iel in indexCluster:
                dist = indexCluster._getDistanceTo(iel)
                if max(dist, distAvg) > maxDist:
                    newcluster = indexCluster.copy()
                    newcluster.remove(iel)
                    if not newcluster in newClusters:
                        newClusters.append(newcluster)

        clusterList = newClusters
        # Check for oversized list of indexCluster (too time consuming)
        if len(clusterList) > 100:
            logger.warning("ElementCluster failed, using unclustered masses")
            finalClusters = []
            clusterList = []

    # finalClusters = finalClusters + clusterList
    # Add clusters of individual masses (just to be safe)
    for iel in massMap:
        finalClusters.append(IndexCluster(massMap, posMap, weightMap,
                                           set([iel]),analysis))

    # Clean up clusters (remove redundant clusters)
    for ic, clusterA in enumerate(finalClusters):
        if clusterA is None:
            continue
        for jc, clusterB in enumerate(finalClusters):
            if clusterB is None:
                continue
            if ic != jc and clusterB.indices.issubset(clusterA.indices):
                finalClusters[jc] = None
    while finalClusters.count(None) > 0:
        finalClusters.remove(None)

    # Transform index clusters to element clusters:
    clusterList = []
    for indexCluster in finalClusters:
        cluster = ElementCluster()
        masses = [massMap[iel] for iel in indexCluster]
        for el in elements:
            if el.getMasses() in masses:
                cluster.elements.append(el)
        clusterList.append(cluster)

    return clusterList