Пример #1
0
    def simulate(self, ptcs):
        self.reset()
        self.ptcs = []

        #newsort
        # import pdb; pdb.set_trace()
        for gen_ptc in sorted(ptcs, key=lambda ptc: ptc.uniqueid):
            pdebugger.info(str('{}'.format(gen_ptc)))
        for gen_ptc in ptcs:
            ptc = pfsimparticle(gen_ptc)
            if ptc.pdgid() == 22:
                self.simulate_photon(ptc)
            elif abs(ptc.pdgid()) == 11:  #check with colin
                self.propagate_electron(ptc)
                #smeared_ptc = self.smear_electron(ptc)
                #smeared.append(smeared_ptc)
                # self.simulate_electron(ptc)
            elif abs(ptc.pdgid()) == 13:  #check with colin
                self.propagate_muon(ptc)
                #smeared_ptc = self.smear_muon(ptc)
                #smeared.append(smeared_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
                if ptc.q() and ptc.pt() < 0.2:
                    # to avoid numerical problems in propagation
                    continue
                self.simulate_hadron(ptc)
            self.ptcs.append(ptc)
        self.pfinput = PFInput(
            self.ptcs
        )  #collect up tracks, clusters etc ready for merging/reconstruction_muon(otc)
Пример #2
0
    def make_cluster(self, ptc, detname, fraction=1., size=None):
        '''adds a cluster in a given detector, with a given fraction of
        the particle energy.'''
        detector = self.detector.elements[detname]
        propagator(ptc.q()).propagate_one(
            ptc, detector.volume.inner,
            self.detector.elements['field'].magnitude)
        if size is None:
            size = detector.cluster_size(ptc)
        cylname = detector.volume.inner.name
        if not cylname in ptc.points:
            # TODO Colin particle was not extrapolated here...
            # issue must be solved!
            errormsg = '''
SimulationError : cannot make cluster for particle: 
particle: {ptc}
with vertex rho={rho:5.2f}, z={zed:5.2f}
cannot be extrapolated to : {det}\n'''.format(ptc=ptc,
                                              rho=ptc.vertex.Perp(),
                                              zed=ptc.vertex.Z(),
                                              det=detector.volume.inner)
            self.logger.warning(errormsg)
            raise SimulationError(
                'Particle not extrapolated to the detector, so cannot make a cluster there. No worries for now, problem will be solved :-)'
            )
        cluster = Cluster(ptc.p4().E() * fraction, ptc.points[cylname], size,
                          cylname, ptc)
        ptc.clusters[cylname] = cluster
        pdebugger.info(" ".join(("Made", cluster.__str__())))
        return cluster
Пример #3
0
 def make_and_store_smeared_cluster(self, cluster, detector, accept=False, acceptance=None):
     '''Returns a copy of cluster, after a gaussian smearing of the energy.
     
     The smeared cluster is stored for further processing.
     
     @param cluster: the cluster to be smeared.
     @param detector: detector object from which the energy resolution, energy response
       and acceptance parametrizations are taken.
     @param accept: if set to true, always accept the cluster after smearing
     @param acceptance: optional detedctor object for acceptance.
       if provided, and if accept is False, used in place of detector.acceptance
     '''
     eres = detector.energy_resolution(cluster.energy, cluster.position.Eta())
     response = detector.energy_response(cluster.energy, cluster.position.Eta())
     energy = cluster.energy * random.gauss(response, eres)
     clusters = self.cluster_collection(cluster.layer, smeared=True)
     smeared_cluster = SmearedCluster(cluster,
                                      energy,
                                      cluster.position,
                                      cluster.size(),
                                      cluster.layer,
                                      len(clusters),
                                      cluster.particle)
     pdebugger.info(str('Made {}'.format(smeared_cluster)))
     det = acceptance if acceptance else detector
     if det.acceptance(smeared_cluster) or accept:
         clusters[smeared_cluster.uniqueid] = smeared_cluster                      
         self.update_history(cluster.uniqueid, smeared_cluster.uniqueid)
         return smeared_cluster
     else:
         pdebugger.info(str('Rejected {}'.format(smeared_cluster)))
         return None
Пример #4
0
 def reconstruct_cluster(self, cluster, layer, energy = None, vertex = None):
     '''construct a photon if it is an ecal
        construct a neutral hadron if it is an hcal
     '''        
     if vertex is None:
         vertex = TVector3()
     pdg_id = None
     if layer=='ecal_in':
         pdg_id = 22 #photon
     elif layer=='hcal_in':
         pdg_id = 130 #K0
     else:
         raise ValueError('layer must be equal to ecal_in or hcal_in')
     assert(pdg_id)
     mass, charge = particle_data[pdg_id]
     if energy is None:
         energy = cluster.energy
     if energy < mass: 
         return None 
     if (mass==0):
         momentum= energy #avoid sqrt for zero mass
     else:
         momentum = math.sqrt(energy**2 - mass**2)
     p3 = cluster.position.Unit() * momentum
     p4 = TLorentzVector(p3.Px(), p3.Py(), p3.Pz(), energy) #mass is not accurate here
     particle = Particle(p4, vertex, charge, pdg_id, Identifier.PFOBJECTTYPE.RECPARTICLE)
     path = StraightLine(p4, vertex)
     path.points[layer] = cluster.position #alice: this may be a bit strange because we can make a photon with a path where the point is actually that of the hcal?
                                         # nb this only is problem if the cluster and the assigned layer are different
     particle.set_path(path)
     particle.clusters[layer] = cluster  # not sure about this either when hcal is used to make an ecal cluster?
     self.locked[cluster.uniqueid] = True #just OK but not nice if hcal used to make ecal.
     pdebugger.info(str('Made {} from {}'.format(particle,  cluster)))
     return particle
Пример #5
0
    def make_cluster(self, ptc, detname, fraction=1.0, size=None):
        """adds a cluster in a given detector, with a given fraction of
        the particle energy."""
        detector = self.detector.elements[detname]
        propagator(ptc.q()).propagate_one(ptc, detector.volume.inner, self.detector.elements["field"].magnitude)
        if size is None:
            size = detector.cluster_size(ptc)
        cylname = detector.volume.inner.name
        if not cylname in ptc.points:
            # TODO Colin particle was not extrapolated here...
            # issue must be solved!
            errormsg = """
SimulationError : cannot make cluster for particle: 
particle: {ptc}
with vertex rho={rho:5.2f}, z={zed:5.2f}
cannot be extrapolated to : {det}\n""".format(
                ptc=ptc, rho=ptc.vertex.Perp(), zed=ptc.vertex.Z(), det=detector.volume.inner
            )
            self.logger.warning(errormsg)
            raise SimulationError(
                "Particle not extrapolated to the detector, so cannot make a cluster there. No worries for now, problem will be solved :-)"
            )
        cluster = Cluster(ptc.p4().E() * fraction, ptc.points[cylname], size, cylname, ptc)
        ptc.clusters[cylname] = cluster
        pdebugger.info(" ".join(("Made", cluster.__str__())))
        return cluster
Пример #6
0
    def make_and_store_cluster(self, ptc, detname, fraction=1., size=None):
        '''adds a cluster in a given detector, with a given fraction of
        the particle energy.
        Stores the cluster in the appropriate collection and records cluster in the history'''
        detector = self.detector.elements[detname]
        propagator(ptc.q()).propagate_one(ptc,
                                          detector.volume.inner,
                                          self.detector.elements['field'].magnitude)
        if size is None:
            size = detector.cluster_size(ptc)
        cylname = detector.volume.inner.name
        if not cylname in ptc.points:
            # TODO Colin particle was not extrapolated here...
            # issue must be solved!
            errormsg = '''
SimulationError : cannot make cluster for particle: 
particle: {ptc}
with vertex rho={rho:5.2f}, z={zed:5.2f}
cannot be extrapolated to : {det}\n'''.format(ptc=ptc,
                                              rho=ptc.vertex.Perp(),
                                              zed=ptc.vertex.Z(),
                                              det=detector.volume.inner)
            self.logger.warning(errormsg)
            raise SimulationError('Particle not extrapolated to the detector, so cannot make a cluster there. No worries for now, problem will be solved :-)')
        clusters = self.cluster_collection(cylname)
        cluster = Cluster(ptc.p4().E()*fraction, ptc.points[cylname], size, cylname, len(clusters), ptc)
        #update collections and history
        ptc.clusters[cylname] = cluster
        clusters[cluster.uniqueid] = cluster 
        self.update_history(ptc.uniqueid, cluster.uniqueid,)          
        pdebugger.info(" ".join(("Made", cluster.__str__())))
        return cluster
Пример #7
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)))
         # 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
Пример #8
0
 def simulate_muon(self, ptc):
     pdebugger.info("Simulating Muon")
     self.propagate(ptc)
     smeared_track = self.smear_track(ptc.track,
                                      self.detector.elements['tracker'])
     if smeared_track:
         ptc.track_smeared = smeared_track
Пример #9
0
 def smear_muon(self, ptc):
     pdebugger.info("Smearing Muon")
     self.propagate(ptc)
     if ptc.q() != 0:
         pdebugger.info(" ".join(("Made", ptc.track.__str__())))
     smeared = copy.deepcopy(ptc)
     return smeared
Пример #10
0
    def simulate(self, ptcs):
        self.reset()
        self.ptcs = []

        # newsort
        # import pdb; pdb.set_trace()
        for gen_ptc in sorted(ptcs, key=lambda ptc: ptc.uniqueid):
            pdebugger.info(str("{}".format(gen_ptc)))
        for gen_ptc in ptcs:
            ptc = pfsimparticle(gen_ptc)
            if ptc.pdgid() == 22:
                self.simulate_photon(ptc)
            elif abs(ptc.pdgid()) == 11:  # check with colin
                self.propagate_electron(ptc)
                # smeared_ptc = self.smear_electron(ptc)
                # smeared.append(smeared_ptc)
                # self.simulate_electron(ptc)
            elif abs(ptc.pdgid()) == 13:  # check with colin
                self.propagate_muon(ptc)
                # smeared_ptc = self.smear_muon(ptc)
                # smeared.append(smeared_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
                if ptc.q() and ptc.pt() < 0.2:
                    # to avoid numerical problems in propagation
                    continue
                self.simulate_hadron(ptc)
            self.ptcs.append(ptc)
        self.pfinput = PFInput(self.ptcs)  # collect up tracks, clusters etc ready for merging/reconstruction_muon(otc)
Пример #11
0
 def make_and_store_smeared_cluster(self, cluster, detector, accept=False, acceptance=None):
     '''Returns a copy of cluster, after a gaussian smearing of the energy.
     
     The smeared cluster is stored for further processing.
     
     @param cluster: the cluster to be smeared.
     @param detector: detector object from which the energy resolution, energy response
       and acceptance parametrizations are taken.
     @param accept: if set to true, always accept the cluster after smearing
     @param acceptance: optional detedctor object for acceptance.
       if provided, and if accept is False, used in place of detector.acceptance
     '''
     eres = detector.energy_resolution(cluster.energy, cluster.position.Eta())
     response = detector.energy_response(cluster.energy, cluster.position.Eta())
     energy = cluster.energy * random.gauss(response, eres)
     clusters = self.cluster_collection(cluster.layer, smeared=True)
     smeared_cluster = SmearedCluster(cluster,
                                      energy,
                                      cluster.position,
                                      cluster.size(),
                                      cluster.layer,
                                      len(clusters),
                                      cluster.particle)
     pdebugger.info(str('Made {}'.format(smeared_cluster)))
     det = acceptance if acceptance else detector
     if det.acceptance(smeared_cluster) or accept:
         clusters[smeared_cluster.uniqueid] = smeared_cluster                      
         self.update_history(cluster.uniqueid, smeared_cluster.uniqueid)            
         return smeared_cluster
     else:
         pdebugger.info(str('Rejected {}'.format(smeared_cluster)))
         return None
Пример #12
0
 def smear_muon(self, ptc):
     pdebugger.info("Smearing Muon")
     self.propagate(ptc)
     if ptc.q() != 0:
         pdebugger.info(" ".join(("Made", ptc.track.__str__())))
     smeared = copy.deepcopy(ptc)
     return smeared
Пример #13
0
 def make_and_store_smeared_cluster(self,
                                    cluster,
                                    detector,
                                    accept=False,
                                    acceptance=None):
     '''Returns a copy of self with a smeared energy.
     If accept is False (default), returns None if the smeared
     cluster is not in the detector acceptance. '''
     eres = detector.energy_resolution(cluster.energy,
                                       cluster.position.Eta())
     response = detector.energy_response(cluster.energy,
                                         cluster.position.Eta())
     energy = cluster.energy * random.gauss(response, eres)
     clusters = self.smeared_cluster_collection(cluster.layer)
     smeared_cluster = SmearedCluster(cluster, energy, cluster.position,
                                      cluster.size(), cluster.layer,
                                      len(clusters), cluster.particle)
     pdebugger.info(str('Made {}'.format(smeared_cluster)))
     det = acceptance if acceptance else detector
     if det.acceptance(smeared_cluster) or accept:
         clusters[smeared_cluster.uniqueid] = smeared_cluster
         self.update_history(cluster.uniqueid, smeared_cluster.uniqueid)
         return smeared_cluster
     else:
         pdebugger.info(str('Rejected {}'.format(smeared_cluster)))
         return None
Пример #14
0
 def propagate_electron(self, ptc):
     pdebugger.info("Propogate Electron")
     ecal = self.detector.elements['ecal']
     propagator(ptc.q()).propagate_one(ptc,
                                       ecal.volume.inner,
                                       self.detector.elements['field'].magnitude)
     return
Пример #15
0
 def reconstruct_track(
     self,
     track,
     pdgid,
     parent_ids,
     clusters=None
 ):  # cluster argument does not ever seem to be used at present
     '''construct a charged hadron from the track
     '''
     if self.locked[track.uniqueid]:
         return
     vertex = track.path.points['vertex']
     pdgid = pdgid * track.charge
     mass, charge = particle_data[pdgid]
     p4 = TLorentzVector()
     p4.SetVectM(track.p3(), mass)
     particle = Particle(p4,
                         vertex,
                         charge,
                         pdgid,
                         len(self.particles),
                         subtype='r')
     #todo fix this so it picks up smeared track points (need to propagagte smeared track)
     particle.set_track(
         track)  #refer to existing track rather than make a new one
     self.locked[track.uniqueid] = True
     pdebugger.info(str('Made {} from {}'.format(particle, track)))
     self.insert_particle(parent_ids, particle)
     return particle
Пример #16
0
 def simulate_electron(self, ptc):
     '''Simulate an electron corresponding to gen particle ptc.
     
     Uses the methods detector.electron_energy_resolution
     and detector.electron_acceptance to smear the electron track.
     Later on, the particle flow algorithm will use the tracks
     coming from an electron to reconstruct electrons.
     
     This method does not simulate an electron energy deposit in the ECAL.
     '''
     pdebugger.info("Simulating Electron")
     ecal = self.detector.elements['ecal']
     track = self.make_and_store_track(ptc)
     propagator(ptc.q()).propagate_one(
         ptc,
         ecal.volume.inner,
         self.detector.elements['field'].magnitude
     )
     eres = self.detector.electron_energy_resolution(ptc)
     smeared_track = self.make_smeared_track(track, eres)
     if self.detector.electron_acceptance(smeared_track):
             self.smeared_tracks[smeared_track.uniqueid] = smeared_track
             self.update_history(track.uniqueid, smeared_track.uniqueid)  
             ptc.track_smeared = smeared_track 
     else:
         pdebugger.info(str('Rejected {}'.format(smeared_track)))
Пример #17
0
    def reconstruct(self, papasevent, block_type_and_subtype):
        '''papasevent: PapasEvent containing collections of particle flow objects 
           block_type_and_subtype: which blocks collection to use'''

        self.unused = []
        self.papasevent = papasevent
        self.history_helper = HistoryHelper(papasevent)
        self.particles = dict()
        self.splitblocks = dict()
        blocks = papasevent.get_collection(block_type_and_subtype)

        # simplify the blocks by editing the links so that each track will end up linked to at most one hcal
        # then recalculate the blocks
        for blockid in sorted(blocks.keys(),
                              reverse=True):  #big blocks come first
            pdebugger.info(str('Splitting {}'.format(blocks[blockid])))
            newblocks = self.simplify_blocks(blocks[blockid],
                                             self.papasevent.history)
            self.splitblocks.update(newblocks)

        #reconstruct each of the resulting blocks
        for b in sorted(self.splitblocks.keys(),
                        reverse=True):  #put big interesting blocks first
            sblock = self.splitblocks[b]
            pdebugger.info('Processing {}'.format(sblock))
            self.reconstruct_block(sblock)

        #check if anything is unused
        if len(self.unused):
            self.log.warning(str(self.unused))
        self.log.info("Particles:")
        self.log.info(str(self))
Пример #18
0
    def reconstruct(self, papasevent, block_type_and_subtype):
        '''papasevent: PapasEvent containing collections of particle flow objects 
           block_type_and_subtype: which blocks collection to use'''
        
        self.unused = []
        self.papasevent = papasevent
        self.history_helper = HistoryHelper(papasevent)
        self.particles = dict()
        self.splitblocks = dict()
        blocks = papasevent.get_collection(block_type_and_subtype)   
        
        # simplify the blocks by editing the links so that each track will end up linked to at most one hcal
        # then recalculate the blocks
        for blockid in sorted(blocks.keys(), reverse=True): #big blocks come first
            pdebugger.info(str('Splitting {}'.format(blocks[blockid])))
            newblocks = self.simplify_blocks(blocks[blockid], self.papasevent.history)
            self.splitblocks.update(newblocks)      
    
        #reconstruct each of the resulting blocks        
        for b in sorted(self.splitblocks.keys(), reverse=True):  #put big interesting blocks first
            sblock = self.splitblocks[b]
            pdebugger.info('Processing {}'.format(sblock))
            self.reconstruct_block(sblock)

        #check if anything is unused
        if len(self.unused):
            self.log.warning(str(self.unused))
        self.log.info("Particles:")
        self.log.info(str(self))         
Пример #19
0
 def smear_electron(self, ptc):
     pdebugger.info("Smearing Electron")
     ecal = self.detector.elements["ecal"]
     propagator(ptc.q()).propagate_one(ptc, ecal.volume.inner, self.detector.elements["field"].magnitude)
     if ptc.q() != 0:
         pdebugger.info(" ".join(("Made", ptc.track.__str__())))
     smeared = copy.deepcopy(ptc)
     return smeared
Пример #20
0
    def simulate_hadron(self, ptc):
        """Simulate a hadron, neutral or charged.
        ptc should behave as pfobjects.Particle.
        """
        pdebugger.info("Simulating Hadron")
        # implement beam pipe scattering

        ecal = self.detector.elements["ecal"]
        hcal = self.detector.elements["hcal"]
        beampipe = self.detector.elements["beampipe"]
        frac_ecal = 0.0

        propagator(ptc.q()).propagate_one(ptc, beampipe.volume.inner, self.detector.elements["field"].magnitude)

        propagator(ptc.q()).propagate_one(ptc, beampipe.volume.outer, self.detector.elements["field"].magnitude)

        mscat.multiple_scattering(ptc, beampipe, self.detector.elements["field"].magnitude)

        # re-propagate after multiple scattering in the beam pipe
        # indeed, multiple scattering is applied within the beam pipe,
        # so the extrapolation points to the beam pipe entrance and exit
        # change after multiple scattering.
        propagator(ptc.q()).propagate_one(ptc, beampipe.volume.inner, self.detector.elements["field"].magnitude)
        propagator(ptc.q()).propagate_one(ptc, beampipe.volume.outer, self.detector.elements["field"].magnitude)
        propagator(ptc.q()).propagate_one(ptc, ecal.volume.inner, self.detector.elements["field"].magnitude)

        # these lines moved earlier in order to match cpp logic
        if ptc.q() != 0:
            pdebugger.info(" ".join(("Made", ptc.track.__str__())))
            smeared_track = self.smear_track(ptc.track, self.detector.elements["tracker"])
            if smeared_track:
                ptc.track_smeared = smeared_track

        if "ecal_in" in ptc.path.points:
            # doesn't have to be the case (long-lived particles)
            path_length = ecal.material.path_length(ptc)
            if path_length < sys.float_info.max:
                # ecal path length can be infinite in case the ecal
                # has lambda_I = 0 (fully transparent to hadrons)
                time_ecal_inner = ptc.path.time_at_z(ptc.points["ecal_in"].Z())
                deltat = ptc.path.deltat(path_length)
                time_decay = time_ecal_inner + deltat
                point_decay = ptc.path.point_at_time(time_decay)
                ptc.points["ecal_decay"] = point_decay
                if ecal.volume.contains(point_decay):
                    frac_ecal = random.uniform(0.0, 0.7)
                    cluster = self.make_cluster(ptc, "ecal", frac_ecal)
                    # For now, using the hcal resolution and acceptance
                    # for hadronic cluster
                    # in the ECAL. That's not a bug!
                    smeared = self.smear_cluster(cluster, hcal, acceptance=ecal)
                    if smeared:
                        ptc.clusters_smeared[smeared.layer] = smeared

        cluster = self.make_cluster(ptc, "hcal", 1 - frac_ecal)
        smeared = self.smear_cluster(cluster, hcal)
        if smeared:
            ptc.clusters_smeared[smeared.layer] = smeared
Пример #21
0
 def reconstruct_cluster(self,
                         cluster,
                         layer,
                         parent_ids,
                         energy=None,
                         vertex=None):
     '''construct a photon if it is an ecal
        construct a neutral hadron if it is an hcal
     '''
     if self.locked[cluster.uniqueid]:
         return
     if vertex is None:
         vertex = TVector3()
     pdg_id = None
     propagate_to = None
     if layer == 'ecal_in':
         pdg_id = 22  #photon
         propagate_to = [self.detector.elements['ecal'].volume.inner]
     elif layer == 'hcal_in':
         pdg_id = 130  #K0
         propagate_to = [
             self.detector.elements['ecal'].volume.inner,
             self.detector.elements['hcal'].volume.inner
         ]
     else:
         raise ValueError('layer must be equal to ecal_in or hcal_in')
     assert (pdg_id)
     mass, charge = particle_data[pdg_id]
     if energy is None:
         energy = cluster.energy
     if energy < mass:
         return None
     if mass == 0:
         momentum = energy  #avoid sqrt for zero mass
     else:
         momentum = math.sqrt(energy**2 - mass**2)
     p3 = cluster.position.Unit() * momentum
     p4 = TLorentzVector(p3.Px(), p3.Py(), p3.Pz(),
                         energy)  #mass is not accurate here
     particle = Particle(p4,
                         vertex,
                         charge,
                         pdg_id,
                         len(self.particles),
                         subtype='r')
     # alice: this may be a bit strange because we can make a photon
     # with a path where the point is actually that of the hcal?
     # nb this only is problem if the cluster and the assigned layer
     # are different
     propagator(charge).propagate([particle], propagate_to)
     #merge Nov 10th 2016 not sure about following line (was commented out in papasevent branch)
     particle.clusters[
         layer] = cluster  # not sure about this either when hcal is used to make an ecal cluster?
     self.locked[
         cluster.
         uniqueid] = True  #just OK but not nice if hcal used to make ecal.
     pdebugger.info(str('Made {} from {}'.format(particle, cluster)))
     self.insert_particle(parent_ids, particle)
Пример #22
0
 def make_and_store_track(self, ptc):
     '''creates a new track, adds it into the true_tracks collection and
     updates the history information'''
     track = Track(ptc.p3(), ptc.q(), ptc.path, index=len(self.true_tracks))
     pdebugger.info(" ".join(("Made", track.__str__())))
     self.true_tracks[track.uniqueid] = track                     
     self.update_history(ptc.uniqueid, track.uniqueid)          
     ptc.set_track(track)
     return track
Пример #23
0
 def simulate_photon(self, ptc):
     pdebugger.info("Simulating Photon")
     detname = 'ecal'
     ecal = self.detector.elements[detname]
     propagator(ptc.q()).propagate_one(ptc, ecal.volume.inner)
     cluster = self.make_and_store_cluster(ptc, detname)
     smeared = self.make_and_store_smeared_cluster(cluster, ecal)
     if smeared:
         ptc.clusters_smeared[smeared.layer] = smeared
Пример #24
0
 def make_and_store_track(self, ptc):
     '''creates a new track, adds it into the true_tracks collection and
     updates the history information'''
     track = Track(ptc.p3(), ptc.q(), ptc.path, index=len(self.true_tracks))
     pdebugger.info(" ".join(("Made", track.__str__())))
     self.true_tracks[track.uniqueid] = track
     self.update_history(ptc.uniqueid, track.uniqueid)
     ptc.set_track(track)
     return track
Пример #25
0
 def smear_electron(self, ptc):
     pdebugger.info("Smearing Electron")
     ecal = self.detector.elements['ecal']
     propagator(ptc.q()).propagate_one(
         ptc, ecal.volume.inner, self.detector.elements['field'].magnitude)
     if ptc.q() != 0:
         pdebugger.info(" ".join(("Made", ptc.track.__str__())))
     smeared = copy.deepcopy(ptc)
     return smeared
Пример #26
0
    def simulate_photon(self, ptc):
        pdebugger.info("Simulating Photon")
        detname = "ecal"
        ecal = self.detector.elements[detname]
        propagator(ptc.q()).propagate_one(ptc, ecal.volume.inner)

        cluster = self.make_cluster(ptc, detname)
        smeared = self.smear_cluster(cluster, ecal)
        if smeared:
            ptc.clusters_smeared[smeared.layer] = smeared
Пример #27
0
 def simulate_electron(self, ptc):
     pdebugger.info("Simulating Electron")
     ecal = self.detector.elements["ecal"]
     propagator(ptc.q()).propagate_one(ptc, ecal.volume.inner, self.detector.elements["field"].magnitude)
     cluster = self.make_cluster(ptc, "ecal")
     smeared_cluster = self.smear_cluster(cluster, ecal)
     if smeared_cluster:
         ptc.clusters_smeared[smeared_cluster.layer] = smeared_cluster
     smeared_track = self.smear_track(ptc.track, self.detector.elements["tracker"])
     if smeared_track:
         ptc.track_smeared = smeared_track
Пример #28
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, index, pid)
     pdebugger.info(" ".join(("Made", simptc.__str__())))
     simptc.gen_ptc = ptc
     return simptc
Пример #29
0
 def make_smeared_track(self, track, resolution):
     '''create a new smeared track'''
     #TODO smearing depends on particle type!
     scale_factor = random.gauss(1, resolution)
     smeared_track = SmearedTrack(track,
                                  track.p3 * scale_factor,
                                  track.charge,
                                  track.path,
                                  index = len(self.smeared_tracks))
     pdebugger.info(" ".join(("Made", smeared_track.__str__())))
     return smeared_track  
Пример #30
0
 def smear_track(self, track, detector, accept=False):
     # TODO smearing depends on particle type!
     ptres = detector.pt_resolution(track)
     scale_factor = random.gauss(1, ptres)
     smeared_track = SmearedTrack(track, track.p3 * scale_factor, track.charge, track.path)
     pdebugger.info(" ".join(("Made", smeared_track.__str__())))
     if detector.acceptance(smeared_track) or accept:
         return smeared_track
     else:
         pdebugger.info(str("Rejected {}".format(smeared_track)))
         return None
Пример #31
0
 def make_smeared_track(self, track, resolution):
     '''create a new smeared track'''
     #TODO smearing depends on particle type!
     scale_factor = random.gauss(1, resolution)
     smeared_track = SmearedTrack(track,
                                  track.p3 * scale_factor,
                                  track.charge,
                                  track.path,
                                  index=len(self.smeared_tracks))
     pdebugger.info(" ".join(("Made", smeared_track.__str__())))
     return smeared_track
Пример #32
0
def pfsimparticle(ptc):
    '''Create a PFSimParticle from a particle.
    The PFSimParticle will have the same p4, vertex, charge, pdg ID.
    '''
    tp4 = ptc.p4()
    vertex = ptc.start_vertex().position()
    charge = ptc.q()
    pid = ptc.pdgid()
    simptc = PFSimParticle(tp4, vertex, charge, pid)
    pdebugger.info(" ".join(("Made", simptc.__str__())))
    simptc.gen_ptc = ptc
    return simptc
Пример #33
0
 def smear_track(self, track, detector, accept=False):
     #TODO smearing depends on particle type!
     ptres = detector.pt_resolution(track)
     scale_factor = random.gauss(1, ptres)
     smeared_track = SmearedTrack(track, track.p3 * scale_factor,
                                  track.charge, track.path)
     pdebugger.info(" ".join(("Made", smeared_track.__str__())))
     if detector.acceptance(smeared_track) or accept:
         return smeared_track
     else:
         pdebugger.info(str('Rejected {}'.format(smeared_track)))
         return None
Пример #34
0
def pfsimparticle(ptc):
    """Create a PFSimParticle from a particle.
    The PFSimParticle will have the same p4, vertex, charge, pdg ID.
    """
    tp4 = ptc.p4()
    vertex = ptc.start_vertex().position()
    charge = ptc.q()
    pid = ptc.pdgid()
    simptc = PFSimParticle(tp4, vertex, charge, pid)
    pdebugger.info(" ".join(("Made", simptc.__str__())))
    simptc.gen_ptc = ptc
    return simptc
Пример #35
0
 def simulate_electron(self, ptc):
     pdebugger.info("Simulating Electron")
     ecal = self.detector.elements['ecal']
     propagator(ptc.q()).propagate_one(
         ptc, ecal.volume.inner, self.detector.elements['field'].magnitude)
     cluster = self.make_cluster(ptc, 'ecal')
     smeared_cluster = self.smear_cluster(cluster, ecal)
     if smeared_cluster:
         ptc.clusters_smeared[smeared_cluster.layer] = smeared_cluster
     smeared_track = self.smear_track(ptc.track,
                                      self.detector.elements['tracker'])
     if smeared_track:
         ptc.track_smeared = smeared_track
Пример #36
0
 def reconstruct_track(self, track, clusters=None):  # cluster argument does not ever seem to be used at present
     """construct a charged hadron from the track
     """
     vertex = track.path.points["vertex"]
     pdg_id = 211 * track.charge
     mass, charge = particle_data[pdg_id]
     p4 = TLorentzVector()
     p4.SetVectM(track.p3, mass)
     particle = Particle(p4, vertex, charge, pdg_id, Identifier.PFOBJECTTYPE.RECPARTICLE)
     particle.set_path(track.path)
     particle.clusters = clusters
     self.locked[track.uniqueid] = True
     pdebugger.info(str("Made {} from {}".format(particle, track)))
     return particle
Пример #37
0
 def reconstruct_track(self, track, clusters = None): # cluster argument does not ever seem to be used at present
     '''construct a charged hadron from the track
     '''
     vertex = track.path.points['vertex']
     pdg_id = 211 * track.charge
     mass, charge = particle_data[pdg_id]
     p4 = TLorentzVector()
     p4.SetVectM(track.p3, mass)
     particle = Particle(p4, vertex, charge, pdg_id, Identifier.PFOBJECTTYPE.RECPARTICLE)
     particle.set_path(track.path)
     particle.clusters = clusters
     self.locked[track.uniqueid] = True
     pdebugger.info(str('Made {} from {}'.format(particle,  track)))
     return particle
Пример #38
0
 def simulate_hadron(self, ptc):
     '''Simulate a hadron, neutral or charged.
     ptc should behave as pfobjects.Particle.
     '''
     pdebugger.info("Simulating Hadron")
     
     #implement beam pipe scattering
     ecal = self.detector.elements['ecal']
     hcal = self.detector.elements['hcal']
     frac_ecal = 0.
     if ptc.q() != 0 :
         #track is now made outside of the particle and then the particle is told where the track is
         track = self.make_and_store_track(ptc)
         tracker = self.detector.elements['tracker']
         smeared_track = self.make_and_store_smeared_track(
             ptc, 
             track, 
             tracker.resolution,
             tracker.acceptance
         )
     propagator(ptc.q()).propagate_one(ptc,
                                       ecal.volume.inner,
                                       self.detector.elements['field'].magnitude)
     
     if 'ecal_in' in ptc.path.points:
         # doesn't have to be the case (long-lived particles)
         path_length = ecal.material.path_length(ptc)
         if path_length < sys.float_info.max:
             # ecal path length can be infinite in case the ecal
             # has lambda_I = 0 (fully transparent to hadrons)
             time_ecal_inner = ptc.path.time_at_z(ptc.points['ecal_in'].Z())
             deltat = ptc.path.deltat(path_length)
             time_decay = time_ecal_inner + deltat
             point_decay = ptc.path.point_at_time(time_decay)
             ptc.points['ecal_decay'] = point_decay
             if ecal.volume.contains(point_decay):
                 frac_ecal = random.uniform(0., 0.7)
                 cluster = self.make_and_store_cluster(ptc, 'ecal', frac_ecal)
                 # For now, using the hcal resolution and acceptance
                 # for hadronic cluster
                 # in the ECAL. That's not a bug!
                 smeared = self.make_and_store_smeared_cluster(cluster, hcal, acceptance=ecal)
                 if smeared:
                     ptc.clusters_smeared[smeared.layer] = smeared
     cluster = self.make_and_store_cluster(ptc, 'hcal', 1-frac_ecal)
     smeared = self.make_and_store_smeared_cluster(cluster, hcal)
     if smeared:
         ptc.clusters_smeared[smeared.layer] = smeared
Пример #39
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
Пример #40
0
 def simulate_muon(self, ptc):
     '''Simulate a muon corresponding to gen particle ptc
     
     Uses the methods detector.muon_energy_resolution
     and detector.muon_acceptance to smear the muon track.
     Later on, the particle flow algorithm will use the tracks
     coming from a muon to reconstruct muons.
     
     This method does not simulate energy deposits in the calorimeters
     '''
     pdebugger.info("Simulating Muon")
     track = self.make_and_store_track(ptc)
     self.propagate(ptc)
     smeared_track = self.make_and_store_smeared_track(
         ptc, track, self.detector.muon_resolution,
         self.detector.muon_acceptance)
Пример #41
0
 def reconstruct_cluster(self, cluster, layer, parent_ids,
                         energy=None, vertex=None):
     '''construct a photon if it is an ecal
        construct a neutral hadron if it is an hcal
     '''
     if self.locked[cluster.uniqueid]:
         return 
     if vertex is None:
         vertex = TVector3()
     pdg_id = None
     propagate_to = None
     if layer=='ecal_in':
         pdg_id = 22 #photon
         propagate_to = [ self.detector.elements['ecal'].volume.inner ]
     elif layer=='hcal_in':
         pdg_id = 130 #K0
         propagate_to = [ self.detector.elements['ecal'].volume.inner,
                          self.detector.elements['hcal'].volume.inner ]
     else:
         raise ValueError('layer must be equal to ecal_in or hcal_in')
     assert(pdg_id)
     mass, charge = particle_data[pdg_id]
     if energy is None:
         energy = cluster.energy
     if energy < mass: 
         return None 
     if mass == 0:
         momentum = energy #avoid sqrt for zero mass
     else:
         momentum = math.sqrt(energy**2 - mass**2)
     p3 = cluster.position.Unit() * momentum
     p4 = TLorentzVector(p3.Px(), p3.Py(), p3.Pz(), energy) #mass is not accurate here
     particle = Particle(p4, vertex, charge, pdg_id)
     particle.set_dagid(IdCoder.make_id(IdCoder.PFOBJECTTYPE.PARTICLE, len(self.particles), 'r', particle.idvalue))
     
     # alice: this may be a bit strange because we can make a photon 
     # with a path where the point is actually that of the hcal?
     # nb this only is problem if the cluster and the assigned layer 
     # are different
     propagator(charge).propagate([particle],
                                  propagate_to)
     #merge Nov 10th 2016 not sure about following line (was commented out in papasevent branch)
     particle.clusters[layer] = cluster  # not sure about this either when hcal is used to make an ecal cluster?
     self.locked[cluster.uniqueid] = True #just OK but not nice if hcal used to make ecal.
     pdebugger.info(str('Made {} from {}'.format(particle, cluster)))
     self.insert_particle(parent_ids, particle)        
Пример #42
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)))
Пример #43
0
 def reconstruct_track(self, track, pdgid, parent_ids,
                       clusters=None): # cluster argument does not ever seem to be used at present
     '''construct a charged hadron from the track
     '''
     if self.locked[track.uniqueid]:
         return 
     vertex = track.path.points['vertex']
     pdgid = pdgid * track.charge
     mass, charge = particle_data[pdgid]
     p4 = TLorentzVector()
     p4.SetVectM(track.p3, mass)
     particle = Particle(p4, vertex, charge, len(self.particles), pdgid,  subtype='r')
     #todo fix this so it picks up smeared track points (need to propagagte smeared track)
     particle.set_track(track) #refer to existing track rather than make a new one
     self.locked[track.uniqueid] = True
     pdebugger.info(str('Made {} from {}'.format(particle, track)))
     self.insert_particle(parent_ids, particle)
     return particle
Пример #44
0
 def simulate_electron(self, ptc):
     '''Simulate an electron corresponding to gen particle ptc.
     
     Uses the methods detector.electron_energy_resolution
     and detector.electron_acceptance to smear the electron track.
     Later on, the particle flow algorithm will use the tracks
     coming from an electron to reconstruct electrons.
     
     This method does not simulate an electron energy deposit in the ECAL.
     '''
     pdebugger.info("Simulating Electron")
     ecal = self.detector.elements['ecal']
     track = self.make_and_store_track(ptc)
     propagator(ptc.q()).propagate_one(
         ptc, ecal.volume.inner, self.detector.elements['field'].magnitude)
     smeared_track = self.make_and_store_smeared_track(
         ptc, track, self.detector.electron_resolution,
         self.detector.electron_acceptance)
Пример #45
0
    def smear_cluster(self, cluster, detector, accept=False, acceptance=None):
        """Returns a copy of self with a smeared energy.
        If accept is False (default), returns None if the smeared
        cluster is not in the detector acceptance. """

        eres = detector.energy_resolution(cluster.energy, cluster.position.Eta())
        response = detector.energy_response(cluster.energy, cluster.position.Eta())
        energy = cluster.energy * random.gauss(response, eres)
        smeared_cluster = SmearedCluster(
            cluster, energy, cluster.position, cluster.size(), cluster.layer, cluster.particle
        )
        pdebugger.info(str("Made {}".format(smeared_cluster)))
        det = acceptance if acceptance else detector
        if det.acceptance(smeared_cluster) or accept:
            return smeared_cluster
        else:
            pdebugger.info(str("Rejected {}".format(smeared_cluster)))
            return None
Пример #46
0
 def simulate_muon(self, ptc):
     '''Simulate a muon corresponding to gen particle ptc
     
     Uses the methods detector.muon_energy_resolution
     and detector.muon_acceptance to smear the muon track.
     Later on, the particle flow algorithm will use the tracks
     coming from a muon to reconstruct muons.
     
     This method does not simulate energy deposits in the calorimeters
     '''
     pdebugger.info("Simulating Muon")  
     track = self.make_and_store_track(ptc)
     self.propagate(ptc)
     smeared_track = self.make_and_store_smeared_track(
         ptc, track,
         self.detector.muon_resolution,
         self.detector.muon_acceptance
     )
Пример #47
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)
Пример #48
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)
Пример #49
0
 def reconstruct(self, event,  blocksname, historyname):
     '''arguments event: should contain blocks and optionally history_nodes'''
     self.blocks = getattr(event,  blocksname)
     self.unused = []
     self.particles = dict()
     
     
     # history nodes will be used to connect reconstructed particles into the history
     # its optional at the moment
     if hasattr(event, historyname):
         self.history_nodes = event.history_nodes
     else : 
         self.history_nodes = None
     
     # simplify the blocks by editing the links so that each track will end up linked to at most one hcal
     # then recalculate the blocks
     splitblocks=dict() 
     
     for block in self._sorted_block_keys(): #put big interesting blocks first
         #print "block: ", len(self.blocks[block]),  self.blocks[block].short_name();
         newblocks=self.simplify_blocks(self.blocks[block], self.history_nodes)
         if newblocks != None:
             splitblocks.update( newblocks)      
     if len(splitblocks):
         self.blocks.update(splitblocks)
     
         
     #reconstruct each of the resulting blocks        
     for b in self._sorted_block_keys():  #put big interesting blocks first
         block=self.blocks[b]
         if block.is_active: # when blocks are split the original gets deactivated                
             #ALICE debugging
             #if len(block.element_uniqueids)<6:
             #    continue
             pdebugger.info('Processing {}'.format(block))
             self.reconstruct_block(block)                
             self.unused.extend( [id for id in block.element_uniqueids if not self.locked[id]])
             
     #check if anything is unused
     if len(self.unused):
         self.log.warning(str(self.unused))
     self.log.info("Particles:")
     self.log.info(str(self))        
Пример #50
0
 def make_and_store_smeared_track(self, ptc, track,
                                  detector_resolution, detector_acceptance):
     '''create a new smeared track'''
     #TODO smearing depends on particle type!
     resolution = detector_resolution(track)
     scale_factor = random.gauss(1, resolution)
     smeared_track = SmearedTrack(track,
                                  track._p3 * scale_factor,
                                  track.charge,
                                  track.path,
                                  index = len(self.smeared_tracks))
     pdebugger.info(" ".join(("Made", smeared_track.__str__())))
     if detector_acceptance(track):
         self.smeared_tracks[smeared_track.uniqueid] = smeared_track
         self.update_history(track.uniqueid, smeared_track.uniqueid)   
         ptc.track_smeared = smeared_track             
         return smeared_track  
     else:
         pdebugger.info(str('Rejected {}'.format(smeared_track)))
         return None
Пример #51
0
 def make_and_store_smeared_track(self, ptc, track,
                                  detector_resolution, detector_acceptance):
     '''create a new smeared track'''
     #TODO smearing depends on particle type!
     resolution = detector_resolution(ptc)
     scale_factor = random.gauss(1, resolution)
     smeared_track = SmearedTrack(track,
                                  track.p3 * scale_factor,
                                  track.charge,
                                  track.path,
                                  index = len(self.smeared_tracks))
     pdebugger.info(" ".join(("Made", smeared_track.__str__())))
     if detector_acceptance(smeared_track):
         self.smeared_tracks[smeared_track.uniqueid] = smeared_track
         self.update_history(track.uniqueid, smeared_track.uniqueid )   
         ptc.track_smeared = smeared_track             
         return smeared_track  
     else:
         pdebugger.info(str('Rejected {}'.format(smeared_track)))
         return None
Пример #52
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)))
Пример #53
0
    def smear_cluster(self, cluster, detector, accept=False, acceptance=None):
        '''Returns a copy of self with a smeared energy.
        If accept is False (default), returns None if the smeared
        cluster is not in the detector acceptance. '''

        eres = detector.energy_resolution(cluster.energy,
                                          cluster.position.Eta())
        response = detector.energy_response(cluster.energy,
                                            cluster.position.Eta())
        energy = cluster.energy * random.gauss(response, eres)
        smeared_cluster = SmearedCluster(cluster, energy, cluster.position,
                                         cluster.size(), cluster.layer,
                                         cluster.particle)
        pdebugger.info(str('Made {}'.format(smeared_cluster)))
        det = acceptance if acceptance else detector
        if det.acceptance(smeared_cluster) or accept:
            return smeared_cluster
        else:
            pdebugger.info(str('Rejected {}'.format(smeared_cluster)))
            return None
Пример #54
0
 def reconstruct_cluster(self, cluster, layer, energy=None, vertex=None):
     """construct a photon if it is an ecal
        construct a neutral hadron if it is an hcal
     """
     if vertex is None:
         vertex = TVector3()
     pdg_id = None
     propagate_to = None
     if layer == "ecal_in":
         pdg_id = 22  # photon
         propagate_to = [self.detector.elements["ecal"].volume.inner]
     elif layer == "hcal_in":
         pdg_id = 130  # K0
         propagate_to = [self.detector.elements["ecal"].volume.inner, self.detector.elements["hcal"].volume.inner]
     else:
         raise ValueError("layer must be equal to ecal_in or hcal_in")
     assert pdg_id
     mass, charge = particle_data[pdg_id]
     if energy is None:
         energy = cluster.energy
     if energy < mass:
         return None
     if mass == 0:
         momentum = energy  # avoid sqrt for zero mass
     else:
         momentum = math.sqrt(energy ** 2 - mass ** 2)
     p3 = cluster.position.Unit() * momentum
     p4 = TLorentzVector(p3.Px(), p3.Py(), p3.Pz(), energy)  # mass is not accurate here
     particle = Particle(p4, vertex, charge, pdg_id, Identifier.PFOBJECTTYPE.RECPARTICLE)
     # path = StraightLine(p4, vertex)
     # path.points[layer] = cluster.position
     # alice: this may be a bit strange because we can make a photon
     # with a path where the point is actually that of the hcal?
     # nb this only is problem if the cluster and the assigned layer
     # are different
     # particle.set_path(path)
     propagator(charge).propagate([particle], propagate_to)
     particle.clusters[layer] = cluster  # not sure about this either when hcal is used to make an ecal cluster?
     self.locked[cluster.uniqueid] = True  # just OK but not nice if hcal used to make ecal.
     pdebugger.info(str("Made {} from {}".format(particle, cluster)))
     return particle
Пример #55
0
    def reconstruct(self, event, blocksname, historyname):
        """arguments event: should contain blocks and optionally history_nodes"""
        self.blocks = getattr(event, blocksname)
        self.unused = []
        self.particles = dict()

        # history nodes will be used to connect reconstructed particles into the history
        # its optional at the moment
        if hasattr(event, historyname):
            self.history_nodes = event.history_nodes
        else:
            self.history_nodes = None

        # simplify the blocks by editing the links so that each track will end up linked to at most one hcal
        # then recalculate the blocks
        splitblocks = dict()

        for block in self._sorted_block_keys():  # put big interesting blocks first
            # print "block: ", len(self.blocks[block]),  self.blocks[block].short_name();
            newblocks = self.simplify_blocks(self.blocks[block], self.history_nodes)
            if newblocks != None:
                splitblocks.update(newblocks)
        if len(splitblocks):
            self.blocks.update(splitblocks)

        # reconstruct each of the resulting blocks
        for b in self._sorted_block_keys():  # put big interesting blocks first
            block = self.blocks[b]
            if block.is_active:  # when blocks are split the original gets deactivated
                # ALICE debugging
                # if len(block.element_uniqueids)<6:
                #    continue
                pdebugger.info("Processing {}".format(block))
                self.reconstruct_block(block)
                self.unused.extend([id for id in block.element_uniqueids if not self.locked[id]])

        # check if anything is unused
        if len(self.unused):
            self.log.warning(str(self.unused))
        self.log.info("Particles:")
        self.log.info(str(self))
Пример #56
0
 def simulate_muon(self, ptc):
     '''Simulate a muon corresponding to gen particle ptc
     
     Uses the methods detector.muon_energy_resolution
     and detector.muon_acceptance to smear the muon track.
     Later on, the particle flow algorithm will use the tracks
     coming from a muon to reconstruct muons.
     
     This method does not simulate energy deposits in the calorimeters
     '''
     pdebugger.info("Simulating Muon")  
     track = self.make_and_store_track(ptc)
     self.propagate(ptc)
     ptres = self.detector.muon_pt_resolution(ptc)
     smeared_track = self.make_smeared_track(track, ptres)
     if self.detector.muon_acceptance(smeared_track):
         self.smeared_tracks[smeared_track.uniqueid] = smeared_track
         self.update_history(track.uniqueid, smeared_track.uniqueid)    
         ptc.track_smeared = smeared_track 
     else:
         pdebugger.info(str('Rejected {}'.format(smeared_track)))
Пример #57
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
Пример #58
0
 def simulate_muon(self, ptc):
     '''Simulate a muon corresponding to gen particle ptc
     
     Uses the methods detector.muon_energy_resolution
     and detector.muon_acceptance to smear the muon track.
     Later on, the particle flow algorithm will use the tracks
     coming from a muon to reconstruct muons.
     
     This method does not simulate energy deposits in the calorimeters
     '''
     pdebugger.info("Simulating Muon")
     track = self.make_and_store_track(ptc)
     self.propagate(ptc)
     ptres = self.detector.muon_pt_resolution(ptc)
     smeared_track = self.make_smeared_track(track, ptres)
     if self.detector.muon_acceptance(smeared_track):
         self.smeared_tracks[smeared_track.uniqueid] = smeared_track
         self.update_history(track.uniqueid, smeared_track.uniqueid)
         ptc.track_smeared = smeared_track
     else:
         pdebugger.info(str('Rejected {}'.format(smeared_track)))
Пример #59
0
 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)))