def _edge_type(self): ''' produces an edge_type string eg "ecal_track" the order of id1 an id2 does not matter, eg for one track and one ecal the type will always be "ecal_track" (and never be a "track_ecal") ''' #consider creating an ENUM instead for the edge_type shortid1 = Identifier.type_short_code(self.id1) shortid2 = Identifier.type_short_code(self.id2) if shortid1 == shortid2: if shortid1 == "h": return "hcal_hcal" elif shortid1 == "e": return "ecal_ecal" elif shortid1 == "t": return "track_track" elif (shortid1 == "h" and shortid2 == "t" or shortid1 == "t" and shortid2 == "h"): return "hcal_track" elif (shortid1 == "e" and shortid2 == "t" or shortid1 == "t" and shortid2 == "e"): return "ecal_track" elif (shortid1 == "e" and shortid2 == "h" or shortid1 == "h" and shortid2 == "e"): return "ecal_hcal" return "unknown"
def __init__(self, element_ids, edges, pfevent): ''' element_ids: list of the uniqueids of the elements to go in this block [id1,id2,...] edges: is a dictionary of edges, it must contain at least all needed edges. It is not a problem if it contains additional edges as only the ones needed will be extracted pfevent: allows access to the underlying elements given a uniqueid must provide a get_object function ''' #make a uniqueid for this block self.uniqueid = Identifier.make_id(Identifier.PFOBJECTTYPE.BLOCK) self.is_active = True # if a block is subsequently split it will be deactivated #allow access to the underlying objects self.pfevent=pfevent #order the elements by element type (ecal, hcal, track) and then by energy #this is a bit yucky but needed to make sure the order returned is consistent #maybe should live outside of this class self.element_uniqueids = sorted(element_ids, key = lambda x: (Identifier.type_short_code(x),-self.pfevent.get_object(x).energy) ) #sequential numbering of blocks, not essential but helpful for debugging self.block_count = PFBlock.temp_block_count PFBlock.temp_block_count += 1 #extract the relevant parts of the complete set of edges and store this within the block self.edges = dict() for id1, id2 in itertools.combinations(self.element_uniqueids,2): key = Edge.make_key(id1,id2) self.edges[key] = edges[key]
def __init__(self, element_ids, edges, pfevent): ''' element_ids: list of the uniqueids of the elements to go in this block [id1,id2,...] edges: is a dictionary of edges, it must contain at least all needed edges. It is not a problem if it contains additional edges as only the ones needed will be extracted pfevent: allows access to the underlying elements given a uniqueid must provide a get_object function ''' #make a uniqueid for this block self.uniqueid = Identifier.make_id(Identifier.PFOBJECTTYPE.BLOCK) self.is_active = True # if a block is subsequently split it will be deactivated #allow access to the underlying objects self.pfevent = pfevent #comment out energy sorting for now as not available C++ sortby = lambda x: Identifier.type_short_code(x) self.element_uniqueids = sorted(element_ids, key=sortby) #sequential numbering of blocks, not essential but helpful for debugging self.block_count = PFBlock.temp_block_count PFBlock.temp_block_count += 1 #extract the relevant parts of the complete set of edges and store this within the block self.edges = dict() for id1, id2 in itertools.combinations(self.element_uniqueids, 2): key = Edge.make_key(id1, id2) self.edges[key] = edges[key]
def edge_matrix_string(self): ''' produces a string containing the the lower part of the matrix of distances between elements elements are ordered as ECAL(E), HCAL(H), Track(T) for example:- distances: E0 H1 T2 T3 E0 . H1 0.0267 . T2 0.0000 0.0000 . T3 0.0287 0.0825 --- . ''' # make the header line for the matrix count = 0 matrixstr = " distances:\n " for e1 in self.element_uniqueids : # will produce short id of form E2 H3, T4 etc in tidy format elemstr = Identifier.type_short_code(e1) + str(count) matrixstr += "{:>9}".format(elemstr) count += 1 matrixstr += "\n" #for each element find distances to all other items that are in the lower part of the matrix countrow = 0 for e1 in self.element_uniqueids : # this will be the rows countcol = 0 rowstr = "" #make short name for the row element eg E3, H5 etc rowname = Identifier.type_short_code(e1) +str(countrow) for e2 in self.element_uniqueids: # these will be the columns #make short name for the col element eg E3, H5 colname = Identifier.type_short_code(e1) + str(countcol) countcol += 1 if (e1 == e2): rowstr += " . " break elif self.get_edge(e1,e2).distance == None: rowstr += " ---" + " " elif self.get_edge(e1,e2).linked == False: rowstr += " xxx" + " " else : rowstr += "{:8.4f}".format(self.get_edge(e1,e2).distance) + " " matrixstr += "{:>11}".format(rowname) + rowstr + "\n" countrow += 1 return matrixstr +" }\n"
def edge_matrix_string(self): ''' produces a string containing the the lower part of the matrix of distances between elements elements are ordered as ECAL(E), HCAL(H), Track(T) for example:- distances: E0 H1 T2 T3 E0 . H1 0.0267 . T2 0.0000 0.0000 . T3 0.0287 0.0825 --- . ''' # make the header line for the matrix count = 0 matrixstr = "\n" if len(self.element_uniqueids) > 1: matrixstr = " distances:\n " for e1 in self.element_uniqueids: # will produce short id of form E2 H3, T4 etc in tidy format elemstr = Identifier.type_short_code(e1) + str(count) matrixstr += "{:>8}".format(elemstr) count += 1 matrixstr += "\n" #for each element find distances to all other items that are in the lower part of the matrix countrow = 0 for e1 in self.element_uniqueids: # this will be the rows countcol = 0 rowstr = "" #make short name for the row element eg E3, H5 etc rowname = Identifier.type_short_code(e1) + str(countrow) for e2 in self.element_uniqueids: # these will be the columns countcol += 1 if e1 == e2: rowstr += " ." break elif self.get_edge(e1, e2).distance is None: rowstr += " ---" elif not self.get_edge(e1, e2).linked: rowstr += " xxx" else: rowstr += "{:8.4f}".format( self.get_edge(e1, e2).distance) matrixstr += "{:>8}".format(rowname) + rowstr + "\n" countrow += 1 return matrixstr
def _edge_type(self): ''' produces an edge_type string eg "ecal_track" the order of id1 an id2 does not matter, eg for one track and one ecal the type will always be "ecal_track" (and never be a "track_ecal") ''' #consider creating an ENUM instead for the edge_type shortid1=Identifier.type_short_code(self.id1); shortid2=Identifier.type_short_code(self.id2); if shortid1 == shortid2: if shortid1 == "h": return "hcal_hcal" elif shortid1 == "e": return "ecal_ecal" elif shortid1 == "t": return "track_track" elif (shortid1=="h" and shortid2=="t" or shortid1=="t" and shortid2=="h"): return "hcal_track" elif (shortid1=="e" and shortid2=="t" or shortid1=="t" and shortid2=="e"): return "ecal_track" elif (shortid1=="e" and shortid2=="h" or shortid1=="h" and shortid2=="e"): return "ecal_hcal" return "unknown"
def elements_string(self): ''' Construct a string description of each of the elements in a block:- The elements are given a short name E/H/T according to ecal/hcal/track and then sequential numbering starting from 0, this naming is also used to index the matrix of distances. The full unique id is also given. For example:- elements: { E0:1104134446736:SmearedCluster : ecal_in 0.57 0.33 -2.78 H1:2203643940048:SmearedCluster : hcal_in 6.78 0.35 -2.86 T2:3303155568016:SmearedTrack : 5.23 4.92 0.34 -2.63 } ''' count = 0 elemdetails = "\n elements: {\n" for uid in self.element_uniqueids: elemdetails += " {shortname}{count}:{strdescrip}\n".format( shortname=Identifier.type_short_code(uid), count=count, strdescrip=self.pfevent.get_object(uid).__str__()) count = count + 1 return elemdetails + " }\n"
def elements_string(self): ''' Construct a string description of each of the elements in a block:- The elements are given a short name E/H/T according to ecal/hcal/track and then sequential numbering starting from 0, this naming is also used to index the matrix of distances. The full unique id is also given. For example:- elements: { E0:1104134446736:SmearedCluster : ecal_in 0.57 0.33 -2.78 H1:2203643940048:SmearedCluster : hcal_in 6.78 0.35 -2.86 T2:3303155568016:SmearedTrack : 5.23 4.92 0.34 -2.63 } ''' count = 0 elemdetails = "\n elements: {\n" for uid in self.element_uniqueids: elemdetails += " {shortname}{count}:{strdescrip}\n".format( shortname=Identifier.type_short_code(uid), count=count, strdescrip=self.pfevent.get_object(uid).__str__()) count = count + 1 return elemdetails + " }\n"