Пример #1
0
 def update_history(self, parentid, childid):
     '''Updates the history adding new nodes if needed and recording parent child relationship'''
     child = self.history.setdefault(
         childid,
         Node(childid))  #creates a new node if it is not there already
     parent = self.history.setdefault(parentid, Node(parentid))
     parent.add_child(child)
Пример #2
0
    def process(self, event):
        event.papasevent = PapasEvent(event.iEv)
        papasevent = event.papasevent

        #make a dict from the gen_particles list so that it can be stored into the papasevent collections
        gen_particles = getattr(event, self.cfg_ana.gen_particles)
        gen_particles_collection = {}
        for g in gen_particles:
            #set the papas identifiers for use in DAG
            g.set_dagid(
                IdCoder.make_id(IdCoder.PFOBJECTTYPE.PARTICLE,
                                g.objid()[0], 'g',
                                g.p4().E()))
            gen_particles_collection[g.dagid()] = g

        #make a dict from the rec_particles list so that it can be stored into the papasevent collections
        rec_particles = getattr(event, self.cfg_ana.rec_particles)

        #if there are no rec_particles we assume this was an evernt discarded during reconstruction and skip it
        if len(rec_particles) == 0:
            self.mainLogger.error(
                'no reconsrtucted particles found -> Event discarded')
            return False
        rec_particles_collection = {}
        for r in rec_particles:
            #set the papas identifiers for use in DAG
            r.set_dagid(
                IdCoder.make_id(IdCoder.PFOBJECTTYPE.PARTICLE,
                                r.objid()[0], 'r',
                                r.p4().E()))
            rec_particles_collection[r.dagid()] = r

        #create the history links for relationship between gen and rec particles
        particle_links = getattr(event, self.cfg_ana.gen_rec_links)
        for plink in particle_links:
            genid = None
            recid = None
            for g in gen_particles:
                if g.objid() == plink.id1():
                    genid = g.dagid()
                    break
            for g in rec_particles:
                if g.objid() == plink.id2():
                    recid = g.dagid()
                    break
            if recid == None or genid == None:
                self.mainLogger.error(
                    'Error: One of the particles in the Particle Link was not found-> discarding event'
                )
                return False
            child = papasevent.history.setdefault(
                recid,
                Node(recid))  #creates a new node if it is not there already
            parent = papasevent.history.setdefault(genid, Node(genid))
            parent.add_child(child)

        papasevent.add_collection(gen_particles_collection)
        papasevent.add_collection(rec_particles_collection)
Пример #3
0
 def build_collections_and_history(self, papasevent, sim_particles):  
     #todo this should be integrated into the simulator in the future
     simulated_particles = dict()
     tracks = dict()
     smeared_tracks=dict()
     smeared_hcals = dict()
     true_hcals = dict()
     smeared_ecals = dict()
     true_ecals = dict()    
     smeared_tracks = dict()
     true_tracks = dict()            
     
     history =  papasevent.history
     for ptc in sim_particles:
         uid = ptc.uniqueid
         simulated_particles[uid] = ptc
         history[uid] = Node(uid)
         if ptc.track:
             track_id = ptc.track.uniqueid
             true_tracks[track_id] = ptc.track
             history[track_id] = Node(track_id)
             history[uid].add_child(history[track_id])
             if ptc.track_smeared:
                 smtrack_id = ptc.track_smeared.uniqueid
                 smeared_tracks[smtrack_id] = ptc.track_smeared
                 history[smtrack_id] = Node(smtrack_id)
                 history[track_id].add_child(history[smtrack_id])    
         if len(ptc.clusters) > 0 : 
             for key, clust in ptc.clusters.iteritems():
                 if Identifier.get_type(clust.uniqueid) == Identifier.PFOBJECTTYPE.ECALCLUSTER:
                     true_ecals[clust.uniqueid] = clust                       
                 elif Identifier.get_type(clust.uniqueid) == Identifier.PFOBJECTTYPE.HCALCLUSTER:
                     true_hcals[clust.uniqueid] = clust
                 else:
                     assert(False)                    
                 history[clust.uniqueid] = Node(clust.uniqueid)
                 history[uid].add_child(history[clust.uniqueid])  
 
                 if len(ptc.clusters_smeared) > 0 :  #need to put in link between true and smeared cluster 
                     for key1, smclust in ptc.clusters_smeared.iteritems():
                         if (key == key1): 
                             if Identifier.get_type(smclust.uniqueid) == Identifier.PFOBJECTTYPE.ECALCLUSTER:
                                 smeared_ecals[smclust.uniqueid]=smclust
                             elif Identifier.get_type(smclust.uniqueid) == Identifier.PFOBJECTTYPE.HCALCLUSTER:
                                 smeared_hcals[smclust.uniqueid]=smclust 
                             history[smclust.uniqueid] = Node(smclust.uniqueid)
                             history[clust.uniqueid].add_child(history[smclust.uniqueid])
                         
     papasevent.add_collection(simulated_particles)
     papasevent.add_collection(true_tracks)
     papasevent.add_collection(smeared_tracks)
     papasevent.add_collection(smeared_hcals)
     papasevent.add_collection(true_hcals)
     papasevent.add_collection(smeared_ecals)
     papasevent.add_collection(true_ecals)    
Пример #4
0
 def insert_particle(self, block, newparticle):
         ''' The new particle will be inserted into the history_nodes (if present).
             A new node for the particle will be created if needed.
             It will have as its parents the block and all the elements of the block.
             '''        
         #Note that although it may be possible to specify more closely that the particle comes from
         #some parts of the block, there are frequently ambiguities and so for now the particle is
         #linked to everything in the block
         if (newparticle) :
             newid = newparticle.uniqueid
             self.particles[newid] = newparticle            
             
             #check if history nodes exists
             if (self.history_nodes == None):
                 return
             
             #find the node for the block        
             blocknode = self.history_nodes[block.uniqueid]
             
             #find or make a node for the particle            
             if newid  in self.history_nodes :
                 pnode = self.history_nodes[newid]
             else :
                 pnode = Node(newid)
                 self.history_nodes[newid] = pnode
             
             #link particle to the block            
             blocknode.add_child(pnode)
             #link particle to block elements
             for element_id in block.element_uniqueids:
                 self.history_nodes[element_id].add_child(pnode)    
Пример #5
0
 def simulate(self, ptcs, history):
     self.reset()
     self.history = history
     # import pdb; pdb.set_trace()
     for gen_ptc in ptcs:
         if gen_ptc.q() and gen_ptc.pt() < 0.2 and abs(
                 gen_ptc.pdgid()) >= 100:
             # to avoid numerical problems in propagation (and avoid making a particle that is not used)
             continue
         ptc = pfsimparticle(gen_ptc, len(self.simulated_particles))
         self.history[ptc.uniqueid] = Node(ptc.uniqueid)
         if ptc.pdgid() == 22:
             self.simulate_photon(ptc)
         elif abs(ptc.pdgid()) == 11:  #check with colin
             # self.propagate_electron(ptc)
             self.simulate_electron(ptc)
         elif abs(ptc.pdgid()) == 13:  #check with colin
             # self.propagate_muon(ptc)
             self.simulate_muon(ptc)
         elif abs(ptc.pdgid()) in [12, 14, 16]:
             self.simulate_neutrino(ptc)
         elif abs(ptc.pdgid()) > 100:  #TODO make sure this is ok
             self.simulate_hadron(ptc)
         self.ptcs.append(ptc)
         self.simulated_particles[ptc.uniqueid] = ptc
Пример #6
0
    def __init__(self, papasevent, uniqueids, ruler, subtype='r'):
        '''
            papasevent a PapasEvent (see above)            
            uniqueids list of which ids from papasevent to build blocks out of
            ruler is something that measures distance between two objects eg track and hcal
                (see Distance class for example)
                it should take the two objects as arguments and return a tuple
                of the form
                    link_type = 'ecal_ecal', 'ecal_track' etc
                    is_link = true/false
                    distance = float
            subtype says which identifier subtype to use when creating new blocks eg 'r' reconstructed, 's' split
        '''
        uniqueids = sorted(uniqueids)
        self.papasevent = papasevent
        if self.papasevent.history is None:
            self.papasevent.history = dict(
                (idt, Node(idt)) for idt in uniqueids)

        # compute edges between each pair of nodes
        edges = dict()

        for id1 in uniqueids:
            for id2 in uniqueids:
                if id1 < id2:
                    edge = self._make_edge(id1, id2, ruler)
                    #the edge object is added into the edges dictionary
                    edges[edge.key] = edge

        #use the underlying BlockBuilder to construct the blocks
        super(PFBlockBuilder, self).__init__(uniqueids, edges, subtype,
                                             self.papasevent.history)
Пример #7
0
 def add_ecal_cluster(self, uid):
     clust = Cluster(uid, 'ecal_in')  # make a cluster
     uniqueid = clust.uniqueid
     self.event.ecal_clusters[
         uniqueid] = clust  # add into the collection of clusters
     self.event.history[uniqueid] = Node(
         uniqueid)  #add into the collection of History Nodes
Пример #8
0
    def process(self, event):

        event.simulator = self
        if self.is_display:
            self.display.clear()
        pfsim_particles = []
        gen_particles = getattr(event, self.cfg_ana.gen_particles)
        try:
            self.simulator.simulate(gen_particles)
        except (PropagationError, SimulationError) as err:
            self.mainLogger.error(str(err) + ' -> Event discarded')
            return False
        pfsim_particles = self.simulator.ptcs
        if self.is_display:
            self.display.register(GTrajectories(pfsim_particles), layer=1)
        #these are the particles before simulation
        simparticles = sorted(pfsim_particles,
                              key=lambda ptc: ptc.e(),
                              reverse=True)
        setattr(event, self.simname, simparticles)

        #extract the tracks and clusters (extraction is prior to Colins merging step)
        event.tracks = dict()
        event.ecal_clusters = dict()
        event.hcal_clusters = dict()
        if "tracker" in self.simulator.pfinput.elements:
            for element in self.simulator.pfinput.elements["tracker"]:
                event.tracks[element.uniqueid] = element

        if "ecal_in" in self.simulator.pfinput.elements:
            for element in self.simulator.pfinput.elements["ecal_in"]:
                event.ecal_clusters[element.uniqueid] = element

        if "hcal_in" in self.simulator.pfinput.elements:
            for element in self.simulator.pfinput.elements["hcal_in"]:
                event.hcal_clusters[element.uniqueid] = element

        ruler = Distance()

        #create history node
        #note eventually history will be created by the simulator and passed in
        # as an argument and this will no longer be needed
        uniqueids = list(event.tracks.keys()) + list(
            event.ecal_clusters.keys()) + list(event.hcal_clusters.keys())
        history = dict((idt, Node(idt)) for idt in uniqueids)

        #Now merge the simulated clusters and tracks as a separate pre-stage (prior to new reconstruction)
        # and set the event to point to the merged cluster
        pfevent = PFEvent(event, 'tracks', 'ecal_clusters', 'hcal_clusters')
        merged_ecals = MergedClusterBuilder(pfevent.ecal_clusters, ruler,
                                            history)
        setattr(event, self.mergedecalsname, merged_ecals.merged)
        merged_hcals = MergedClusterBuilder(pfevent.hcal_clusters, ruler,
                                            merged_ecals.history_nodes)
        setattr(event, self.mergedhcalsname, merged_hcals.merged)
        setattr(event, self.historyname, merged_hcals.history_nodes)
Пример #9
0
 def simparticle(ptc, index):
     '''Create a sim particle to be used in papas from an input particle.
     '''
     tp4 = ptc.p4()
     vertex = ptc.start_vertex().position()
     charge = ptc.q()
     pid = ptc.pdgid()
     simptc = Particle(tp4, vertex, charge, pid)
     simptc.set_dagid(
         IdCoder.make_id(IdCoder.PFOBJECTTYPE.PARTICLE, index, 's',
                         simptc.idvalue))
     pdebugger.info(" ".join(("Made", simptc.__str__())))
     #simptc.gen_ptc = ptc
     #record that sim particle derives from gen particle
     child = papasevent.history.setdefault(
         simptc.dagid(), Node(simptc.dagid(
         )))  #creates a new node if it is not there already
     parent = papasevent.history.setdefault(ptc.dagid(),
                                            Node(ptc.dagid()))
     parent.add_child(child)
     return simptc
Пример #10
0
    def __init__(self, pfevent, ruler, history_nodes=None):
        '''
        pfevent is event structure inside which we find
            tracks is a dictionary : {id1:track1, id2:track2, ...}
            ecal is a dictionary : {id1:ecal1, id2:ecal2, ...}
            hcal is a dictionary : {id1:hcal1, id2:hcal2, ...}
            get_object() which allows a cluster or track to be found from its id
        ruler is something that measures distance between two objects eg track and hcal
            (see Distance class for example)
            it should take the two objects as arguments and return a tuple
            of the form
                link_type = 'ecal_ecal', 'ecal_track' etc
                is_link = true/false
                distance = float
        history_nodes is an optional dictionary of Nodes : { id:Node1, id: Node2 etc}
            it could for example contain the simulation history nodes
            A Node contains the id of an item (cluster, track, particle etc)
            and says what it is linked to (its parents and children)
            if hist_nodes is provided it will be added to with the new block information
            If hist_nodes is not provided one will be created, it will contain nodes
            corresponding to each of the tracks, ecal etc and also for the blocks that
            are created by the event block builder.
        '''

        #given a unique id this can return the underying object
        self.pfevent = pfevent

        # collate all the ids of tracks and clusters and, if needed, make history nodes
        uniqueids = []
        uniqueids = list(pfevent.tracks.keys()) + list(
            pfevent.ecal_clusters.keys()) + list(pfevent.hcal_clusters.keys())
        uniqueids = sorted(uniqueids)

        self.history_nodes = history_nodes
        if history_nodes is None:
            self.history_nodes = dict((idt, Node(idt)) for idt in uniqueids)

        # compute edges between each pair of nodes
        edges = dict()

        for id1 in uniqueids:
            for id2 in uniqueids:
                if id1 < id2:
                    edge = self._make_edge(id1, id2, ruler)
                    #the edge object is added into the edges dictionary
                    edges[edge.key] = edge

        #use the underlying BlockBuilder to construct the blocks
        super(PFBlockBuilder, self).__init__(uniqueids, edges,
                                             self.history_nodes, pfevent)
Пример #11
0
 def add_particle(self, uid, pdgid, parents):
     ''' creates a new particle and then updates the 
         event to include the new node and its parental links
         pdgid = is the particle type id eg 22 for photon
         parents = list of the unique ids (from Identifier class) for the elements from 
                    which the particle has been reconstructed
     '''
     particle = ReconstructedParticle(uid, pdgid)
     self.event.reconstructed_particles[particle.uniqueid] = particle
     #Now create the history node and links
     particle_node = Node(particle.uniqueid)
     self.event.history[particle.uniqueid] = particle_node
     for parent in parents:
         self.event.history[parent].add_child(particle_node)
Пример #12
0
 def _make_blocks (self) :
     ''' uses the DAGfloodfill algorithm in connection with the BlockBuilder nodes
         to work out which elements are connected
         Each set of connected elements will be used to make a new PFBlock
     ''' 
     for subgraph in self.subgraphs:
         #make the block
         block = PFBlock(subgraph, self.edges, self.startindex + len(self.blocks), subtype=self.subtype)        
         pdebugger.info("Made {}".format(block))
         #put the block in the dict of blocks            
         self.blocks[block.uniqueid] = block
         
         #make a node for the block and add into the history Nodes
         if (self.history != None):
             blocknode = Node(block.uniqueid)
             self.history[block.uniqueid] = blocknode
             #now add in the links between the block elements and the block into the history
             for elemid in block.element_uniqueids:
                 self.history[elemid].add_child(blocknode)
Пример #13
0
 def insert_particle(self, parent_ids, newparticle):
     ''' The new particle will be inserted into the history_nodes (if present).
         A new node for the particle will be created if needed.
         It will have as its parents the block and all the elements of the block.
         '''
     #Note that although it may be possible to specify more closely that the particle comes from
     #some parts of the block, there are frequently ambiguities and so for now the particle is
     #linked to everything in the block
     if newparticle:
         newid = newparticle.uniqueid
         self.particles[newid] = newparticle
         #check if history nodes exists
         if self.papasevent.history is None:
             return
         assert (newid not in self.papasevent.history)
         particlenode = Node(newid)
         self.papasevent.history[newid] = particlenode
         #add in parental history
         for pid in parent_ids:
             self.papasevent.history[pid].add_child(particlenode)
Пример #14
0
 def _make_and_store_merged_clusters(self):
     '''
         This takes the subgraphs of connected clusters that are to be merged, and makes a new MergedCluster.
         It stores the new MergedCluser into the self.merged_clusters collection.
         It then updates the history to record the links between the clusters and the merged cluster.
     '''
     for subgraph in self.subgraphs:  # TODO may want to order subgraphs from largest to smallest at some point
         subgraph.sort(reverse=True)  #start with highest E or pT clusters
         overlapping_clusters = [
             self.clusters[node_id] for node_id in subgraph
         ]
         supercluster = MergedCluster(overlapping_clusters,
                                      len(self.merged_clusters))
         self.merged_clusters[supercluster.uniqueid] = supercluster
         if self.history_nodes:
             snode = Node(supercluster.uniqueid)
             self.history_nodes[supercluster.uniqueid] = snode
             for node_id in subgraph:
                 self.history_nodes[node_id].add_child(snode)
         pdebugger.info(str('Made {}'.format(supercluster)))
 def _make_merged_clusters(self):
     #carry out the merging of linked clusters
     for subgraphids in self.subgraphs:
         subgraphids.sort()
         first = None
         supercluster =None
         snode = None
         for elemid in subgraphids :
             if not first:
                 first = elemid
                 supercluster = MergedCluster(self.clusters[elemid])
                 self.merged[supercluster.uniqueid] = supercluster;
                 if (self.history_nodes) :
                     snode = Node(supercluster.uniqueid)
                     self.history_nodes[supercluster.uniqueid] = snode 
             else:
                 thing = self.clusters[elemid]
                 supercluster += thing
             if (self.history_nodes) :
                 self.history_nodes[elemid].add_child(snode)
             pdebugger.info('Merged Cluster from {}\n'.format(self.clusters[elemid]))
         pdebugger.info(str('Made {}\n'.format(supercluster)))
Пример #16
0
 def simulate(self, ptcs, history):
     self.reset()
     self.history = history
     # import pdb; pdb.set_trace()
     for ptc in ptcs:
         if ptc.q() and ptc.pt() < 0.2 and abs(ptc.pdgid()) >= 100:
             # to avoid numerical problems in propagation (and avoid making a particle that is not used)
             continue
         pdebugger.info(str('Simulating {}'.format(ptc)))
         parent = self.history.setdefault(ptc.dagid(), Node(ptc.dagid()))
         if ptc.pdgid() == 22:
             self.simulate_photon(ptc)
         elif abs(ptc.pdgid()) == 11:  #check with colin
             # self.propagate_electron(ptc)
             self.simulate_electron(ptc)
         elif abs(ptc.pdgid()) == 13:  #check with colin
             # self.propagate_muon(ptc)
             self.simulate_muon(ptc)
         elif abs(ptc.pdgid()) in [12, 14, 16]:
             self.simulate_neutrino(ptc)
         elif abs(ptc.pdgid()) > 100:  #TODO make sure this is ok
             self.simulate_hadron(ptc)
         self.ptcs.append(ptc)
         self.simulated_particles[ptc.dagid()] = ptc
Пример #17
0
 def add_particle(self, uid, pdgid):
     particle = Particle(uid, pdgid)
     uniqueid = particle.uniqueid
     self.event.sim_particles[uniqueid] = particle
     self.event.history[uniqueid] = Node(uniqueid)
Пример #18
0
    def test_papasevent(self):

        #create a dummy papasevent
        papasevent = PapasEvent(0)

        ecals = dict()
        tracks = dict()
        mixed = dict()

        for i in range(0, 2):
            uid = Identifier.make_id(Identifier.PFOBJECTTYPE.ECALCLUSTER, 't',
                                     4.5)
            ecals[uid] = uid
            papasevent.history[uid] = Node(uid)
            uidt = Identifier.make_id(Identifier.PFOBJECTTYPE.TRACK, 's', 4.5)
            tracks[uidt] = uidt
            papasevent.history[uidt] = Node(uidt)
            papasevent.history[uidt].add_child(papasevent.history[uid])

        lastid = Identifier.make_id(Identifier.PFOBJECTTYPE.ECALCLUSTER, 't',
                                    3)
        ecals[lastid] = lastid
        papasevent.history[lastid] = Node(lastid)
        papasevent.add_collection(ecals)
        papasevent.add_collection(tracks)

        #create HistoryHelper
        hhelper = HistoryHelper(papasevent)

        #get all ids in event
        ids = hhelper.event_ids()
        self.assertTrue(len(ids) == 5)

        #check id_from_pretty
        self.assertTrue(hhelper.id_from_pretty('et5') == lastid)

        #check get_linked_ids

        linked = hhelper.get_linked_ids(
            lastid)  #everything linked to lastid (which is just lastid)
        self.assertTrue(linked[0] == lastid and len(linked) == 1)
        self.assertTrue(
            hhelper.get_linked_ids(ids[0], direction="undirected")[1] ==
            hhelper.id_from_pretty('ts2'))
        self.assertTrue(
            hhelper.get_linked_ids(ids[0], direction="parents") ==
            hhelper.get_linked_ids(ids[0], direction="undirected"))
        self.assertTrue(
            hhelper.get_linked_ids(ids[0], direction="children") ==
            [hhelper.id_from_pretty('et1')])

        #filter_ids
        self.assertTrue(len(hhelper.filter_ids(ids, 'ts')) == 2)
        self.assertTrue(hhelper.filter_ids(ids, 'no') == [])

        #get_collection
        self.assertTrue(len(hhelper.get_collection(ids[1:2], 'no')) == 0)
        self.assertTrue(len(hhelper.get_collection([99], 'no')) == 0)
        self.assertTrue(len(hhelper.get_collection(ids[0:2], 'ts')) == 1)
        pass

        #get_history_subgroups
        subgroups = hhelper.get_history_subgroups()
        self.assertTrue(len(subgroups) == 3)

        #get_linked_collection
        self.assertTrue(
            hhelper.get_linked_collection(hhelper.id_from_pretty(
                'et1'), 'ts').keys() == [hhelper.id_from_pretty('ts2')])
        self.assertRaises(KeyError, hhelper.get_linked_collection, 0, 'ts')
        self.assertTrue(
            len(
                hhelper.get_linked_collection(hhelper.id_from_pretty('et1'),
                                              'no')) == 0)
Пример #19
0
 def add_nodes(self, nodedict, values):
     for e1 in values:
         nodedict[e1.uniqueid] = Node(e1.uniqueid)
Пример #20
0
 def add_track(self, uid):
     track = Track(uid)
     uniqueid = track.uniqueid
     self.event.tracks[uniqueid] = track
     self.event.history[uniqueid] = Node(uniqueid)
Пример #21
0
 def add_hcal_cluster(self, uid):
     clust = Cluster(uid, 'hcal_in')
     uniqueid = clust.uniqueid
     self.event.hcal_clusters[uniqueid] = clust
     self.event.history[uniqueid] = Node(uniqueid)