def weight(x, y, z, zenith, azimuth, multiplicity, e, r): axis = dataclasses.I3Particle() axis.pos = dataclasses.I3Position(x, y, z) axis.dir = dataclasses.I3Direction(zenith, azimuth) assert multiplicity == 1 bundle = MuonGun.BundleConfiguration() bundle.append(MuonGun.BundleEntry(float(r), float(e))) return weighter(axis, bundle)
def effective_area(frame, model, generator): mctree = frame["I3MCTree"] primary = mctree.primaries[0] muon = mctree.get_daughters(primary)[0] bundle = MuonGun.BundleConfiguration([MuonGun.BundleEntry(0, muon.energy)]) area = 1 / generator.generated_events(primary, bundle) frame["MCMuon"] = muon frame["MuonEffectiveArea"] = dataclasses.I3Double(area) weighter = MuonGun.WeightCalculator(model, generator) weight = weighter(primary, bundle) frame["MuonWeight"] = dataclasses.I3Double(weight) return True
def book_weights(infiles, outfile, model='Hoerandel5_atmod12_SIBYLL'): tray = I3Tray() tray.AddModule('I3Reader', 'reader', filenamelist=infiles) tray.AddModule( lambda frame: frame.Put('MCPrimary', frame['I3MCTree'].primaries[0]), Streams=[icetray.I3Frame.DAQ]) tray.AddModule(lambda frame: frame.Put('Muon', frame['I3MCTree'][1]), Streams=[icetray.I3Frame.DAQ]) model = MuonGun.load_model(model) generator = harvest_generators(infiles) tray.AddModule('I3MuonGun::WeightCalculatorModule', 'MuonWeight', Model=model, Generator=generator) from icecube.hdfwriter import I3SimHDFWriter tray.AddSegment(I3SimHDFWriter, 'scribe', Output=outfile, Keys=[ 'MCPrimary', 'Muon', 'MuonWeight', dict(key='I3MCTree', name='BundleParameters', converter=MuonGun.converters.MuonBundleConverter( 1, generator.surface)) ], Types=[]) tray.Execute()
def todet(frame, surface): detmu = MuonGun.muons_at_surface(frame, surface) for i in range(len(detmu)): frame['EnteringMuon_' + str(i)] = detmu[i] if ('EnteringMuon_0' ) not in frame: #does not contain an intersecting muon, toss it return False else: return True
def generate(nevents=1, fname='foo.i3'): tray = I3Tray() generator = MuonGun.Floodlight() # set up a random number generator randomService = phys_services.I3SPRNGRandomService(seed=1, nstreams=10000, streamnum=1) tray.context['I3RandomService'] = randomService def make_particle(): p = dataclasses.I3Particle() p.pos = dataclasses.I3Position(0, 0, 2e3) p.dir = dataclasses.I3Direction(0, 0) p.time = 0 p.energy = 10**randomService.Uniform(3, 6) p.type = p.DeltaE p.location_type = p.InIce return p make_particle.i = 0 def make_mctree(frame): mctree = dataclasses.I3MCTree() primary = make_particle() primary.location_type = primary.Anywhere primary.type = primary.unknown muon = make_particle() mctree.add_root(primary) mctree.append_child(primary, muon) frame['I3MCTree'] = mctree tray.AddSegment(GenerateBundles, 'BundleGen', Generator=generator, NEvents=nevents, GCDFile=gcd) def stash(frame): frame['RemadeMCTree'] = dataclasses.I3MCTree(frame['I3MCTree']) tray.AddModule(stash, 'copy', Streams=[icetray.I3Frame.DAQ]) tray.AddModule('I3PropagatorModule', 'propagator', PropagatorServices=make_propagators(), RandomService=randomService, RNGStateName="RNGState") tray.AddModule('I3Writer', 'writer', Streams=[icetray.I3Frame.DAQ, icetray.I3Frame.Physics], filename=fname) tray.Execute(nevents + 3)
def Configure(self): self.binner = MuonGun.TrackBinner(self.GetParameter("MinDepth"), self.GetParameter("MaxDepth"), self.GetParameter("DepthSteps")) self.weighter = self.GetParameter("Weight") import os components = os.path.split(self.GetParameter("Outfile")) if os.path.splitext(components[-1])[1] in ('.hdf5', '.h5'): self.where = '/' self.outfile = os.path.join(*components) else: self.where = '/' + components[-1] self.outfile = os.path.join(*components[:-1]) if os.path.exists(self.outfile): os.unlink(self.outfile) self.nevents = 0
def get_fluxes_and_names(): """Get fluxes and names of all available models. Returns ------- list of MuonGun models, list of str List of MuonGun models List of model names """ table_path = os.path.expandvars('$I3_BUILD/MuonGun/resources/tables/*') table_files = glob(table_path) table_files = [os.path.basename(table_file) for table_file in table_files] flux_names = np.unique( [table_file.split('.')[0] for table_file in table_files]) fluxes = [] for flux_name in flux_names: fluxes.append(MuonGun.load_model(flux_name)) return fluxes, flux_names
def SurfEneCut(frame): dcPart = MuonGun.muons_at_surface(frame,dcSurface) max_ene = 0 # if(frame.Has('I3MCTree')): # if(frame["I3MCTree"].most_energetic_muon): # if(frame["I3MCTree"].most_energetic_muon.energy<500): # return False # else: # return False # else: # return False if(len(dcPart)>0): for i in xrange(len(dcPart)): if(dcPart[i].energy>max_ene): max_ene = dcPart[i].energy if(max_ene>0): # print max_ene, len(dcPart) return True else: return False else: return False
def sample_energy(edist, depth, ct, m, nsamples=10000): # bins that will have roughly equal contents rbins = numpy.array([0, 1, 2, 3, 4, 6, 10, 15, 250]) powerlaw = MuonGun.OffsetPowerLaw(4, 1e3, edist.min, edist.max) ebins = powerlaw.isf(numpy.linspace(0, 1, 21)[::-1]) start = resource.getrusage(resource.RUSAGE_SELF) samples = edist.generate(rng, depth, ct, m, nsamples) end = resource.getrusage(resource.RUSAGE_SELF) dt = end.ru_utime - start.ru_utime icetray.logging.log_info("%.1f microsec/sample" % (1e6 * dt / nsamples)) samples = numpy.array([(i.first, i.second) for i in samples]) bins, edges = numpy.histogramdd(samples, bins=(rbins, ebins)) assert bins.sum() == nsamples empties = (bins < 10).sum() / float(bins.size) if empties > 0.25: warnings.warn('%d%% of bins have fewer than 10 entries' % (100 * empties)) norm = nsamples / edist.integrate(depth, ct, m, 0, 250, edist.min, edist.max) @numpy.vectorize def integrate_model(rbin, ebin): return edist.integrate(depth, ct, m, edges[0][rbin], edges[0][rbin + 1], edges[1][ebin], edges[1][ebin + 1]) i, j = numpy.meshgrid(range(len(rbins) - 1), range(len(ebins) - 1), indexing='ij') mu = norm * integrate_model(i.T, j.T) chi2 = (bins.T - mu)**2 / mu return samples, chi2.sum(), bins.size
def book_weights(infiles, outfile, model='Hoerandel5_atmod12_SIBYLL'): tray = I3Tray() tray.AddModule('I3Reader', 'reader', filenamelist=infiles) tray.AddModule('I3NullSplitter', 'nullsplit') tray.AddModule( lambda frame: frame.Put('MCPrimary', frame['I3MCTree'].primaries[0])) tray.AddModule( lambda frame: frame.Put('Muon', frame['I3MCTree'].most_energetic_muon)) model = MuonGun.load_model(model) generator = harvest_generators(infiles) tray.AddModule('I3MuonGun::WeightCalculatorModule', 'MuonWeight', Model=model, Generator=generator) from icecube.hdfwriter import I3HDFWriter tray.AddSegment( I3HDFWriter, 'scribe', Output=outfile, Keys=[ 'MCPrimary', 'Muon', 'MuonWeight', dict(key='I3MCTree', name='BundleParameters', converter=MuonGun.converters.MuonBundleConverter( 1, generator.surface)) ], Types=[], SubEventStreams=['nullsplit'], ) tray.AddModule('TrashCan', 'YesWeCan') tray.Execute() tray.Finish()
#!/usr/bin/env python """ Use muon flux weights to calculate an effective livetime for combined CORSIKA samples as a function of energy. """ import pylab, numpy from icecube import MuonGun, icetray, dataclasses from icecube.icetray import I3Units outer = MuonGun.Cylinder(1600, 800) #inner = MuonGun.Cylinder(1600, 800) inner = MuonGun.Cylinder(500, 150, dataclasses.I3Position(46.3, -34.9, -300)) #inner = MuonGun.Cylinder(700, 125, dataclasses.I3Position(29.3,52.6,-150)) #inner = outer #Most tested spectrum #spectrum = MuonGun.OffsetPowerLaw(5.0, 7e2, 0, 1e5) spectrum = MuonGun.OffsetPowerLaw(5.0, 7e2, 500, 1e5) #Limited spectrum range #spectrum = MuonGun.OffsetPowerLaw(5.2, 7e2, 150, 1e4) #spectrum = MuonGun.OffsetPowerLaw(2, 1*I3Units.TeV, 1*I3Units.TeV, 1*I3Units.PeV) #Good spectrum producing ~1 day with 10k evts above 200 GeV #spectrum = MuonGun.OffsetPowerLaw(5.2, 7e2, 200, 1e6) #Jackob's spectrum #spectrum = MuonGun.OffsetPowerLaw(5.0, 5e2, 200, 1e6) #Good spectrum producing ~1 day with 5000 evts above 400 GeV #spectrum = MuonGun.OffsetPowerLaw(5.25, 1000, 1, 1e6) model = MuonGun.load_model( '/home/mamday/icesim/build/MuonGun/resources/tables/GaisserH4a_atmod12_SIBYLL' )
#!/usr/bin/env python from argparse import ArgumentParser parser = ArgumentParser() parser.add_argument("--read", default=None) parser.add_argument("--write", default=None) args = parser.parse_args() from icecube import icetray, dataio, MuonGun, phys_services generator = MuonGun.StaticSurfaceInjector() def read(fname='muongun_serialization_test.i3'): f = dataio.I3File(fname) frame = f.pop_frame() f.close() newgenerator = frame['Generator'] assert newgenerator.surface == generator.surface def write(fname='muongun_serialization_test.i3'): frame = icetray.I3Frame() frame['Generator'] = generator f = dataio.I3File(fname, 'w') f.push(frame) f.close()
print 'Usage: %prog [options] output.i3 input1.i3 [input2.i3] ...' sys.exit(1) tray = I3Tray() tray.AddModule('I3Reader', 'reader', FilenameList=filenamelist) #Add muon weight that I guess I should have added before from icecube import MuonGun, sim_services from icecube.icetray import I3Units from icecube.dataclasses import * from icecube.sim_services.propagation import get_propagators from icecube.MuonGun.segments import GenerateBundles from icecube.MuonGun import load_model, EnergyDependentSurfaceInjector, ConstantSurfaceScalingFunction, StaticSurfaceInjector, Cylinder, OffsetPowerLaw #Flux model model = MuonGun.load_model('GaisserH4a_atmod12_SIBYLL') model.flux.min_multiplicity = 1 model.flux.max_multiplicity = 1 #Inner and outher target surfaces outSurface = Cylinder(1600*I3Units.m, 800*I3Units.m) inSurface = Cylinder(700*I3Units.m, 125*I3Units.m, I3Position(29.3,52.6,-150)) #Sets energy and spectral index of muons spectrum = MuonGun.OffsetPowerLaw(5.2, 7e2, 200, 1e6) #This version only aims at inSurface, but muons originate at outSurface scaling = MuonGun.ConstantSurfaceScalingFunction(inSurface) generator = MuonGun.EnergyDependentSurfaceInjector(outSurface, model.flux, spectrum, model.radius, scaling,0,1) tray.AddModule('I3MuonGun::WeightCalculatorModule', 'MuonWeight', Model=model, Generator=generator, )
def GenerateAtmosphericNeutrinos(tray, name, Files, GCDFile="", AutoExtendMuonVolume=False, EnergyBiasPower=1, FlavorBias=[30, 1, 1], CylinderRadius=600 * I3Units.m, CylinderHeight=1200 * I3Units.m, CrossSections='csms', NEvents=-1, MakeNeutrino=True): r""" Read CORSIKA showers containing neutrinos, and force exactly one neutrino to interact. NB: this segment is deprecated. Use GenerateAirShowers, SelectNeutrino, and PropagateMuons instead. :param Files: a list of CORSIKA files to read :param GCDFile: I3 file with GCD information to read in before the CORSIKA files :param AutoExtendMuonVolume: allow :math:`\nu_{\mu}` to interact far before they reach the detector :param EnergyBiasPower: select a neutrino from the bundle with probability proportional to E^power :param FlavorBias: scale selection probability for :math:`\nu_{e}/\nu_{\mu}/\nu_{\tau}` by these factors. The default value is appropriate for equal sampling of conventional atmospheric :math:`\nu_{e}/\nu_{\mu}`. :param CylinderRadius: radius of upright-cylinder target volume :param CylinderHeight: full height of simulation volume :param CrossSections: cross-section tables to use ('cteq5', 'css', or 'csms') """ import warnings warnings.warn( 'GenerateAtmosphericNeutrinos is deprecated. Use GenerateAirShowers, SelectNeutrino, and PropagateMuons instead' ) from operator import add from icecube import neutrino_generator, sim_services, MuonGun from icecube.sim_services.propagation import get_propagators icetray.load('corsika-reader', False) random = tray.context['I3RandomService'] surface = MuonGun.Cylinder(CylinderHeight, CylinderRadius) tray.Add('I3CORSIKAReader', 'reader', filenamelist=Files, NEvents=NEvents, CylinderHeight=surface.length, CylinderRadius=surface.radius, Prefix=GCDFile) # Drop showers where no particles reach the observation level tray.Add(lambda frame: len(frame['I3MCTree']) > 1, Streams=[icetray.I3Frame.DAQ]) # Remove low-energy muons that can't reach the detector tray.Add('I3InIceCORSIKATrimmer') tray.Add(SelectNeutrino, AutoExtendMuonVolume=AutoExtendMuonVolume, EnergyBiasPower=EnergyBiasPower, FlavorBias=FlavorBias, CylinderRadius=CylinderRadius, CylinderHeight=CylinderHeight, CrossSections=CrossSections) base_propagators = get_propagators() propagators = tray.context['I3ParticleTypePropagatorServiceMap'] for k in base_propagators.keys(): propagators[k] = base_propagators[k] tray.Add('Rename', Keys=['I3MCTree', 'I3MCTree_preMuonProp']) tray.Add('I3PropagatorModule', PropagatorServices=propagators, InputMCTreeName="I3MCTree_preMuonProp", OutputMCTreeName="I3MCTree", RandomService='I3RandomService')
def SelectNeutrino( tray, name, Propagators=None, AutoExtendMuonVolume=False, EnergyBiasPower=1, FlavorBias=[30, 1, 1], CylinderRadius=600 * I3Units.m, CylinderHeight=1200 * I3Units.m, CrossSections='csms', ): """ Select a neutrino to interact, and add neutrino propagators to the context. :param AutoExtendMuonVolume: allow :math:`\nu_{\mu}` to interact far before they reach the detector :param EnergyBiasPower: select a neutrino from the bundle with probability proportional to E^power :param FlavorBias: scale selection probability for :math:`\nu_{e}/\nu_{\mu}/\nu_{\tau}` by these factors. The default value is appropriate for equal sampling of conventional atmospheric :math:`\nu_{e}/\nu_{\mu}`. :param CylinderRadius: radius of upright-cylinder target volume :param CylinderHeight: full height of simulation volume :param CrossSections: cross-section tables to use ('cteq5', 'css', or 'csms') """ from operator import add from icecube import neutrino_generator, sim_services, MuonGun # Set up NeutrinoGenerator internals random = tray.context['I3RandomService'] surface = MuonGun.Cylinder(CylinderHeight, CylinderRadius) config = neutrino_generator.Steering() config.detection_surface = surface config.do_muon_range_extension = AutoExtendMuonVolume interactions = neutrino_generator.I3NuGInteractionInfo( random, config, CrossSections) interactions.initialize() # I3NuGSourceSelector needs this in its context tray.context['NuGSteer'] = config # Remove all but one neutrino tray.Add('I3NuGSourceSelector', EnergyBiasPowerIndex=EnergyBiasPower, ParticleBiases=reduce(add, [[b] * 2 for b in FlavorBias]), KeepDarkNeutrinos=False) # Store propagators in the context if not 'I3ParticleTypePropagatorServiceMap' in tray.context: tray.context[ 'I3ParticleTypePropagatorServiceMap'] = sim_services.I3ParticleTypePropagatorServiceMap( ) Propagators = tray.context['I3ParticleTypePropagatorServiceMap'] # Use NeutrinoPropagator for neutrinos prop = neutrino_generator.I3NeutrinoPropagator(random, config, interactions) # ensure that all nu_e and nu_mu reach the detector prop.prop_mode = neutrino_generator.PropagationMode.ncgrweighted tau_prop = neutrino_generator.I3NeutrinoPropagator(random, config, interactions) # un-weighted propagation for nu_tau to allow for tau regeneration tau_prop.prop_mode = neutrino_generator.PropagationMode.nopropweight for flavor in 'E', 'Mu', 'Tau': for ptype in '', 'Bar': Propagators[getattr(dataclasses.I3Particle.ParticleType, 'Nu' + flavor + ptype)] = tau_prop if flavor == 'Tau' else prop
def cascade_l5_cuts_muongun(tray, name, infiles): from icecube import MuonGun if 'high' in infiles[1]: sframe_file = '/data/user/nwandkowsky/utils/sframes/muongun_highe_sframe.i3.bz2' elif 'med' in infiles[1]: sframe_file = '/data/user/nwandkowsky/utils/sframes/muongun_mede_sframe.i3.bz2' elif 'low' in infiles[1]: sframe_file = '/data/user/nwandkowsky/utils/sframes/muongun_lowe_sframe.i3.bz2' print( '\033[93mWarning: Inserting {} to infiles.\033[0m'.format(sframe_file)) print('\033[93m Make sure this is correct... \033[0m') infiles.insert(0, sframe_file) tray.Add('Rename', Keys=["I3MCTree_preMuonProp", "I3MCTree"]) def harvest_generators(sinfiles): from icecube.icetray.i3logging import log_info as log generator = None f = dataio.I3File(sinfiles[0]) while True: try: fr = f.pop_frame(icetray.I3Frame.Stream('S')) except RuntimeError as e: log('Caught the following exception:', str(e)) fr = None if fr is None: break for k in fr.keys(): v = fr[k] if isinstance(v, MuonGun.GenerationProbability): log('%s: found "%s" (%s)' % (sinfiles[0], k, type(v).__name__), unit="MuonGun") if generator is None: generator = v else: generator += v #print generator f.close() return generator generator = harvest_generators(infiles) def track_energy(frame): energy = [] energy.append(frame["SplineMPEMuEXDifferential"].energy + frame["MillipedeDepositedEnergy"].value) energy.append(frame["SplineMPEMuEXDifferential"].energy + frame["L5MonopodFit4"].energy) energy.append(frame["L5MonopodFit4"].energy + frame["MillipedeDepositedEnergy"].value) frame["TrackEnergy"] = dataclasses.I3Double(min(energy)) tray.Add(track_energy) def remove_background(frame): if frame["IsHese"].value == True: return True if frame["IsCascade_reco"].value == False and ( (numpy.cos(frame["SplineMPEMuEXDifferential"].dir.zenith) > 0.4 and frame["SplineMPEMuEXDifferential"].energy < 1e4) or numpy.cos(frame["SplineMPEMuEXDifferential"].dir.zenith) > 0.6 and frame["SplineMPEMuEXDifferential"].energy < 3e4): print("Likely a background event (spline)... removing...", frame["I3EventHeader"].run_id, frame["I3EventHeader"].event_id) return False if frame["IsCascade"].value == True and frame["TrackFit"].pos.z > 370.: print("Potentially coincident cascade removed...", frame["I3EventHeader"].run_id, frame["I3EventHeader"].event_id) return False tray.Add(remove_background) def printy(frame): del frame["MillipedeDepositedEnergy"] del frame["TrackEnergy"] if "MuonLosses" in frame: losses = frame["MuonLosses"] first_loss_found = False deposited_energy = 0 for i in range(0, len(losses)): if losses[i].pos.z < 500 and losses[ i].pos.z > -500 and math.sqrt( losses[i].pos.x * losses[i].pos.x + losses[i].pos.y * losses[i].pos.y) < 550: deposited_energy = deposited_energy + losses[i].energy else: deposited_energy = 0. frame["MillipedeDepositedEnergy"] = dataclasses.I3Double( deposited_energy) frame["TrackEnergy"] = dataclasses.I3Double(deposited_energy) if frame["IsHese"].value == False and frame[ "IsCascade_reco"].value == False and deposited_energy == 0.: return False if frame["IsCascade_reco"] == True and frame[ "L5MonopodFit4"].energy > 6e4: del frame["IsCascade_reco"] del frame["IsTrack_reco"] if frame["TrackLength"] > 550: frame["IsCascade_reco"] = icetray.I3Bool(False) frame["IsTrack_reco"] = icetray.I3Bool(True) else: frame["IsCascade_reco"] = icetray.I3Bool(True) frame["IsTrack_reco"] = icetray.I3Bool(False) if frame["IsCascade_reco"].value == False and frame[ "TrackEnergy"].value > 6e4: del frame["IsCascade_reco"] del frame["IsTrack_reco"] if frame["TrackLength"] > 550: frame["IsCascade_reco"] = icetray.I3Bool(False) frame["IsTrack_reco"] = icetray.I3Bool(True) else: frame["IsCascade_reco"] = icetray.I3Bool(True) frame["IsTrack_reco"] = icetray.I3Bool(False) if frame["IsCascade_reco"].value == True and abs( frame["L5MonopodFit4"].pos.z) > 550.: return False if frame["IsHese"].value == True and frame[ "IsHESE_ck"].value == False and frame[ "CascadeFilter"].value == False: #and frame["L4VetoLayer1"].value<10: del frame["IsHese"] frame["IsHese"] = icetray.I3Bool(False) if frame["IsCascade"].value == True and frame[ "IsCascade_reco"].value == True and ( frame["L5MonopodFit4"].pos.z < -500 or frame["L5MonopodFit4"].pos.z > 500 or numpy.sqrt(frame["L5MonopodFit4"].pos.x * frame["L5MonopodFit4"].pos.x + frame["L5MonopodFit4"].pos.y * frame["L5MonopodFit4"].pos.y) > 550): print("Cascade event outside of detector... ", frame["I3EventHeader"].run_id, frame["I3EventHeader"].event_id) del frame["IsCascade"] frame["IsCascade"] = icetray.I3Bool(False) if frame["IsCascade"].value == True and frame[ "IsCascade_reco"].value == False and ( frame["L4VetoTrackMilliOfflineVetoCharge"].value > 2 or frame['L4VetoTrackMarginMilliOfflineSide'].value < 125): del frame["IsCascade"] frame["IsCascade"] = icetray.I3Bool(False) if frame["IsUpgoingMuon"].value == True: #print "UpMu event: ", frame["I3EventHeader"].run_id, frame["I3EventHeader"].event_id return True elif frame["IsHese"].value == True: print("HESE event: ", frame["I3EventHeader"].run_id, frame["I3EventHeader"].event_id) return True elif frame["IsCascade"].value == True and frame[ "L4VetoTrackOfflineVetoCharge"].value < 6 and frame[ "L4VetoTrackL5OfflineVetoCharge"].value < 2: #print "Cascade event: ", frame["I3EventHeader"].run_id, frame["I3EventHeader"].event_id return True elif frame["IsCascade"].value == True and frame[ "L4VetoTrackOfflineVetoCharge"].value < 2 and frame[ "L4VetoTrackL5OfflineVetoCharge"].value < 3: #print "Cascade event: ", frame["I3EventHeader"].run_id, frame["I3EventHeader"].event_id return True else: if ( ( frame['L4UpgoingTrackOfflineVetoCharge'].value > 10 and frame['L4UpgoingTrackOfflineVetoCharge'].value > \ frame['L4VetoTrackOfflineVetoCharge'].value and frame['L4UpgoingTrackOfflineVetoChannels'].value > 3 ) or \ ( frame['L4UpgoingTrackSplitVetoCharge'].value > 10 and frame['L4UpgoingTrackSplitVetoCharge'].value > \ frame['L4VetoTrackSplitVetoCharge'].value and frame['L4UpgoingTrackSplitVetoChannels'].value > 3 ) or \ ( frame['L4UpgoingTrackMilliOfflineVetoCharge'].value > 10 and frame['L4UpgoingTrackMilliOfflineVetoCharge'].value > \ frame['L4VetoTrackMilliOfflineVetoCharge'].value and frame['L4UpgoingTrackMilliOfflineVetoChannels'].value > 3 and \ frame['L4UpgoingTrackSplitVetoCharge'].value > 6 ) )\ and frame["TrackFit"].dir.zenith>1.5 and frame["MuonFilter"].value==True:# and frame["OnlineL2Filter"].value==True: del frame["IsUpgoingMuon"] del frame["IsCascade"] frame["IsUpgoingMuon"] = icetray.I3Bool(True) frame["IsCascade"] = icetray.I3Bool(False) #print "UpMu event!", frame["I3EventHeader"].run_id, frame["I3EventHeader"].event_id return True else: return False tray.Add(printy, streams=[icetray.I3Frame.Physics]) def bug_filter(frame): #if frame["I3EventHeader"].run_id==16 and frame["I3EventHeader"].event_id==17967: # return False #if frame["I3EventHeader"].run_id==16780 and frame["I3EventHeader"].event_id==34774: # return False print(frame["I3EventHeader"].run_id, frame["I3EventHeader"].event_id) tray.Add(bug_filter, streams=[icetray.I3Frame.DAQ, icetray.I3Frame.Physics]) tray.AddModule('I3MuonGun::WeightCalculatorModule', 'MuonWeight_Hoerandel5', Model=MuonGun.load_model('Hoerandel5_atmod12_SIBYLL'), Generator=generator) tray.AddModule('I3MuonGun::WeightCalculatorModule', 'MuonWeight_GaisserH4a', Model=MuonGun.load_model('GaisserH4a_atmod12_SIBYLL'), Generator=generator)
tray = I3Tray() tray.AddService('I3GSLRandomServiceFactory', 'rng') if infiles[0].endswith('.i3.bz2'): tray.AddModule('I3Reader', 'reader', filenamelist=infiles) else: tray.AddModule( 'I3CORSIKAReader', 'reader', filenamelist=infiles, NEvents=opts.nevents, CylinderHeight=0, CylinderRadius=0, ParticlesToWrite=MuonGun.I3ParticleTypeSeries( [dataclasses.I3Particle.MuMinus, dataclasses.I3Particle.MuPlus]), ) tray.AddModule( 'Muonitron', 'propatron', Depths=list(numpy.linspace(1.0, 4.5, 8) * I3Units.km), # Depths=list(numpy.arange(0.1, 1.0, 0.1)*I3Units.km), MMC=MMCFactory(), CylinderHeight=10. * I3Units.m, ) def printy(frame): #mctree = frame['I3MCTree'] #print mctree.primaries[0]
def main(cfg, run_number, scratch): with open(cfg, 'r') as stream: if int(yaml.__version__[0]) < 5: # backwards compatibility for yaml versions before version 5 cfg = yaml.load(stream) else: cfg = yaml.full_load(stream) cfg['run_number'] = run_number cfg['run_folder'] = get_run_folder(run_number) tray = I3Tray() random_services, _ = create_random_services( dataset_number=cfg['dataset_number'], run_number=cfg['run_number'], seed=cfg['seed'], n_services=2) random_service, random_service_prop = random_services tray.context['I3RandomService'] = random_service model = MuonGun.load_model(cfg['muongun_model']) model.flux.min_multiplicity = cfg['muongun_min_multiplicity'] model.flux.max_multiplicity = cfg['muongun_max_multiplicity'] spectrum = MuonGun.OffsetPowerLaw(cfg['gamma'], cfg['e_min'] * icetray.I3Units.GeV, cfg['e_min'] * icetray.I3Units.GeV, cfg['e_max'] * icetray.I3Units.GeV) surface = MuonGun.Cylinder(1600, 800, dataclasses.I3Position(31.25, 19.64, 0)) if cfg['muongun_generator'] == 'energy': scale = MuonGun.BasicSurfaceScalingFunction() scale.SetSideScaling(4., 17266, 3.41, 1.74) scale.SetCapScaling(4., 23710, 3.40, 1.88) generator = MuonGun.EnergyDependentSurfaceInjector( surface, model.flux, spectrum, model.radius, scale) elif cfg['muongun_generator'] == 'static': generator = MuonGun.StaticSurfaceInjector(surface, model.flux, spectrum, model.radius) elif cfg['muongun_generator'] == 'floodlight': generator = MuonGun.Floodlight( surface=surface, energyGenerator=spectrum, cosMin=cfg['muongun_floodlight_min_cos'], cosMax=cfg['muongun_floodlight_max_cos'], ) else: err_msg = 'MuonGun generator {} is not known.' err_msg += " Must be 'energy','static' or 'floodlight" raise ValueError(err_msg.format(cfg['muongun_generator'])) tray.Add(MuonGun.segments.GenerateBundles, 'MuonGenerator', Generator=generator, NEvents=cfg['n_events_per_run'], GCDFile=cfg['gcd']) tray.Add("Rename", keys=["I3MCTree", "I3MCTree_preMuonProp"]) tray.AddSegment(segments.PropagateMuons, "PropagateMuons", RandomService=random_service_prop, **cfg['muon_propagation_config']) if scratch: outfile = cfg['scratchfile_pattern'].format(**cfg) else: outfile = cfg['outfile_pattern'].format(**cfg) outfile = outfile.replace(' ', '0') if cfg['distance_splits'] is not None: click.echo('SplittingDistance: {}'.format(cfg['distance_splits'])) distance_splits = np.atleast_1d(cfg['distance_splits']) dom_limits = np.atleast_1d(cfg['threshold_doms']) if len(dom_limits) == 1: dom_limits = np.ones_like(distance_splits) * cfg['threshold_doms'] oversize_factors = np.atleast_1d(cfg['oversize_factors']) order = np.argsort(distance_splits) distance_splits = distance_splits[order] dom_limits = dom_limits[order] oversize_factors = oversize_factors[order] stream_objects = generate_stream_object(distance_splits, dom_limits, oversize_factors) tray.AddModule(OversizeSplitterNSplits, "OversizeSplitterNSplits", thresholds=distance_splits, thresholds_doms=dom_limits, oversize_factors=oversize_factors) for stream_i in stream_objects: outfile_i = stream_i.transform_filepath(outfile) tray.AddModule("I3Writer", "writer_{}".format(stream_i.stream_name), Filename=outfile_i, Streams=[ icetray.I3Frame.DAQ, icetray.I3Frame.Physics, icetray.I3Frame.Stream('S'), icetray.I3Frame.Stream('M') ], If=stream_i) click.echo('Output ({}): {}'.format(stream_i.stream_name, outfile_i)) else: click.echo('Output: {}'.format(outfile)) tray.AddModule("I3Writer", "writer", Filename=outfile, Streams=[ icetray.I3Frame.DAQ, icetray.I3Frame.Physics, icetray.I3Frame.Stream('S'), icetray.I3Frame.Stream('M') ]) click.echo('Scratch: {}'.format(scratch)) tray.AddModule("TrashCan", "the can") tray.Execute() tray.Finish()
def make_binner(): return MuonGun.TrackBinner(self.GetParameter("MinDepth"), self.GetParameter("MaxDepth"), self.GetParameter("DepthSteps"))
print DOM_file f = dataio.I3File(DOM_file) n_events = 0 for frame in f: if ("I3RecoPulseSeriesMapGen2" not in frame): continue if (n_events % 100 == 0): print "runing event: %s" % str(n_events) n_events += 1 #propagate muons to surface, if they dont intersect, throw the event away entering_muon_bool = todet(frame, surface_det) if not entering_muon_bool: continue #should we include this cut if len(frame["I3RecoPulseSeriesMapGen2"]) < 1: continue #sometimes no charge is even recorded #first store the event level info like weights energy zeniths etc... model = MuonGun.load_model('GaisserH4a_atmod12_SIBYLL') #natural rate muon = frame["MCMuon"] flux = model.flux(MuonGun.depth(muon.pos.z), np.cos( muon.dir.zenith), 1) * model.energy(MuonGun.depth( muon.pos.z), np.cos(muon.dir.zenith), 1, 0, muon.energy) weight = flux * frame['MuonEffectiveArea'].value energy = frame["EnteringMuon_0"].energy cos_zenith = np.cos(frame["EnteringMuon_0"].dir.zenith) area_eff = frame["MuonEffectiveArea"].value #now work on the triggers passes_cut = 0 times = [] ndom = 0 string_dom = "" spes_times = [] spes = []
def PolyplopiaSegment( tray, name, mctype='CORSIKA', RandomService=None, mctree_name="I3MCTree_preMuonProp", separate_coincident_mctree_name="", # leave empty to combine bgfile=None, timewindow=40. * I3Units.microsecond, rate=float('nan'), If=lambda f: True): """ There are three scenarios for polyplopia: 1. bgfile: We are reading background MC from a separate file and injecting events to signal (or weighted background) based on a Poisson distribution within the given time window. 2. we are generating MuonGun bundles and injecting events to signal (or weighted background) based on a Poisson distribution within the given time window. """ from icecube import polyplopia, MuonGun #tray.AddModule("ParticleMapper","mapprimary") if bgfile: # merge bg into signal background = polyplopia.CoincidentI3ReaderService(bgfile) else: # Use MuonGun # Default: use Hoerandel as a template for generating muons. model = MuonGun.load_model("Hoerandel5_atmod12_SIBYLL") #model = MuonGun.load_model('GaisserH4a_atmod12_SIBYLL') # Generate bundles (even if not 100 percent accurate). model.flux.max_multiplicity = 100 gamma_index = 2.6 energy_offset = 700. energy_min = 1e4 energy_max = 1e7 cylinder_length = 1600. cylinder_radius = 800. cylinder_x = 0. cylinder_y = 0. cylinder_z = 0. # Default: cylinder aligned with z-axis at detector center as injection # surface. outsurface_center = dataclasses.I3Position(cylinder_x * I3Units.m, cylinder_y * I3Units.m, cylinder_z * I3Units.m) outsurface = MuonGun.Cylinder(length=cylinder_length * I3Units.m, radius=cylinder_radius * I3Units.m, center=outsurface_center) generator = MuonGun.NaturalRateInjector(outsurface, model.flux, model.energy) background = polyplopia.MuonGunBackgroundService() background.set_generator(generator) background.set_rng(RandomService) background.set_rate(rate) background.set_mctree_name(mctree_name) tray.AddModule("PoissonMerger", "merge", CoincidentEventService=background, PrimaryType=mctype, MCTreeName=mctree_name, Rate=rate, SeparateMCTree=separate_coincident_mctree_name, TimeWindow=timewindow) return tray
def main(cfg, run_number, scratch): with open(cfg, 'r') as stream: cfg = yaml.load(stream, Loader=yaml.Loader) cfg['run_number'] = run_number cfg['run_folder'] = get_run_folder(run_number) infile = cfg['infile_pattern'].format(**cfg) infile = infile.replace(' ', '0') if scratch: outfile = cfg['scratchfile_pattern'].format(**cfg) else: outfile = cfg['outfile_pattern'].format(**cfg) outfile = outfile.replace(' ', '0') tray = I3Tray() """The main script""" tray.AddModule('I3Reader', 'i3 reader', FilenameList=[cfg['gcd'], infile]) detectorsurface = MuonGun.Cylinder( length=1600.*icetray.I3Units.m, radius=800.*icetray.I3Units.m, center=dataclasses.I3Position(0.*icetray.I3Units.m, 0.*icetray.I3Units.m, 0.*icetray.I3Units.m,)) # filter secondaries that are not in detector volume tray.AddModule(MuonRemoveChildren, 'MuonRemoveChildren', Detector=detectorsurface, Output='I3MCTree') #-------------------------------------------------- # Add MC Labels mirco trained his DNN on #-------------------------------------------------- add_cascade_labels = False if add_cascade_labels: tray.AddModule(modules.MCLabelsCascades, 'MCLabelsCascade', PulseMapString='InIcePulses', PrimaryKey='MCPrimary1', OutputKey='LabelsDeepLearning') else: tray.AddModule(modules.MCLabelsDeepLearning, 'MCLabelsDeepLearning', PulseMapString='InIcePulses', PrimaryKey='MCPrimary1', MCPESeriesMapName=cfg['mcpe_series_map'], OutputKey='LabelsDeepLearning', IsMuonGun=True) tray.AddModule("I3Writer", "EventWriter", filename=outfile, Streams=[icetray.I3Frame.DAQ, icetray.I3Frame.Physics, icetray.I3Frame.TrayInfo, icetray.I3Frame.Simulation], DropOrphanStreams=[icetray.I3Frame.DAQ]) tray.Execute() del tray
tray.Finish() book_weights(infiles, outfile) try: import tables, pylab, numpy hdf = tables.openFile(outfile) # We can get pre-calculated weights calcuated by the icetray module muon_energy = hdf.root.Muon.cols.energy[:] pre_weights = hdf.root.MuonWeight.cols.value[:] # or make a freestanding WeightCalculator with a different flux model model = MuonGun.load_model('GaisserH4a_atmod12_SIBYLL') generator = harvest_generators(infiles) weighter = MuonGun.WeightCalculator(model, generator) # and use the bundle axis and its radius/energy distribution to calculate a weight axis = hdf.root.MCPrimary.read() bundle = hdf.root.BundleParameters.read() post_weights = weighter(axis['x'], axis['y'], axis['z'], axis['zenith'], axis['azimuth'], bundle['multiplicity'], bundle['energy'], bundle['radius']) pylab.hist(muon_energy, bins=numpy.logspace(4, 7, 101), log=True, histtype='bar', label='unweighted (counts)')
def todet(frame, surface): detmu = MuonGun.muons_at_surface(frame, surface) #print "multi: " + str(len(detmu)) for i in range(len(detmu)): frame['EnteringMuon_' + str(i)] = detmu[i]
elif "9255" in filename: w /= 95000.0 elif "10282" in filename w /= 11200.0 elif "10309" in filename w /= 12200.0 elif "10369" in filename w /= 400.0 elif "11905" in filename w /= 90000.0 elif "12268" in filename w /= 96000.0 elif "12332" in filename w /= 99000.0 # Now, we want the primary. Let's get it primary = dataclasses.get_most_energetic_primary(frame["I3MCTree"]) muon = dataclasses.get_most_energetic_muon(frame["I3MCTree"]) # Propagate the muons muons to the MuonGun generating surface outSurface = Cylinder(1600*I3Units.m, 800*I3Units.m) partVec = MuonGun.muons_at_surface(frame, outSurface) muongun_energy = 1e-9 for p in partVec: if p.energy > muongun_energy: muongun_energy = p.energy weights.append(w) energy_of_primary.append(primary.energy) energy_at_depth.append(muongun_energy) coszens.append(numpy.cos(muon.dir.zenith)) code_of_primary.append(primary.pdg_encoding) if not id_1000160320 and primary.pdg_encoding == 1000160320: print '1000160320 = %s'%primary.type id_1000160320 = True if not id_1000080160 and primary.pdg_encoding == 1000080160:
#inner = MuonGun.Cylinder(700, 125, dataclasses.I3Position(29.3,52.6,-150)) #inner = outer #Most tested spectrum #spectrum = MuonGun.OffsetPowerLaw(5.0, 7e2, 0, 1e5) spectrum = MuonGun.OffsetPowerLaw(5.0, 7e2, 500, 1e5) #Limited spectrum range #spectrum = MuonGun.OffsetPowerLaw(5.2, 7e2, 150, 1e4) #spectrum = MuonGun.OffsetPowerLaw(2, 1*I3Units.TeV, 1*I3Units.TeV, 1*I3Units.PeV) #Good spectrum producing ~1 day with 10k evts above 200 GeV #spectrum = MuonGun.OffsetPowerLaw(5.2, 7e2, 200, 1e6) #Jackob's spectrum #spectrum = MuonGun.OffsetPowerLaw(5.0, 5e2, 200, 1e6) #Good spectrum producing ~1 day with 5000 evts above 400 GeV #spectrum = MuonGun.OffsetPowerLaw(5.25, 1000, 1, 1e6) model = MuonGun.load_model('/home/mamday/icesim/build/MuonGun/resources/tables/GaisserH4a_atmod12_SIBYLL') #gun = .365e4*MuonGun.EnergyDependentSurfaceInjector(outer, model.flux, spectrum, model.radius, gun = 5000*MuonGun.EnergyDependentSurfaceInjector(outer, model.flux, spectrum, model.radius, #gun = 680*MuonGun.EnergyDependentSurfaceInjector(outer, model.flux, spectrum, model.radius, MuonGun.ConstantSurfaceScalingFunction(inner)) def get_weight(weighter, energy, zenith=numpy.pi/8, scale=True): # def get_weight(weighter, energy, zenith=0, z=0): shape = energy.shape if scale: x = numpy.array([gun.target_surface(e).radius - 1 for e in energy]) else: # x = numpy.ones(shape[0])*surface.radius - 1 x = numpy.ones(shape[0])*surface.radius - 1
for k,v in sorted(vars(args).items()): print( " {0}: {1}".format(k,v)) print "------ end ------ " ######################### # I3 ######################### tray = I3Tray() ######################### # FLUX ######################### # Flux model model = MuonGun.load_model('GaisserH4a_atmod12_SIBYLL') #TODO Do we need a new fit to the latest CORSIKA (including SYBYLL 2.3c)??? model.flux.min_multiplicity = 1 model.flux.max_multiplicity = 1 # Check the spectral index is negative # This is for consistency with CORSIKA scripts # Will convert to a positve number (as MuonGun expects it) later assert args.power_law_index <= 0., "Spectral index must be negative" power_law_index = args.power_law_index positive_power_law_index = -1. * power_law_index # Muon spectrum (spectral index, break in power law, and energy range) power_law_offset = args.power_law_offset * icecube.icetray.I3Units.GeV min_energy = args.min_energy * icecube.icetray.I3Units.GeV max_energy = args.max_energy * icecube.icetray.I3Units.GeV spectrum = MuonGun.OffsetPowerLaw(
'$I3_TESTDATA/GCD/GeoCalibDetectorStatus_IC86.55697_corrected_V2.i3.gz' )) parser.add_argument("outfile", help="save plot to file") args = parser.parse_args() from icecube import icetray, dataclasses, dataio from icecube import phys_services, simclasses, MuonGun from I3Tray import I3Tray from os.path import expandvars tray = I3Tray() tray.context['I3RandomService'] = phys_services.I3GSLRandomService(1337) from icecube.MuonGun.segments import GenerateBundles outer = MuonGun.Cylinder(1600, 800) inner = MuonGun.Cylinder(300, 150, dataclasses.I3Position(0, 0, -350)) spectrum = MuonGun.OffsetPowerLaw(5, 1e3, 1e1, 1e4) model = MuonGun.load_model('GaisserH4a_atmod12_SIBYLL') generator = MuonGun.EnergyDependentSurfaceInjector( outer, model.flux, spectrum, model.radius, MuonGun.ConstantSurfaceScalingFunction(inner)) tray.AddSegment( GenerateBundles, 'BundleGen', NEvents=1000, Generator=generator, GCDFile=expandvars( '$I3_TESTDATA/GCD/GeoCalibDetectorStatus_IC86.55697_corrected_V2.i3.gz' ))
#!/usr/bin/env python from icecube import icetray, dataclasses, dataio from icecube import phys_services, sim_services, simclasses, MuonGun from I3Tray import I3Tray tray = I3Tray() tray.AddModule('I3InfiniteSource', 'driver') tray.AddService('I3GSLRandomServiceFactory', 'rng', Seed=1337) surface = MuonGun.Cylinder(1600, 800) flux = MuonGun.BMSSFlux() flux.min_multiplicity = 1 flux.max_multiplicity = 1 energies = MuonGun.BMSSEnergyDistribution() radii = MuonGun.BMSSRadialDistribution() generator = 10*MuonGun.StaticSurfaceInjector(surface, flux, MuonGun.OffsetPowerLaw(2, 500., 50, 1e6), radii) tray.AddModule('I3MuonGun::GeneratorModule', 'generator', Generator=generator) tray.AddModule('I3MuonGun::WeightCalculatorModule', 'weight', Model=MuonGun.BundleModel(flux, radii, energies), Generator=generator) def check_weight(frame): weight = frame['weight'].value assert weight > 0 tray.Add(check_weight, Streams=[icetray.I3Frame.DAQ]) tray.AddModule('TrashCan', 'YesWeCan') tray.Execute()
""" from argparse import ArgumentParser from os.path import expandvars parser = ArgumentParser() parser.add_argument("outfile", help="save plot to file") args = parser.parse_args() import matplotlib matplotlib.use('agg') import pylab, numpy from icecube import dataclasses, MuonGun surface = MuonGun.Cylinder(1600, 800) area = numpy.pi**2 * surface.radius * (surface.radius + surface.length) # 1 file of E^-2.6 5-component 3e4-1e9 GeV (3:2:1:1:1) soft = 4e5 * MuonGun.corsika_genprob('CascadeOptimized5Comp') # 1 file of E^-2 5-component 6e2-1e11 GeV (10:5:3:2:1) hard = 2.5e6 * MuonGun.corsika_genprob('Standard5Comp') # In order to compare to "unweighted" CORSIKA, turn the Hoerandel flux # into a probability (since we happen to know the integral) areanorm = 0.131475115 * area # 1 file of natural-spectrum ("unweighted") CORSIKA unweighted = (2.5e7 / areanorm) * MuonGun.corsika_genprob('Hoerandel5') model = MuonGun.load_model('GaisserH4a_atmod12_SIBYLL') model.flux.min_multiplicity = 1 model.flux.max_multiplicity = 1
def GenerateNeutrinos( tray, name, RandomService=None, NumEvents=100, SimMode='Full', VTXGenMode='NuGen', # currently only NuGen is supported InjectionMode='Surface', CylinderParams=[ 0, 0, 0, 0, 0 ], # CIRCLE[radius, active_height_before, active_height_after] SURFACE[radius, length, center_x, center_y, center_z] AutoExtendMuonVolume=True, Flavor="NuMu", GammaIndex=2.0, FromEnergy=1. * I3Units.TeV, ToEnergy=10. * I3Units.PeV, ZenithRange=[0, 180 * I3Units.degree], AzimuthRange=[0, 360 * I3Units.degree], CrossSections='csms', CrossSectionsPath=None, ParamsMap=dict()): from I3Tray import I3Units from icecube import icetray, dataclasses, dataio, phys_services, sim_services from icecube import neutrino_generator, MuonGun earthModelService = name + "_earthmodel" steering = name + "_steering" injector = name + "_injector" interactions = name + "_interactions" #----------------------------- # make ParamMap's key lowercase and # check multiple definitions. #----------------------------- params = dict() for key in ParamsMap: keylower = key.lower() if keylower in params: raise Exception('param %s is set twice!' % (keylower)) params[keylower] = ParamsMap[key] #----------------------------- # configure earthmodel service #----------------------------- earthModelServiceArgs = dict() if "earthmodels" in params: if not isinstance(params["earthmodels"], (list, tuple)): raise Exception('EarthModels must be a list of strings') earthModelServiceArgs['EarthModels'] = params["earthmodels"] if "materialmodels" in params: if not isinstance(params["materialmodels"], (list, tuple)): raise Exception('MaterialModels must be a list of strings') earthModelServiceArgs['MaterialModels'] = params["materialmodels"] if "earthparamspath" in params: if not isinstance(params["earthparamspath"], (str, unicode)): raise Exception('EarthParamsPath must be a strings') earthModelServiceArgs['PathToDataFileDir'] = params["earthparamspath"] if "icecaptype" in params: if not isinstance(params["icecaptype"], (str, unicode)): raise Exception('IceCapType must be a strings') earthModelServiceArgs['IceCapType'] = params["icecaptype"] if "icecapsimpleangle" in params: if not isinstance(params["icecapsimpleangle"], float): raise Exception('IceCapType must be a float') earthModelServiceArgs['IceCapSimpleAngle'] = params[ "icecapsimpleangle"] if "detectordepth" in params: if not isinstance(params["detectordepth"], float): raise Exception('DetectorDepth must be a float') earthModelServiceArgs['DetectorDepth'] = params["detectordepth"] tray.AddService("I3EarthModelServiceFactory", earthModelService, **earthModelServiceArgs) #----------------------------- # configure steering factory #----------------------------- # this is default cylinder. If you want to change cylinder size # and cylinder center, set positive value to CylinderParams. surface = MuonGun.Cylinder(1900 * I3Units.m, 950 * I3Units.m) steeringServiceArgs = dict() steeringServiceArgs['NEvents'] = NumEvents steeringServiceArgs['SimMode'] = SimMode steeringServiceArgs['VTXGenMode'] = VTXGenMode steeringServiceArgs['InjectionMode'] = InjectionMode steeringServiceArgs['DetectionSurface'] = surface steeringServiceArgs['CylinderParams'] = CylinderParams steeringServiceArgs['DoMuonRangeExtension'] = AutoExtendMuonVolume if "globalxsecscalefactor" in params: if not isinstance(params["globalxsecscalefactor"], (list, tuple)): raise Exception('GlobalXsecScaleFactor must be a list of float') steeringServiceArgs['GlobalXsecScaleFactor'] = params[ "globalxsecscalefactor"] tray.AddService("I3NuGSteeringFactory", steering, EarthModelName=earthModelService, **steeringServiceArgs) #----------------------------- # configure injector #----------------------------- EnergyLogRange = [ math.log10(FromEnergy / I3Units.GeV), math.log10(ToEnergy / I3Units.GeV) ] injectorServiceArgs = dict() injectorServiceArgs['NuFlavor'] = Flavor injectorServiceArgs['GammaIndex'] = GammaIndex injectorServiceArgs['ZenithMin'] = ZenithRange[0] injectorServiceArgs['ZenithMax'] = ZenithRange[1] injectorServiceArgs['AzimuthMin'] = AzimuthRange[0] injectorServiceArgs['AzimuthMax'] = AzimuthRange[1] injectorServiceArgs['EnergyMinLog'] = EnergyLogRange[0] injectorServiceArgs['EnergyMaxLog'] = EnergyLogRange[1] if "zenithweightparam" in params: if not isinstance(params["zenithweightparam"], float): raise Exception('ZenithWeightParam must be a float') injectorServiceArgs['ZenithWeightParam'] = params["zenithweightparam"] tray.AddService("I3NuGInjectorFactory", injector, SteeringName=steering, **injectorServiceArgs) #----------------------------- # configure interaction service #----------------------------- interactionServiceArgs = dict() if CrossSectionsPath is not None: interactionServiceArgs['TablesDir'] = CrossSectionsPath interactionServiceArgs['CrossSectionModel'] = CrossSections tray.AddService("I3NuGInteractionInfoFactory", interactions, SteeringName=steering, **interactionServiceArgs) #----------------------------- # configure neutrino generator #----------------------------- nugenArgs = dict() nugenArgs['MCTreeName'] = 'I3MCTree_preMuonProp' if "primarynuname" in params: if not isinstance(params["primarynuname"], (str, unicode)): raise Exception('PrimaryNuName must be a strings') nugenArgs['PrimaryNuName'] = params["primarynuname"] if "interactionweight" in params: if not isinstance(params["interactionweight"], (list, tuple)): raise Exception('InteractionWeight must be a list of float') nugenArgs['InteractionCCFactor'] = params["interactionweight"][0] nugenArgs['InteractionNCFactor'] = params["interactionweight"][1] nugenArgs['InteractionGRFactor'] = params["interactionweight"][2] if "propagationweightmode" in params: if not isinstance(params["propagationweightmode"], (str, unicode)): raise Exception('PropagationWeightMode must be a string') propmode = neutrino_generator.to_propagation_mode( params["propagationweightmode"]) nugenArgs['PropagationWeightMode'] = propmode tray.AddModule("I3NeutrinoGenerator", name + "_neutrino", SteeringName=steering, InjectorName=injector, InteractionInfoName=interactions, **nugenArgs)
def TabulatePhotonsFromSource(tray, name, PhotonSource="cascade", Zenith=0. * I3Units.degree, Azimuth=0. * I3Units.degree, ZCoordinate=0. * I3Units.m, Energy=1. * I3Units.GeV, FlasherWidth=127, FlasherBrightness=127, Seed=12345, NEvents=100, IceModel='spice_mie', DisableTilt=False, Filename="", TabulateImpactAngle=False, PhotonPrescale=1, Axes=None, Directions=None, Sensor='DOM', RecordErrors=False): """ Tabulate the distribution of photoelectron yields on IceCube DOMs from various light sources. The light profiles of the sources are computed from the same parameterizations used in PPC, but like in the direct propagation mode can be computed using GEANT4 instead. The mode of tabulation is controlled primarily by the **PhotonSource** parameter. - *'cascade'* will simulate an electromagnetic cascade of **Energy** GeV at (0, 0, **ZCoordinate**), oriented according to **Zenith** and **Azimuth**. The default coordinate system is spherical and centered the given vertex, with 200 quadratically spaced bins in radius, 36 linear bins in azimuthal angle (only from 0 to 180 degrees by default), 100 linear bins in the cosine of the polar angle, and 105 quadratic bins in time residual w.r.t the direct path from (0, 0, **ZCoordinate**). - *'flasher'* will simulate a 405 nm LED flasher pulse with the given **FlasherWidth** and **FlasherBrightness** settings. The source position and coordinate system are the same as for the 'cascade' case. - *'infinite-muon'* will simulate a "bare" muon of infinite length. The coordinate system is cylindrical and centered on the axis of the muon. Since the muon's position is degenerate with time, the usual parallel distance is replaced by the z coordinate of the closest approach to the detection position, and the starting positions of the simulated muons are sampled randomly (**ZCoordinate** is ignored). There are 100 quadratic bins in perpendicular distance to the source axis, 36 linear bins in azimuthal angle (0 to :math:`\pi` radians), 100 linear bins in z coordinate of closest approach, and 105 quadratic bins in time residual w.r.t. the earliest possible Cherenkov photon. :param PhotonSource: the type of photon source ('cascade', 'flasher', or 'infinite-muon'). :param Zenith: the orientation of the source :param ZCoordinate: the depth of the source :param Energy: the energy of the source (only for cascade tables) :param FlasherWidth: the width of the flasher pulse (only for flasher tables) :param FlasherBrightness: the brightness of the flasher pulse (only for flasher tables) :param Seed: the seed for the random number service :param NEvents: the number of events to simulate :param RecordErrors: record the squares of weights as well (useful for error bars) :param IceModel: the path to an ice model in $I3_SRC/clsim/resources/ice. Likely values include: 'spice_mie' ppc-style SPICE-Mie parametrization 'photonics_spice_1/Ice_table.spice.i3coords.cos080.10feb2010.txt' Photonics-style SPICE1 table 'photonics_wham/Ice_table.wham.i3coords.cos094.11jul2011.txt' Photonics-style WHAM! table :param DisableTilt: if true, disable tilt in ice model :param Filename: the name of the FITS file to write :param TabulateImpactAngle: if True, tabulate the impact position of the photon on the DOM instead of weighting by the DOM's angular acceptance :param Axes: a subclass of :cpp:class:`clsim::tabulator::Axes` that defines the coordinate system. If None, an appropriate default will be chosen based on **PhotonSource**. :param Directions: a set of directions to allow table generation for multiple sources. If None, only one direction given by **Zenith** and **Azimuth** is used. """ # check sanity of args PhotonSource = PhotonSource.lower() if PhotonSource not in ['cascade', 'flasher', 'infinite-muon']: raise ValueError( "photon source %s is unknown. Please specify either 'cascade', 'flasher', or 'infinite-muon'" % PhotonSource) from icecube import icetray, dataclasses, dataio, phys_services, sim_services, clsim from os.path import expandvars # a random number generator randomService = phys_services.I3GSLRandomService(Seed) tray.AddModule("I3InfiniteSource", name + "streams", Stream=icetray.I3Frame.DAQ) tray.AddModule("I3MCEventHeaderGenerator", name + "gen_header", Year=2009, DAQTime=158100000000000000, RunNumber=1, EventID=1, IncrementEventID=True) if Directions is None: Directions = numpy.asarray([(Zenith, Azimuth)]) if PhotonSource in ('cascade', 'flasher', 'muon-segment'): if PhotonSource == 'muon-segment': ptype = I3Particle.ParticleType.MuMinus else: ptype = I3Particle.ParticleType.EMinus def reference_source(zenith, azimuth, scale): source = I3Particle() source.type = ptype source.energy = Energy * scale source.pos = I3Position(0., 0., ZCoordinate) source.dir = I3Direction(zenith, azimuth) source.time = 0. if PhotonSource == 'muon-segment': source.length = 3. else: source.length = 0. source.location_type = I3Particle.LocationType.InIce return source elif PhotonSource == 'infinite-muon': from icecube import MuonGun # pad depth to ensure that the track appears effectively infinite surface = MuonGun.Cylinder(1800, 800) # account for zenith-dependent distribution of track lengths length_scale = surface.area(dataclasses.I3Direction( 0, 0)) / surface.area(dataclasses.I3Direction(Zenith, 0)) ptype = I3Particle.ParticleType.MuMinus def reference_source(zenith, azimuth, scale): source = I3Particle() source.type = ptype source.energy = Energy * scale source.dir = I3Direction(zenith, azimuth) source.pos = surface.sample_impact_position( source.dir, randomService) crossings = surface.intersection(source.pos, source.dir) source.length = crossings.second - crossings.first source.time = 0. source.location_type = I3Particle.LocationType.InIce return source import copy class MakeParticle(icetray.I3Module): def __init__(self, ctx): super(MakeParticle, self).__init__(ctx) self.AddOutBox("OutBox") self.AddParameter("SourceFunction", "", lambda: None) self.AddParameter("NEvents", "", 100) def Configure(self): self.reference_source = self.GetParameter("SourceFunction") self.nevents = self.GetParameter("NEvents") self.emittedEvents = 0 def DAQ(self, frame): if PhotonSource != "flasher": primary = I3Particle() mctree = I3MCTree() mctree.add_primary(primary) for zenith, azimuth in Directions: source = self.reference_source(zenith, azimuth, 1. / len(Directions)) mctree.append_child(primary, source) frame["I3MCTree"] = mctree # use the emitting particle as a geometrical reference frame["ReferenceParticle"] = source else: pulseseries = I3CLSimFlasherPulseSeries() for zenith, azimuth in Directions: pulse = makeFlasherPulse(0, 0, ZCoordinate, zenith, azimuth, FlasherWidth, FlasherBrightness, 1. / len(Directions)) pulseseries.append(pulse) frame["I3FlasherPulseSeriesMap"] = pulseseries frame["ReferenceParticle"] = self.reference_source( Zenith, Azimuth, 1.) self.PushFrame(frame) self.emittedEvents += 1 if self.emittedEvents >= self.nevents: self.RequestSuspension() tray.AddModule(MakeParticle, SourceFunction=reference_source, NEvents=NEvents) if PhotonSource == "flasher": flasherpulse = "I3FlasherPulseSeriesMap" mctree = None else: flasherpulse = None mctree = "I3MCTree" header = dict(FITSTable.empty_header) header['zenith'] = Zenith / I3Units.degree header['azimuth'] = Azimuth / I3Units.degree header['z'] = ZCoordinate header['energy'] = Energy header['type'] = int(ptype) header['efficiency'] = Efficiency.RECEIVER | Efficiency.WAVELENGTH if PhotonSource == 'infinite-muon': header['n_events'] = length_scale * NEvents / float(PhotonPrescale) if Axes is None: if PhotonSource != "infinite-muon": dims = [ clsim.tabulator.PowerAxis(0, 580, 200, 2), clsim.tabulator.LinearAxis(0, 180, 36), clsim.tabulator.LinearAxis(-1, 1, 100), clsim.tabulator.PowerAxis(0, 7e3, 105, 2), ] geo = clsim.tabulator.SphericalAxes else: dims = [ clsim.tabulator.PowerAxis(0, 580, 100, 2), clsim.tabulator.LinearAxis(0, numpy.pi, 36), clsim.tabulator.LinearAxis(-8e2, 8e2, 80), clsim.tabulator.PowerAxis(0, 7e3, 105, 2), ] geo = clsim.tabulator.CylindricalAxes # Add a dimension for the impact angle if TabulateImpactAngle: dims.append(clsim.tabulator.LinearAxis(-1, 1, 20)) Axes = geo(dims) if PhotonSource == "flasher": header['flasherwidth'] = FlasherWidth header['flasherbrightness'] = FlasherBrightness # some constants DOMRadius = 0.16510 * icetray.I3Units.m # 13" diameter referenceArea = dataclasses.I3Constants.pi * DOMRadius**2 # NB: GetIceCubeDOMAcceptance() calculates the quantum efficiency by # dividing the geometric area (a circle of radius domRadius) by the # tabulated effective area. Scaling that radius by *sqrt(prescale)* # _reduces_ the effective quantum efficiency by a factor *prescale*. # Since we draw photons directly from the QE-weighted Cherenkov # spectrum, this causes *prescale* fewer photons to be progagated per # light source. We compensate by dividing the number of events by # *prescale* in the header above. # to be propagated per light source. domAcceptance = clsim.GetIceCubeDOMAcceptance( domRadius=math.sqrt(PhotonPrescale) * DOMRadius) if Sensor.lower() == 'dom': angularAcceptance = clsim.GetIceCubeDOMAngularSensitivity(holeIce=True) elif Sensor.lower() == 'degg': referenceArea = dataclasses.I3Constants.pi * (300. * I3Units.mm / 2)**2 angularAcceptance = Gen2Sensors.GetDEggAngularSensitivity(pmt='both') domAcceptance = Gen2Sensors.GetDEggAcceptance(active_fraction=1. / PhotonPrescale) elif Sensor.lower() == 'wom': # outer diameter of the pressure vessel is 11.4 cm, walls are 9 mm thick referenceArea = (11 - 2 * 0.9) * 90 * icetray.I3Units.cm2 angularAcceptance = Gen2Sensors.GetWOMAngularSensitivity() domAcceptance = Gen2Sensors.GetWOMAcceptance(active_fraction=1. / PhotonPrescale) else: raise ValueError("Don't know how to simulate %ds yet" % (sensor)) tray.AddSegment( I3CLSimTabulatePhotons, name + "makeCLSimPhotons", MCTreeName= mctree, # if source is a cascade this will point to the I3MCTree FlasherPulseSeriesName= flasherpulse, # if source is a flasher this will point to the I3CLSimFlasherPulseSeries MMCTrackListName=None, # do NOT use MMC ParallelEvents= 1, # only work at one event at a time (it'll take long enough) RandomService=randomService, # UnWeightedPhotons=True, UseGPUs= False, # table-making is not a workload particularly suited to GPUs UseCPUs=True, # it should work fine on CPUs, though Area=referenceArea, WavelengthAcceptance=domAcceptance, AngularAcceptance=angularAcceptance, DoNotParallelize=True, # no multithreading UseGeant4=False, OverrideApproximateNumberOfWorkItems= 1, # if you *would* use multi-threading, this would be the maximum number of jobs to run in parallel (OpenCL is free to split them) ExtraArgumentsToI3CLSimModule=dict(Filename=Filename, TableHeader=header, Axes=Axes, PhotonsPerBunch=200, EntriesPerPhoton=5000, RecordErrors=RecordErrors), MediumProperties=parseIceModel( expandvars("$I3_SRC/clsim/resources/ice/" + IceModel), disableTilt=DisableTilt), )
else: outfile = sys.argv[1] tray = I3Tray() from clsim_server.client_module import GPU_Client from icecube import MuonGun, sim_services from icecube.icetray import I3Units from icecube.dataclasses import * from icecube.sim_services.propagation import get_propagators from icecube.MuonGun.segments import GenerateBundles from icecube.MuonGun import load_model, EnergyDependentSurfaceInjector, ConstantSurfaceScalingFunction, StaticSurfaceInjector, Cylinder, OffsetPowerLaw # base = expandvars('$I3_SRC/MuonGun/resources/scripts/fitting/') #Flux model model = MuonGun.load_model('GaisserH4a_atmod12_SIBYLL') model.flux.min_multiplicity = 1 model.flux.max_multiplicity = 1 #Inner and outher target surfaces outSurface = Cylinder(1600 * I3Units.m, 800 * I3Units.m) inSurface = Cylinder(500 * I3Units.m, 150 * I3Units.m, I3Position(46.3, -34.9, -300)) #Sets energy and spectral index of muons #Jackob's spectrum #spectrum = MuonGun.OffsetPowerLaw(5.0, 5e2, 200, 1e6) spectrum = MuonGun.OffsetPowerLaw(5.0, 7e2, int(sys.argv[2]), int(sys.argv[3])) #spectrum = MuonGun.OffsetPowerLaw(5.2, 7e2, 150, 1e5) #spectrum = MuonGun.OffsetPowerLaw(2, 1e3, 1e3, 1e5) #This version only aims at inSurface, but muons originate at outSurface scaling = MuonGun.ConstantSurfaceScalingFunction(inSurface)