class PapasDisplay(Analyzer): '''Plots a PAPAS event display Example configuration: from heppy.analyzers.PapasDisplay import PapasDisplay papasdisplay = cfg.Analyzer( PapasDisplay, instance_label = 'papas', detector = detector, particles = 'papas_sim_particles', clusters = ['ecal_clusters', 'hcal_clusters'] display = True ) ''' def __init__(self, *args, **kwargs): super(PapasDisplay, self).__init__(*args, **kwargs) self.detector = self.cfg_ana.detector self.is_display = self.cfg_ana.display if self.is_display: self.init_display() def init_display(self): self.display = Display(['xy', 'yz']) self.gdetector = GDetector(self.detector) self.display.register(self.gdetector, layer=0, clearable=False) self.is_display = True def process(self, event): particles = getattr(event, self.cfg_ana.particles) if self.is_display: self.display.clear() self.display.register(GTrajectories(particles), layer=1) for clustername in self.cfg_ana.clusters: blobs = map(Blob, getattr(event, clustername).values()) self.display.register(blobs, layer=1, clearable=False)
from heppy.display.geometry import GDetector from heppy.display.pfobjects import GTrajectories display_on = True detector = cms logging.basicConfig(level='WARNING') logger = logging.getLogger('Simulator') logger.addHandler(logging.StreamHandler(sys.stdout)) for i in range(1): if not i % 100: print i simulator = Simulator(detector, logger) # particles = monojet([211, -211, 130, 22, 22, 22], math.pi/2., math.pi/2., 2, 50) particles = [ # particle(211, math.pi/2., math.pi/2., 100), particle(211, math.pi / 2 + 0.5, 0., 40.), # particle(130, math.pi/2., math.pi/2.+0., 100.), # particle(22, math.pi/2., math.pi/2.+0.0, 10.) ] simulator.simulate(particles) if display_on: display = Display(['xy', 'yz', 'ECAL_thetaphi', 'HCAL_thetaphi']) gdetector = GDetector(detector) display.register(gdetector, 0) gtrajectories = GTrajectories(simulator.ptcs) display.register(gtrajectories, 1) display.draw()
class PapasSim(Analyzer): '''Runs PAPAS, the PArametrized Particle Simulation. #This will need to redocumented once new papasdata structure arrives Example configuration: from heppy.analyzers.PapasSim import PapasSim from heppy.papas.detectors.CMS import CMS papas = cfg.Analyzer( PapasSim, instance_label = 'papas', detector = CMS(), gen_particles = 'gen_particles_stable', sim_particles = 'sim_particles', merged_ecals = 'ecal_clusters', merged_hcals = 'hcal_clusters', tracks = 'tracks', #rec_particles = 'sim_rec_particles', # optional - will only do a simulation reconstruction if a name is provided output_history = 'history_nodes', display_filter_func = lambda ptc: ptc.e()>1., display = False, verbose = True ) detector: Detector model to be used. gen_particles: Name of the input gen particle collection sim_particles: Name extension for the output sim particle collection. Note that the instance label is prepended to this name. Therefore, in this particular case, the name of the output sim particle collection is "papas_sim_particles". merged_ecals: Name for the merged clusters created by simulator merged_hcals: Name for the merged clusters created by simulator tracks: Name for smeared tracks created by simulator rec_particles: Optional. Name extension for the reconstructed particles created by simulator This is retained for the time being to allow two reconstructions to be compared Reconstruction will occur if this parameter or rec_particles_no_leptons is provided Same comments as for the sim_particles parameter above. rec_particles_no_leptons: Optional. Name extension for the reconstructed particles created by simulator without electrons and muons Reconstruction will occur if this parameter or rec_particles is provided This is retained for the time being to allow two reconstructions to be compared Same comments as for the sim_particles parameter above. smeared: Name for smeared leptons history: Optional name for the history nodes, set to None if not needed display : Enable the event display verbose : Enable the detailed printout. event must contain todo once history is implemented event will gain ecal_clusters:- smeared merged clusters from simulation hcal_clusters:- smeared merged clusters from simulation tracks: - tracks from simulation baseline_particles:- simulated particles (excluding electrons and muons) sim_particles - simulated particles including electrons and muons ''' def __init__(self, *args, **kwargs): super(PapasSim, self).__init__(*args, **kwargs) self.detector = self.cfg_ana.detector self.simulator = Simulator(self.detector, self.mainLogger) self.simname = '_'.join( [self.instance_label, self.cfg_ana.sim_particles]) self.tracksname = self.cfg_ana.tracks self.mergedecalsname = self.cfg_ana.merged_ecals self.mergedhcalsname = self.cfg_ana.merged_hcals self.historyname = self.cfg_ana.output_history self.is_display = self.cfg_ana.display if self.is_display: self.init_display() def init_display(self): self.display = Display(['xy', 'yz']) self.gdetector = GDetector(self.detector) self.display.register(self.gdetector, layer=0, clearable=False) self.is_display = True 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)
from heppy.display.geometry import GDetector from heppy.display.pfobjects import GTrajectories display_on = True detector = cms logging.basicConfig(level="WARNING") logger = logging.getLogger("Simulator") logger.addHandler(logging.StreamHandler(sys.stdout)) for i in range(1): if not i % 100: print i simulator = Simulator(detector, logger) # particles = monojet([211, -211, 130, 22, 22, 22], math.pi/2., math.pi/2., 2, 50) particles = [ # particle(211, math.pi/2., math.pi/2., 100), particle(211, math.pi / 2 + 0.5, 0.0, 40.0), # particle(130, math.pi/2., math.pi/2.+0., 100.), # particle(22, math.pi/2., math.pi/2.+0.0, 10.) ] simulator.simulate(particles) if display_on: display = Display(["xy", "yz", "ECAL_thetaphi", "HCAL_thetaphi"]) gdetector = GDetector(detector) display.register(gdetector, 0) gtrajectories = GTrajectories(simulator.ptcs) display.register(gtrajectories, 1) display.draw()
class PapasDisplay(Analyzer): '''Plots a PAPAS event display Can be used to produce a single event plot or a comparative event plot. Example configuration:: #(single event plot) from heppy.analyzers.PapasDisplay import PapasDisplay papasdisplay = cfg.Analyzer( PapaDisplay, projections = ['xy', 'yz'], screennames = ["simulated"], particles_type_and_subtypes = ['ps'], clusters_type_and_subtypes = [['es', 'hs']], detector = detector, save = True, display = True ) #(comparative event plot) from heppy.analyzers.PapasDisplay import PapasDisplay papasdisplay = cfg.Analyzer( PapaDisplay, projections = ['xy', 'yz'], screennames = ["simulated", "reconstructed"], particles_type_and_subtypes = ['ps', 'pr'], clusters_type_and_subtypes = [['es', 'hs'],['em', 'hm']], detector = detector, save = True, display = True ) @param projections: list of projections eg ['xy', 'yz', 'xz' ,'ECAL_thetaphi', 'HCAL_thetaphi'] these will be separate windows @param subscreens: list of names of panels within each window eg subscreens=["simulated", "reconstructed"] each of the projection windows will contain all of the subscreens the subscreens can be used to show different aspects of an event, eg simulated particles and reconstructed particles @param particles_type_and_subtypes: list of type_and_subtypes of particles (eg ['ps', 'pr']). List must be same length as subscreens. Each element of list says which particles to plot on the corresponding subscreen. @param clusters_type_and_subtypes: list of type_and_subtypes of clusters (eg [['es', 'hs'],['em', 'hm']]). The list must be same length as subscreens, and each element should itself be a list. Each element of the list says which clusters to plot on the corresponding subscreen. More than one cluster type may be plotted on a single screen. @param detector: the detector to be plotted @param save: boolean, if True will save graph to png file. @param display: boolean, if True will plot graph to screen. ''' def __init__(self, *args, **kwargs): super(PapasDisplay, self).__init__(*args, **kwargs) self.compare = False nscreens = len(self.cfg_ana.screennames) if nscreens == 2: self.compare = True if (len(self.cfg_ana.particles_type_and_subtypes) != nscreens or len(self.cfg_ana.clusters_type_and_subtypes) != nscreens): raise Exception("Inconsistent display options: screennames, particles_type_and_subtypes and clusters_type_and_subtypes argument lists must have same length") if self.cfg_ana.do_display: self.init_display() def init_display(self): '''Set up the display''' self.display = Display(self.cfg_ana.projections, self.cfg_ana.screennames) self.gdetector = GDetector(self.cfg_ana.detector) self.display.register(self.gdetector, layer=0, clearable=False) def process(self, event): '''Selects the required particles and clusters and registers them on the display @param event: event that must contain a papasevent''' if not self.cfg_ana.do_display: return self.display.clear() for i in range(len(self.cfg_ana.screennames)): particles_collection = event.papasevent.get_collection(self.cfg_ana.particles_type_and_subtypes[i]) if particles_collection: self.register_particles(particles_collection.values(), i) for type_and_subtype in self.cfg_ana.clusters_type_and_subtypes[i]: cluster_collection = event.papasevent.get_collection(type_and_subtype) if cluster_collection: self.register_clusters(cluster_collection.values(), i) def register_particles(self, particles, side=0): ''' Adds list of particles into the display @param particles: list of particles to append to display @param side: 0 = left, 1 = right ''' self.display.register(GTrajectories(particles), layer=2, sides=[side]) if self.compare: otherside = (side + 1)%2 #opposite side self.display.register(GTrajectories(particles, is_grey=True), layer=1, sides=[otherside]) def register_clusters(self, clusters, side=0): '''Adds list of clusters into the display @param clusters: list of clusters to append to display @param side: 0 = left, 1 = right''' blobs = map(Blob, clusters) self.display.register(blobs, layer=2, clearable=True, sides=[side]) if self.compare: otherside = (side + 1)%2 mapfunc = partial(Blob, grey=True) blobs = map(mapfunc, clusters) self.display.register(blobs, layer=1, clearable=True, sides=[otherside])
pass else: raise ValueError('implement drawing for projection ' + projection ) class GDetector(object): def __init__(self, description): self.desc = description elems = sorted(self.desc.elements.values(), key= lambda x : x.volume.outer.rad, reverse = True) self.elements = [GDetectorElement(elem) for elem in elems] #self.elements = [GDetectorElement(elem) for elem in self.desc.elements.values()] def draw(self, projection): for elem in self.elements: elem.draw(projection) if __name__ == '__main__': from ROOT import TCanvas, TH2F from heppy.papas.detectors.CMS import CMS from heppy.display.core import Display cms = CMS() gcms = GDetector(cms) display = Display() display.register(gcms, 0) display.draw()
class PapasSim(Analyzer): '''Runs PAPAS, the PArametrized Particle Simulation. Example configuration: from heppy.analyzers.PapasSim import PapasSim from heppy.papas.detectors.CMS import CMS papas = cfg.Analyzer( PapasSim, instance_label = 'papas', detector = CMS(), gen_particles = 'gen_particles_stable', sim_particles = 'sim_particles', rec_particles = 'rec_particles', display = False, verbose = False ) detector: Detector model to be used. gen_particles: Name of the input gen particle collection sim_particles: Name extension for the output sim particle collection. Note that the instance label is prepended to this name. Therefore, in this particular case, the name of the output sim particle collection is "papas_sim_particles". rec_particles: Name extension for the output reconstructed particle collection. Same comments as for the sim_particles parameter above. display : Enable the event display verbose : Enable the detailed printout. ''' def __init__(self, *args, **kwargs): super(PapasSim, self).__init__(*args, **kwargs) self.detector = self.cfg_ana.detector self.simulator = Simulator(self.detector, self.mainLogger) self.simname = '_'.join([self.instance_label, self.cfg_ana.sim_particles]) self.recname = '_'.join([self.instance_label, self.cfg_ana.rec_particles]) self.is_display = self.cfg_ana.display if self.is_display: self.init_display() def init_display(self): self.display = Display(['xy','yz']) self.gdetector = GDetector(self.detector) self.display.register(self.gdetector, layer=0, clearable=False) self.is_display = True 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) self.simulator.simulate( gen_particles ) pfsim_particles = self.simulator.ptcs if self.is_display: self.display.register( GTrajectories(pfsim_particles), layer=1) simparticles = sorted( pfsim_particles, key = lambda ptc: ptc.e(), reverse=True) particles = sorted( self.simulator.particles, key = lambda ptc: ptc.e(), reverse=True) setattr(event, self.simname, simparticles) pfinput = PFInput(simparticles) event.tracks = dict() event.ECALclusters = dict() event.HCALclusters = dict() for label, element in pfinput.elements.iteritems(): if label == 'tracker': event.tracks[0,id(element)]=element elif label == 'ecal_in': event.ECALclusters[1,id(element)]=element elif label == 'hcal_in': event.HCALclusters[2,id(element)]=element else: print label assert(False) setattr(event, self.recname, particles)
class Papas(Analyzer): '''Runs PAPAS, the PArametrized Particle Simulation. Papas reads a list of stable generated particles, and creates a list of reconstruted particles. First, the particles are extrapolated in the magnetic field through the tracker and to the calorimeters, and the particle deposits are simulated using a parametrized simulation. Then, a particle flow algorithm is used to connect the simulated tracks and calorimeter energy deposits, and to identify and reconstruct final state particles. Example: from heppy.analyzers.Papas import Papas from heppy.papas.detectors.CMS import CMS papas = cfg.Analyzer( Papas, instance_label = 'papas', detector = CMS(), gen_particles = 'gen_particles_stable', sim_particles = 'sim_particles', rec_particles = 'particles', display = False, verbose = True ) detector: Detector model to be used, here CMS. gen_particles: Name of the input gen particle collection sim_particles: Name for the output sim particle collection. rec_particles: Name for the output reconstructed particle collection. display : Enable the event display verbose : Enable the detailed printout. ''' def __init__(self, *args, **kwargs): super(Papas, self).__init__(*args, **kwargs) self.detector = self.cfg_ana.detector self.simulator = Simulator(self.detector, self.mainLogger) self.is_display = self.cfg_ana.display if self.is_display: self.init_display() def init_display(self): self.display = Display(['xy','yz']) self.gdetector = GDetector(self.detector) self.display.register(self.gdetector, layer=0, clearable=False) self.is_display = True 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) self.simulator.simulate( gen_particles ) pfsim_particles = self.simulator.ptcs if self.is_display: particles_for_display = pfsim_particles if hasattr(self.cfg_ana, 'display_filter_func'): particles_for_display = [ ptc for ptc in pfsim_particles if self.cfg_ana.display_filter_func(ptc) ] self.display.register( GTrajectories(particles_for_display), layer=1) simparticles = sorted( pfsim_particles, key = lambda ptc: ptc.e(), reverse=True) particles = sorted( self.simulator.particles, key = lambda ptc: ptc.e(), reverse=True) setattr(event, self.cfg_ana.sim_particles, simparticles) setattr(event, self.cfg_ana.rec_particles, particles)
class PapasDisplay(Analyzer): '''Plots a PAPAS event display Can be used to produce a single event plot or a comparative event plot. Example configuration:: #(single event plot) from heppy.analyzers.PapasDisplay import PapasDisplay papasdisplay = cfg.Analyzer( PapaDisplay, projections = ['xy', 'yz'], screennames = ["simulated"], particles_type_and_subtypes = ['ps'], clusters_type_and_subtypes = [['es', 'hs']], detector = detector, save = True, display = True ) #(comparative event plot) from heppy.analyzers.PapasDisplay import PapasDisplay papasdisplay = cfg.Analyzer( PapaDisplay, projections = ['xy', 'yz'], screennames = ["simulated", "reconstructed"], particles_type_and_subtypes = ['ps', 'pr'], clusters_type_and_subtypes = [['es', 'hs'],['em', 'hm']], detector = detector, save = True, display = True ) @param projections: list of projections eg ['xy', 'yz', 'xz' ,'ECAL_thetaphi', 'HCAL_thetaphi'] these will be separate windows @param subscreens: list of names of panels within each window eg subscreens=["simulated", "reconstructed"] each of the projection windows will contain all of the subscreens the subscreens can be used to show different aspects of an event, eg simulated particles and reconstructed particles @param particles_type_and_subtypes: list of type_and_subtypes of particles (eg ['ps', 'pr']). List must be same length as subscreens. Each element of list says which particles to plot on the corresponding subscreen. @param clusters_type_and_subtypes: list of type_and_subtypes of clusters (eg [['es', 'hs'],['em', 'hm']]). The list must be same length as subscreens, and each element should itself be a list. Each element of the list says which clusters to plot on the corresponding subscreen. More than one cluster type may be plotted on a single screen. @param detector: the detector to be plotted @param save: boolean, if True will save graph to png file. @param display: boolean, if True will plot graph to screen. ''' def __init__(self, *args, **kwargs): super(PapasDisplay, self).__init__(*args, **kwargs) self.compare = False nscreens = len(self.cfg_ana.screennames) if nscreens == 2: self.compare = True if (len(self.cfg_ana.particles_type_and_subtypes) != nscreens or len(self.cfg_ana.clusters_type_and_subtypes) != nscreens): raise Exception("Inconsistent display options: screennames, particles_type_and_subtypes and clusters_type_and_subtypes argument lists must have same length") if self.cfg_ana.do_display: self.init_display() def init_display(self): '''Set up the display''' self.display = Display(self.cfg_ana.projections, self.cfg_ana.screennames) self.gdetector = GDetector(self.cfg_ana.detector) self.display.register(self.gdetector, layer=0, clearable=False) def process(self, event): '''Selects the required particles and clusters and registers them on the display @param event: event that must contain a papasevent''' if not self.cfg_ana.do_display: return self.display.clear() for i in range(len(self.cfg_ana.screennames)): particles_collection = event.papasevent.get_collection(self.cfg_ana.particles_type_and_subtypes[i]) if particles_collection: self.register_particles(particles_collection.values(), i) for type_and_subtype in self.cfg_ana.clusters_type_and_subtypes[i]: clusters = event.papasevent.get_collection(type_and_subtype) if clusters: self.register_clusters(clusters.values(), i) def register_particles(self, particles, side=0): ''' Adds list of particles into the display @param particles: list of particles to append to display @param side: 0 = left, 1 = right ''' self.display.register(GTrajectories(particles), layer=2, sides=[side]) if self.compare: otherside = (side + 1)%2 #opposite side self.display.register(GTrajectories(particles, is_grey=True), layer=1, sides=[otherside]) def register_clusters(self, clusters, side=0): '''Adds list of clusters into the display @param clusters: list of clusters to append to display @param side: 0 = left, 1 = right''' blobs = map(Blob, clusters) self.display.register(blobs, layer=2, clearable=True, sides=[side]) if self.compare: otherside = (side + 1)%2 mapfunc = partial(Blob, grey=True) blobs = map(mapfunc, clusters) self.display.register(blobs, layer=1, clearable=True, sides=[otherside])
class PapasSim(Analyzer): '''Runs PAPAS, the PArametrized Particle Simulation. Example configuration: from heppy.analyzers.PapasSim import PapasSim from heppy.papas.detectors.CMS import CMS papas = cfg.Analyzer( PapasSim, instance_label = 'papas', detector = CMS(), gen_particles = 'gen_particles_stable', sim_particles = 'sim_particles', merged_ecals = 'ecal_clusters', merged_hcals = 'hcal_clusters', tracks = 'tracks', #rec_particles = 'sim_rec_particles', # optional - will only do a simulation reconstruction if a name is provided output_history = 'history_nodes', display_filter_func = lambda ptc: ptc.e()>1., display = False, verbose = True ) detector: Detector model to be used. gen_particles: Name of the input gen particle collection sim_particles: Name extension for the output sim particle collection. Note that the instance label is prepended to this name. Therefore, in this particular case, the name of the output sim particle collection is "papas_sim_particles". merged_ecals: Name for the merged clusters created by simulator merged_hcals: Name for the merged clusters created by simulator tracks: Name for smeared tracks created by simulator rec_particles: Optional. Name extension for the reconstructed particles created by simulator This is retained for the time being to allow two reconstructions to be compared Reconstruction will occur if this parameter or rec_particles_no_leptons is provided Same comments as for the sim_particles parameter above. rec_particles_no_leptons: Optional. Name extension for the reconstructed particles created by simulator without electrons and muons Reconstruction will occur if this parameter or rec_particles is provided This is retained for the time being to allow two reconstructions to be compared Same comments as for the sim_particles parameter above. smeared: Name for smeared leptons history: Optional name for the history nodes, set to None if not needed display : Enable the event display verbose : Enable the detailed printout. ''' def __init__(self, *args, **kwargs): super(PapasSim, self).__init__(*args, **kwargs) self.detector = self.cfg_ana.detector self.simulator = Simulator(self.detector, self.mainLogger) self.simname = '_'.join([self.instance_label, self.cfg_ana.sim_particles]) self.tracksname = self.cfg_ana.tracks self.mergedecalsname = self.cfg_ana.merged_ecals self.mergedhcalsname = self.cfg_ana.merged_hcals self.historyname = self.cfg_ana.output_history #decide if reconstruction is needed self.do_reconstruct = False if hasattr(self.cfg_ana, 'rec_particles') : self.do_reconstruct = True self.recname = '_'.join([self.instance_label, self.cfg_ana.rec_particles]) #if hasattr(self.cfg_ana, 'rec_particles_no_leptons') : # self.do_reconstruct = True # self.rec_noleptonsname = '_'.join([self.instance_label, self.cfg_ana.rec_particles_no_leptons]) self.is_display = self.cfg_ana.display if self.is_display: self.init_display() def init_display(self): self.display = Display(['xy','yz']) self.gdetector = GDetector(self.detector) self.display.register(self.gdetector, layer=0, clearable=False) self.is_display = True def process(self, event): ''' event must contain the event will gain ecal_clusters:- smeared merged clusters from simulation hcal_clusters:- smeared merged clusters from simulation tracks: - tracks from simulation baseline_particles:- simulated particles (excluding electrons and muons) sim_particles - simulated particles including electrons and muons ''' event.simulator = self if self.is_display: self.display.clear() pfsim_particles = [] gen_particles = getattr(event, self.cfg_ana.gen_particles) self.simulator.simulate( gen_particles, self.do_reconstruct) 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) if self.do_reconstruct: # used for verification/ comparison of reconstruction methods #these are the reconstructed (via simulation) particles including electrons and muons particles = sorted( self.simulator.particles, key = lambda ptc: ptc.e(), reverse=True) #these are the reconstructed (via simulation) particles excluding muons and electrons #origparticles = sorted( self.simulator.pfsequence.pfreco.particles, # key = lambda ptc: ptc.e(), reverse=True) if hasattr(self, 'recname') : setattr(event, self.recname, particles) #if hasattr(self, 'rec_noleptonsname') : # setattr(event, self.rec_noleptonsname, origparticles) #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) ####if uncommented this will use the original reconstructions to provide the ready merged tracks and clusters #event.ecal_clusters = dict() #event.hcal_clusters = dict() #for element in self.simulator.pfsequence.elements : #elif element.__class__.__name__ == 'SmearedCluster' and element.layer == 'ecal_in': #event.ecal_clusters[element.uniqueid] = element #elif element.__class__.__name__ == 'SmearedCluster' and element.layer == 'hcal_in': #event.hcal_clusters[element.uniqueid] = element #else : #print element.__class__.__name__ #assert(False) ###if uncommented will check that cluster merging is OK (compare new merging module with Colins merging) #event.origecal_clusters = dict() #event.orighcal_clusters = dict() #for element in self.simulator.pfsequence.elements : #if element.__class__.__name__ == 'SmearedCluster' and element.layer == 'ecal_in': #event.origecal_clusters[element.uniqueid] = element #elif element.__class__.__name__ == 'SmearedCluster' and element.layer == 'hcal_in': #event.orighcal_clusters[element.uniqueid] = element #ClusterComparer(event.origecal_clusters,event.ecal_clusters) #ClusterComparer(event.orighcal_clusters,event.hcal_clusters) #event.othertracks = dict() #for element in self.simulator.pfsequence.elements : #if element.__class__.__name__ == 'SmearedTrack': #event.othertracks[element.uniqueid] = element #assert (len(event.tracks) == len(event.othertracks)) pass
class PapasSim(Analyzer): '''Runs PAPAS, the PArametrized Particle Simulation. #This will need to redocumented once new papasdata structure arrives Example configuration: from heppy.analyzers.PapasSim import PapasSim from heppy.papas.detectors.CMS import CMS papas = cfg.Analyzer( PapasSim, instance_label = 'papas', detector = CMS(), gen_particles = 'gen_particles_stable', sim_particles = 'sim_particles', merged_ecals = 'ecal_clusters', merged_hcals = 'hcal_clusters', tracks = 'tracks', #rec_particles = 'sim_rec_particles', # optional - will only do a simulation reconstruction if a name is provided output_history = 'history_nodes', display_filter_func = lambda ptc: ptc.e()>1., display = False, verbose = True ) detector: Detector model to be used. gen_particles: Name of the input gen particle collection sim_particles: Name extension for the output sim particle collection. Note that the instance label is prepended to this name. Therefore, in this particular case, the name of the output sim particle collection is "papas_sim_particles". merged_ecals: Name for the merged clusters created by simulator merged_hcals: Name for the merged clusters created by simulator tracks: Name for smeared tracks created by simulator rec_particles: Optional. Name extension for the reconstructed particles created by simulator This is retained for the time being to allow two reconstructions to be compared Reconstruction will occur if this parameter or rec_particles_no_leptons is provided Same comments as for the sim_particles parameter above. rec_particles_no_leptons: Optional. Name extension for the reconstructed particles created by simulator without electrons and muons Reconstruction will occur if this parameter or rec_particles is provided This is retained for the time being to allow two reconstructions to be compared Same comments as for the sim_particles parameter above. smeared: Name for smeared leptons history: Optional name for the history nodes, set to None if not needed display : Enable the event display verbose : Enable the detailed printout. event must contain todo once history is implemented event will gain ecal_clusters:- smeared merged clusters from simulation hcal_clusters:- smeared merged clusters from simulation tracks: - tracks from simulation baseline_particles:- simulated particles (excluding electrons and muons) sim_particles - simulated particles including electrons and muons ''' def __init__(self, *args, **kwargs): super(PapasSim, self).__init__(*args, **kwargs) self.detector = self.cfg_ana.detector self.simulator = Simulator(self.detector, self.mainLogger) self.simname = '_'.join([self.instance_label, self.cfg_ana.sim_particles]) self.tracksname = self.cfg_ana.tracks self.mergedecalsname = self.cfg_ana.merged_ecals self.mergedhcalsname = self.cfg_ana.merged_hcals self.historyname = self.cfg_ana.output_history self.is_display = self.cfg_ana.display if self.is_display: self.init_display() def init_display(self): self.display = Display(['xy', 'yz']) self.gdetector = GDetector(self.detector) self.display.register(self.gdetector, layer=0, clearable=False) self.is_display = True 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)