"/event-viewer/Level3aGCD_IC79_EEData_Run00115990_slim.i3" app.files.openLocalFile(test_file) while app.files.framesAreProcessed: sleep(0.1) # steamshovel jumps to the first Physics frame automatically window.gl.perspectiveView = False window.gl.cameraLoc = (0, -1500, 0) window.gl.cameraPivot = (500, 500, 500) window.gl.cameraOrientation = (1.0, 1.0, 0.0) # add some extra particles for i, beta in enumerate((0.7, 0.8, 0.9, 1.0)): p = dcl.I3Particle() p.pos = dcl.I3Position(100 + 100 * i, 0, 0) p.dir = dcl.I3Direction(0, 0, 1) p.type = dcl.I3Particle.MuPlus p.speed = beta * dcl.I3Constants.c p.time = 38000 key = "p{:0.3f}".format(beta) frame[key] = p artist = scenario.add("Particles", [key]) scenario.changeSetting(artist, "arrow head size", 50.0) scenario.changeSetting(artist, "Cherenkov cone size", 100.0) scenario.add("CoordinateSystem", []) window.gl.screenshot(200, 200, "cherenkov_cone.png")
def Physics(self, frame): # get muon muon = mu_utils.get_muon( frame=frame, primary=frame[self._primary_key], convex_hull=self._convex_hull, ) labels = dataclasses.I3MapStringDouble() if self._write_vector: binned_energy_losses, bin_center_pos = \ mu_utils.get_binned_energy_losses_in_cube( frame=frame, muon=muon, bin_width=self._bin_width, boundary=self._boundary, return_bin_centers=self._write_vector ) else: binned_energy_losses = mu_utils.get_binned_energy_losses_in_cube( frame=frame, muon=muon, bin_width=self._bin_width, boundary=self._boundary, return_bin_centers=self._write_vector) # write to frame labels['track_anchor_x'] = muon.pos.x labels['track_anchor_y'] = muon.pos.y labels['track_anchor_z'] = muon.pos.z labels['track_anchor_time'] = muon.time labels['azimuth'] = muon.dir.azimuth labels['zenith'] = muon.dir.zenith for i, energy_i in enumerate(binned_energy_losses): # stop adding energy losses if we reached the maximum if self._max_num_bins is not None: if i >= self._max_num_bins: msg = 'MaxNumBinsis set to {}. '.format(self._max_num_bins) msg += 'Cutting off an additional {} losses!'.format( len(binned_energy_losses) - self._max_num_bins) log_warn(msg) break labels['EnergyLoss_{:05d}'.format(i)] = energy_i # pad rest with NaNs if self._max_num_bins is not None: for i in range(len(binned_energy_losses), self._max_num_bins): labels['EnergyLoss_{:05d}'.format(i)] = float('NaN') frame.Put(self._output_key, labels) if self._write_vector: part_vec = dataclasses.I3VectorI3Particle() for energy_i, pos_i in zip(binned_energy_losses, bin_center_pos): part = dataclasses.I3Particle() part.pos = dataclasses.I3Position(*pos_i) part.energy = energy_i part.dir = dataclasses.I3Direction(muon.dir) part.time = ((muon.pos - part.pos).magnitude / dataclasses.I3Constants.c) part_vec.append(part) frame.Put(self._output_key + 'ParticleVector', part_vec) self.PushFrame(frame)
# create new geometry object geometry = dataclasses.I3Geometry() # fill new geometry geometry.start_time = gcdHelpers.start_time geometry.end_time = gcdHelpers.end_time geometry.omgeo = dataclasses.I3OMGeoMap() # create spacing distortion spacing = gcdHelpers.generateSpacingList(spacing_type, basicSpacing, domsPerLine) stringNum = 1 xpos = -(domsPerLine - 1) / 2.0 * basicSpacing # centering position startPos = dataclasses.I3Position(xpos, ypos, zpos) direction = dataclasses.I3Direction(1, 0, 0) lineMap = gcdHelpers.generateDOMLine(stringNum, startPos, spacing, direction, verticalSpacing, domsPerLine, layers) geometry.omgeo.update(lineMap) # generate new frames gframe = icetray.I3Frame(icetray.I3Frame.Geometry) cframe = gcdHelpers.generateCFrame(geometry) dframe = gcdHelpers.generateDFrame(geometry) # add keys and values to G frame gframe["I3Geometry"] = geometry # push frames onto output file outfile.push(gframe) outfile.push(cframe)
print(mytrig) my_th = dataclasses.I3TriggerHierarchy() ## TriggerHierarchy is RO right now from the python side. print('Testing I3Constants') print('NA', dataclasses.I3Constants.NA) print('Coordinate_shift_x', dataclasses.I3Constants.Coordinate_shift_x) print('Coordinate_shift_y', dataclasses.I3Constants.Coordinate_shift_y) print('Coordinate_shift_z', dataclasses.I3Constants.Coordinate_shift_z) print('OriginElev', dataclasses.I3Constants.OriginElev) print('SurfaceElev', dataclasses.I3Constants.SurfaceElev) print('c', dataclasses.I3Constants.c) print('Testing I3Direction') dir = dataclasses.I3Direction(1.0, 1.0, 1.0) print("Directions!", dir.theta, dir.phi, dir.azimuth, dir.zenith) dir2 = dataclasses.I3Direction(1.0, 0.0, 0.0) print(dir2) dir2.rotate_z(90 * icetray.I3Units.deg) print(dir2) # Testing DOMFunctions print('Testing I3DOMFunctions') ds = dataclasses.I3DOMStatus() dc = dataclasses.I3DOMCalibration() transittime = dataclasses.transit_time(ds, dc)
def DAQ(self, frame): """Inject accompanying muons """ for i in range(self.n_frames_per_neutrino): # get I3MCTree mc_tree = dataclasses.I3MCTree(frame[self.mctree_name]) # primary particle primary = mc_tree.get_primaries()[0] # inject uncorrelated muon with arbitrary anchor point if self.uncorrelated_muon_settings is not None: primary = dataclasses.I3Particle(primary) x = self.random_service.uniform( *self.uncorrelated_muon_settings['anchor_x_range']) y = self.random_service.uniform( *self.uncorrelated_muon_settings['anchor_y_range']) z = self.random_service.uniform( *self.uncorrelated_muon_settings['anchor_z_range']) t = self.random_service.uniform( *self.uncorrelated_muon_settings['time_range']) azimuth = self.random_service.uniform(*np.deg2rad( self.uncorrelated_muon_settings['azimuth_range'])) zenith = self.random_service.uniform(*np.deg2rad( self.uncorrelated_muon_settings['zenith_range'])) primary.pos = dataclasses.I3Position(x, y, z) primary.dir = dataclasses.I3Direction(zenith, azimuth) primary.time = t # compute entry point intersection_ts = mu_utils.get_muon_convex_hull_intersections( primary, convex_hull=detector.icecube_hull) if len(intersection_ts) == 0: # particle did not hit convex hull, use closest approach closest_position = I3Calculator.closest_approach_position( primary, dataclasses.I3Position(0., 0., 0.)) distance = mu_utils.get_distance_along_track_to_point( primary.pos, primary.dir, closest_position) else: distance = min(intersection_ts) # in order to not land exactly on the convex hull and potentially # cause issues for label generation, we will walk back a little # further for primary and muon injection distance -= 1 inj_pos = primary.pos + distance * primary.dir inj_time = primary.time + distance / dataclasses.I3Constants.c inj_dir = dataclasses.I3Direction(primary.dir) # inject new muon mc_tree, injection_info = self._create_mc_tree( inj_pos=inj_pos, inj_time=inj_time, inj_dir=inj_dir, ) # copy frame frame_copy = icetray.I3Frame(frame) # replace I3MCTree frame_copy[self.mctree_name + 'VetoMuon_preMuonProp'] = mc_tree # add info to frame injection_info['injection_counter'] = float(i) if self.uncorrelated_muon_settings is not None: injection_info['is_correlated'] = False else: injection_info['is_correlated'] = True frame_copy[self.output_key] = injection_info # push frame on to subsequent modules self.PushFrame(frame_copy)
#!/usr/bin/env python from I3Tray import I3Units from I3Tray import NaN from icecube import dataclasses as dc from icecube import icetray from icecube import PROPOSAL from icecube import simclasses ptype = dc.I3Particle.TauMinus propagator = PROPOSAL.I3PropagatorServicePROPOSAL(type=ptype) mu = dc.I3Particle() mu.type = ptype mu.pos = dc.I3Position(0, 0, 0) mu.dir = dc.I3Direction(0, 0) mu.energy = 100 * I3Units.TeV mu.time = 0 * I3Units.ns mu.location_type = dc.I3Particle.InIce mu_length = list() n_daughters = list() for i in range(10000): mu.length = NaN # returns None instead of an I3MMCTrack daughters = propagator.Propagate(mu) # length of daughters is always 1 mu_length.append(mu.length) n_daughters.append(len(daughters)) try:
# fill the geometry map omgeomap = geometry.omgeo domcalmap = calibration.dom_cal domstatusmap = detectorStatus.dom_status for i, pos in enumerate(omPositions): shiftedPos = pos shiftedPos[0] += options.XPOS*I3Units.m shiftedPos[1] += options.YPOS*I3Units.m shiftedPos[2] += options.ZPOS*I3Units.m omkey = omKeys[i] newomgeo = dataclasses.I3OMGeo() newomgeo.omtype = dataclasses.I3OMGeo.OMType.IceCube newomgeo.orientation = dataclasses.I3Orientation(dataclasses.I3Direction(0.,0.,-1.)) newomgeo.position = dataclasses.I3Position(shiftedPos[0], shiftedPos[1], shiftedPos[2]) omgeomap[omkey] = newomgeo newdomcal = dataclasses.I3DOMCalibration() newdomcal.relative_dom_eff = 1.0 domcalmap[omkey] = newdomcal newdomstatus = dataclasses.I3DOMStatus() newdomstatus.pmt_hv = 1345.*I3Units.V # some arbitrary setting: >0 and not NaN domstatusmap[omkey] = newdomstatus
minimizer.migrad() # record minimizer results in output file printOutFile.write("results:\n") printOutFile.write(str(minimizer.get_fmin()) + '\n') printOutFile.write(str(minimizer.values) + '\n') printOutFile.write('\n\n') solution = minimizer.values q = dataclasses.I3Position(solution['q_x'], solution['q_y'], solution['q_z']) phi = solution['phi'] * I3Units.deg theta = np.arccos(solution['u_z']) u = dataclasses.I3Direction( np.sin(theta) * np.cos(phi), np.sin(theta) * np.sin(phi), solution['u_z']) # record final q function breakdown in output file printQFunctor = QualityFunctor(frame, t_0, printout=True) printQFunctor(solution['q_x'], solution['q_y'], solution['q_z'], solution["u_z"], solution["phi"]) recoParticle = dataclasses.I3Particle() recoParticle.shape = dataclasses.I3Particle.InfiniteTrack # record on particle whether reconstruction was successful if minimizer.get_fmin()["is_valid"]: recoParticle.fit_status = dataclasses.I3Particle.OK else: recoParticle.fit_status = dataclasses.I3Particle.InsufficientQuality
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_BUILD/ice-models/resources/models. Likely values include: 'spice_mie' ppc-style SPICE-Mie parametrization :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=expandvars("$I3_SRC/ice-models/resources/models/angsens/as.h2-50cm")) 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_BUILD/ice-models/resources/models/" + IceModel), disableTilt=DisableTilt), )
def Process(self): gcd = dataio.I3File(self.gcdfile, 'R') while (gcd.more()): frame = gcd.pop_frame() self.PushFrame(frame) gcd.close() #now deliver artificial testcase #make a Q-frame Qframe = icetray.I3Frame(icetray.I3Frame.DAQ) Qeh = dataclasses.I3EventHeader() Qeh.start_time = (dataclasses.I3Time(2011, 0)) Qeh.end_time = (dataclasses.I3Time(2011, 2)) Qeh.run_id = 1 Qeh.event_id = 1 Qframe.Put("I3EventHeader", Qeh) Qrecomap = dataclasses.I3RecoPulseSeriesMap() recopulse1 = dataclasses.I3RecoPulse() recopulse1.time = 0. recopulse1.charge = 1. recopulse2 = dataclasses.I3RecoPulse() recopulse2.time = 100. recopulse2.charge = 1. Qrecomap[icetray.OMKey(1, 1)] = [recopulse1, recopulse2] Qrecomap[icetray.OMKey(2, 2)] = [recopulse1] Qrecomap[icetray.OMKey(3, 3)] = [recopulse1, recopulse2] Qrecomap[icetray.OMKey(4, 4)] = [recopulse1] Qrecomap[icetray.OMKey(5, 5)] = [recopulse1, recopulse2] Qrecomap[icetray.OMKey(6, 6)] = [recopulse1] Qrecomap[icetray.OMKey(7, 7)] = [recopulse1, recopulse2] Qrecomap[icetray.OMKey(8, 8)] = [recopulse1] Qframe.Put(OrgPulses, Qrecomap) Qframe.Put(SplitName + "SplitCount", icetray.I3Int(2)) Qframe.Put(SplitName + "ReducedCount", icetray.I3Int(0)) self.PushFrame(Qframe) #now make the first p-frame containing one I3RecoPulse P1frame = icetray.I3Frame(icetray.I3Frame.Physics) P1eh = dataclasses.I3EventHeader() P1eh.start_time = (dataclasses.I3Time(2011, 0)) P1eh.end_time = (dataclasses.I3Time(2011, 1)) P1eh.run_id = 1 P1eh.event_id = 1 P1eh.sub_event_stream = "split" P1eh.sub_event_id = 0 P1frame.Put("I3EventHeader", P1eh) P1recomap = dataclasses.I3RecoPulseSeriesMap() P1recomap[icetray.OMKey(1, 1)] = [recopulse1] P1recomap[icetray.OMKey(2, 2)] = [recopulse1] P1recomap[icetray.OMKey(3, 3)] = [recopulse1] P1recomap[icetray.OMKey(4, 4)] = [recopulse1] P1recomap[icetray.OMKey(5, 5)] = [recopulse1] P1recomap[icetray.OMKey(6, 6)] = [recopulse1] P1recomap[icetray.OMKey(7, 7)] = [recopulse1] P1recomap[icetray.OMKey(8, 8)] = [recopulse1] P1recomask = dataclasses.I3RecoPulseSeriesMapMask( Qframe, OrgPulses, P1recomap) P1frame.Put(SplitPulses, P1recomask) self.PushFrame(P1frame) #now make the second p-frame containing one I3RecoPulse P2frame = icetray.I3Frame(icetray.I3Frame.Physics) P2eh = dataclasses.I3EventHeader() P2eh.start_time = (dataclasses.I3Time(2011, 1)) P2eh.end_time = (dataclasses.I3Time(2011, 2)) P2eh.run_id = 1 P2eh.event_id = 1 P2eh.sub_event_stream = "split" P2eh.sub_event_id = 1 P2frame.Put("I3EventHeader", P2eh) P2recomap = dataclasses.I3RecoPulseSeriesMap() P2recomap[icetray.OMKey(1, 1)] = [recopulse2] P2recomap[icetray.OMKey(3, 3)] = [recopulse2] P2recomap[icetray.OMKey(5, 5)] = [recopulse2] P2recomap[icetray.OMKey(7, 7)] = [recopulse2] P2recomask = dataclasses.I3RecoPulseSeriesMapMask( Qframe, OrgPulses, P2recomap) P2frame.Put(SplitPulses, P2recomask) self.PushFrame(P2frame) Hframe = icetray.I3Frame(icetray.I3Frame.Physics) Heh = dataclasses.I3EventHeader() Heh.start_time = (dataclasses.I3Time(2011, 0)) Heh.end_time = (dataclasses.I3Time(2011, 2)) Heh.run_id = 1 Heh.event_id = 1 Heh.sub_event_stream = HypoName Heh.sub_event_id = 0 Hframe.Put("I3EventHeader", Heh) Hrecomap = dataclasses.I3RecoPulseSeriesMap() Hrecomap[icetray.OMKey(1, 1)] = [recopulse1, recopulse2] Hrecomap[icetray.OMKey(2, 2)] = [recopulse1] Hrecomap[icetray.OMKey(3, 3)] = [recopulse1, recopulse2] Hrecomap[icetray.OMKey(4, 4)] = [recopulse1] Hrecomap[icetray.OMKey(5, 5)] = [recopulse1, recopulse2] Hrecomap[icetray.OMKey(6, 6)] = [recopulse1] Hrecomap[icetray.OMKey(7, 7)] = [recopulse1, recopulse2] Hrecomap[icetray.OMKey(8, 8)] = [recopulse1] Hrecomask = dataclasses.I3RecoPulseSeriesMapMask( Qframe, OrgPulses, Hrecomap) Hframe.Put(SplitPulses, Hrecomask) Hcf = dataclasses.I3MapStringVectorDouble() Hcf["split"] = [0, 1] Hframe.Put("CS_CreatedFrom", Hcf) Hfit = dataclasses.I3Particle() Hfit.time = 0 Hfit.pos = dataclasses.I3Position(0., 0., 0.) Hfit.dir = dataclasses.I3Direction(0., 0.) Hfit.fit_status = dataclasses.I3Particle.OK Hframe.Put("HFit", Hfit) self.PushFrame(Hframe) self.RequestSuspension()
def Process(self): frame = icetray.I3Frame(icetray.I3Frame.DAQ) mctree = dataclasses.I3MCTree() ######################################################## # This muon should be removed by I3InIceCORSIKATrimmer # ######################################################## trimmed_muon = dataclasses.I3Particle() trimmed_muon.energy = 500 * I3Units.GeV trimmed_muon.type = dataclasses.I3Particle.MuMinus trimmed_muon.location_type = dataclasses.I3Particle.InIce ######################################################## # This muon should be kept by I3InIceCORSIKATrimmer # ######################################################## kept_muon = dataclasses.I3Particle() kept_muon.energy = 1. * I3Units.TeV kept_muon.type = dataclasses.I3Particle.MuMinus kept_muon.location_type = dataclasses.I3Particle.InIce kept_muon.dir = dataclasses.I3Direction(0, 0) ######################################################## # This neutrino can be kept or dropped # ######################################################## nu_mu = dataclasses.I3Particle() nu_mu.type = dataclasses.I3Particle.NuMu nu_mu.location_type = dataclasses.I3Particle.InIce ######################################################## # This neutrino can be kept or dropped # ######################################################## nu_e = dataclasses.I3Particle() nu_e.type = dataclasses.I3Particle.NuE nu_e.location_type = dataclasses.I3Particle.InIce ######################################################## # This neutrino can be kept or dropped # ######################################################## nu_tau = dataclasses.I3Particle() nu_tau.type = dataclasses.I3Particle.NuTau nu_tau.location_type = dataclasses.I3Particle.InIce ######################################################## # I3InIceCORSIKATrimmer claims it's removing newly # # childless parents, but really it's any childless # # parent that's not InIce. # ######################################################## mu_plus = dataclasses.I3Particle() mu_plus.type = dataclasses.I3Particle.MuPlus mu_plus.energy = 1. * I3Units.TeV mu_plus.location_type = dataclasses.I3Particle.InIce mu_plus.dir = dataclasses.I3Direction(0, 0) mctree.add_primary(trimmed_muon) mctree.add_primary(kept_muon) mctree.add_primary(nu_mu) mctree.add_primary(nu_e) mctree.add_primary(nu_tau) mctree.append_child(nu_tau, mu_plus) print(mctree) frame["I3MCTree"] = mctree self.PushFrame(frame)
import os print("Working out I3XMLOMKey2MBID service") infile = './phys-services/resources/mainboard_ids.xml.gz' ms = phys_services.I3XMLOMKey2MBID(infile) ambid = ms.get_mbid(icetray.OMKey(2, 2)) aom = ms.get_omkey(ambid) ENSURE(aom == icetray.OMKey(2, 2), "Failed to find the right om in I3XMLOMKey2MBID") print("Working out I3Calculator") part1 = dataclasses.I3Particle() part1.dir = dataclasses.I3Direction(1.0, 0.0, 0.0) part2 = dataclasses.I3Particle() part2.dir = dataclasses.I3Direction(0.0, 1.0, 0.0) anglediff = phys_services.I3Calculator.angle(part1, part2) print("Particle 1: %s" % part1.dir) print("Particle 2: %s" % part2.dir) print("Angle diff: %.2f degrees" % (anglediff / icetray.I3Units.deg)) print("Working out CutValues") ## This is just a dumb container. cv = phys_services.I3CutValues() cog_pos = dataclasses.I3Position(0.0, 0.0, 0.0) cv.cog = cog_pos cv.ldir = 500.5 * icetray.I3Units.m
def get_mc_tree_input_data_dict(frame, angle_bins, distance_bins, distance_cutoff, energy_cutoff, add_distance): allowed_types = [ dataclasses.I3Particle.NuclInt, dataclasses.I3Particle.PairProd, dataclasses.I3Particle.Brems, dataclasses.I3Particle.DeltaE, dataclasses.I3Particle.EMinus, dataclasses.I3Particle.EPlus, dataclasses.I3Particle.Hadrons, ] num_dist_bins = len(distance_bins) - 1 num_angle_bins = len(angle_bins) - 1 num_bins = 1 + add_distance + num_dist_bins * num_angle_bins # create empty data array for DOMs dom_data = np.zeros(shape=(86, 60, num_bins)) if add_distance: dom_data[..., 0] = float('inf') # walk through energy losses and calculate data for loss in frame['I3MCTree']: # skip energy loss if it is not one of the allowed types if (loss.type not in allowed_types or loss.energy < energy_cutoff or loss.pos.magnitude > 2000): continue # walk through DOMs and calculate data min_distance = float('inf') min_omkey = None for string in range(1, 87): for dom in range(1, 61): om_key = icetray.OMKey(string, dom) # get position of DOM dom_pos = frame['I3Geometry'].omgeo[om_key].position # calculate distance and opening angle to DOM diff = dom_pos - loss.pos diff_p = dataclasses.I3Particle() diff_p.dir = dataclasses.I3Direction(diff.x, diff.y, diff.z) angle = I3Calculator.angle(diff_p, loss) distance = diff.magnitude # sort loss energy to correct bin index index_angle = np.searchsorted(angle_bins, angle) - 1 index_dist = np.searchsorted(distance_bins, distance) - 1 # check if it is out of bounds out_of_bounds = False if index_angle < 0 or index_angle >= num_angle_bins: out_of_bounds = True if index_dist < 0 or index_dist >= num_dist_bins: out_of_bounds = True if not out_of_bounds: # calculate index index = add_distance + \ index_dist * num_angle_bins + index_angle assert index >= add_distance and index < num_bins - 1 # accumulate energy dom_data[om_key.string - 1, om_key.om - 1, index] += \ loss.energy # check if distance is closest so far if (add_distance and distance < dom_data[om_key.string - 1, om_key.om - 1, 0]): dom_data[om_key.string - 1, om_key.om - 1, 0] = distance if distance < min_distance: min_distance = distance min_omkey = om_key # add energy loss to closest DOM within distance_cutoff if loss.energy > energy_cutoff: if min_distance < distance_cutoff: dom_data[min_omkey.string - 1, min_omkey.om - 1, -1] += \ loss.energy # create constant lists bin_indices_list = range(num_bins) bin_exclusions = [] # create data dict data_dict = {} for string in range(1, 87): for dom in range(1, 61): om_key = icetray.OMKey(string, dom) bin_values = dom_data[om_key.string - 1, om_key.om - 1].tolist() # compress output bin_values_compressed = [] bin_indices_compressed = [] for v, i in zip(bin_values, bin_indices_list): if v > 1e-7: bin_values_compressed.append(v) bin_indices_compressed.append(i) if len(bin_values_compressed) > 0: data_dict[om_key] = (bin_values_compressed, bin_indices_compressed, bin_exclusions) return data_dict
def Process(self): gcd = dataio.I3File(self.gcdfile, 'R') while (gcd.more()): frame = gcd.pop_frame() if (frame.Stop == icetray.I3Frame.Geometry): geo = frame["I3Geometry"] self.PushFrame(frame) gcd.close() #now deliver artificial testcase #make a Q-frame Qrecomap = dataclasses.I3RecoPulseSeriesMap() recopulse1 = dataclasses.I3RecoPulse() recopulse1.time = 0. recopulse1.charge = 1. recopulse2 = dataclasses.I3RecoPulse() recopulse2.time = 1000. / I3Constants.c #=3335.ns recopulse2.charge = 2. Qrecomap[icetray.OMKey(26, 1)] = [recopulse1] Qrecomap[icetray.OMKey(27, 1)] = [recopulse1] Qrecomap[icetray.OMKey(35, 1)] = [recopulse1] Qrecomap[icetray.OMKey(37, 1)] = [recopulse1] Qrecomap[icetray.OMKey(45, 1)] = [recopulse1] Qrecomap[icetray.OMKey(46, 1)] = [recopulse1] Qrecomap[icetray.OMKey(26, 60)] = [recopulse2] Qrecomap[icetray.OMKey(27, 60)] = [recopulse2] Qrecomap[icetray.OMKey(35, 60)] = [recopulse2] Qrecomap[icetray.OMKey(37, 60)] = [recopulse2] Qrecomap[icetray.OMKey(45, 60)] = [recopulse2] Qrecomap[icetray.OMKey(46, 60)] = [recopulse2] Qframe = icetray.I3Frame(icetray.I3Frame.DAQ) Qeh = dataclasses.I3EventHeader() Qeh.start_time = (dataclasses.I3Time(2011, 0)) Qeh.end_time = (dataclasses.I3Time(2011, 2)) Qeh.run_id = 1 Qeh.event_id = 1 Qframe.Put("I3EventHeader", Qeh) Qframe.Put(OrgPulses, Qrecomap) Qframe.Put(SplitName + "SplitCount", icetray.I3Int(2)) Qframe.Put(SplitName + "ReducedCount", icetray.I3Int(0)) self.PushFrame(Qframe) #now make the first p-frame containing one I3RecoPulse P1frame = icetray.I3Frame(icetray.I3Frame.Physics) P1eh = dataclasses.I3EventHeader() P1eh.start_time = (dataclasses.I3Time(2011, 0)) P1eh.end_time = (dataclasses.I3Time(2011, 1)) P1eh.run_id = 1 P1eh.event_id = 1 P1eh.sub_event_stream = "split" P1eh.sub_event_id = 0 P1frame.Put("I3EventHeader", P1eh) P1recomap = dataclasses.I3RecoPulseSeriesMap() P1recomap[icetray.OMKey(26, 1)] = [recopulse1] P1recomap[icetray.OMKey(27, 1)] = [recopulse1] P1recomap[icetray.OMKey(35, 1)] = [recopulse1] P1recomap[icetray.OMKey(37, 1)] = [recopulse1] P1recomap[icetray.OMKey(45, 1)] = [recopulse1] P1recomap[icetray.OMKey(46, 1)] = [recopulse1] P1recomask = dataclasses.I3RecoPulseSeriesMapMask( Qframe, OrgPulses, P1recomap) P1frame.Put(SplitPulses, P1recomask) P1fit = dataclasses.I3Particle( dataclasses.I3Particle.ParticleShape.InfiniteTrack) P1fit.time = 0 - 455. * I3Units.ns P1fit.pos = geo.omgeo[icetray.OMKey(36, 1)].position P1fit.dir = dataclasses.I3Direction(0., 0.) #straight down P1fit.fit_status = dataclasses.I3Particle.OK P1frame.Put("Fit", P1fit) self.PushFrame(P1frame) #now make the second p-frame containing one I3RecoPulse P2frame = icetray.I3Frame(icetray.I3Frame.Physics) P2eh = dataclasses.I3EventHeader() P2eh.start_time = (dataclasses.I3Time(2011, 1)) P2eh.end_time = (dataclasses.I3Time(2011, 2)) P2eh.run_id = 1 P2eh.event_id = 1 P2eh.sub_event_stream = SplitName P2eh.sub_event_id = 1 P2frame.Put("I3EventHeader", P2eh) P2recomap = dataclasses.I3RecoPulseSeriesMap() P2recomap[icetray.OMKey(26, 60)] = [recopulse2] P2recomap[icetray.OMKey(27, 60)] = [recopulse2] P2recomap[icetray.OMKey(35, 60)] = [recopulse2] P2recomap[icetray.OMKey(37, 60)] = [recopulse2] P2recomap[icetray.OMKey(45, 60)] = [recopulse2] P2recomap[icetray.OMKey(46, 60)] = [recopulse2] P2recomask = dataclasses.I3RecoPulseSeriesMapMask( Qframe, OrgPulses, P2recomap) P2frame.Put(SplitPulses, P2recomask) P2fit = dataclasses.I3Particle( dataclasses.I3Particle.ParticleShape.InfiniteTrack) P2fit.time = 1000. / I3Constants.c - 455. * I3Units.ns P2fit.pos = geo.omgeo[icetray.OMKey(36, 60)].position P2fit.dir = dataclasses.I3Direction(0., 0.) #straight up P2fit.fit_status = dataclasses.I3Particle.OK P2frame.Put("Fit", P2fit) self.PushFrame(P2frame) Hframe = icetray.I3Frame(icetray.I3Frame.Physics) Heh = dataclasses.I3EventHeader() Heh.start_time = (dataclasses.I3Time(2011, 0)) Heh.end_time = (dataclasses.I3Time(2011, 2)) Heh.run_id = 1 Heh.event_id = 1 Heh.sub_event_stream = HypoName Heh.sub_event_id = 0 Hframe.Put("I3EventHeader", Heh) Hrecomap = dataclasses.I3RecoPulseSeriesMap() Hrecomap[icetray.OMKey(26, 1)] = [recopulse1] #ring top Hrecomap[icetray.OMKey(27, 1)] = [recopulse1] Hrecomap[icetray.OMKey(35, 1)] = [recopulse1] Hrecomap[icetray.OMKey(37, 1)] = [recopulse1] Hrecomap[icetray.OMKey(45, 1)] = [recopulse1] Hrecomap[icetray.OMKey(46, 1)] = [recopulse1] Hrecomap[icetray.OMKey(26, 60)] = [recopulse2] #ring bottom Hrecomap[icetray.OMKey(27, 60)] = [recopulse2] Hrecomap[icetray.OMKey(35, 60)] = [recopulse2] Hrecomap[icetray.OMKey(37, 60)] = [recopulse2] Hrecomap[icetray.OMKey(45, 60)] = [recopulse2] Hrecomap[icetray.OMKey(46, 60)] = [recopulse2] Hrecomask = dataclasses.I3RecoPulseSeriesMapMask( Qframe, OrgPulses, Hrecomap) Hframe.Put(SplitPulses, Hrecomask) Hcf = dataclasses.I3MapStringVectorDouble() Hcf["split"] = [0, 1] Hframe.Put("CS_CreatedFrom", Hcf) Hfit = dataclasses.I3Particle( dataclasses.I3Particle.ParticleShape.InfiniteTrack) Hfit.time = -454. * I3Units.ns Hfit.pos = geo.omgeo[icetray.OMKey(36, 1)].position Hfit.dir = dataclasses.I3Direction(0., 0.) Hfit.fit_status = dataclasses.I3Particle.OK Hframe.Put("HFit", Hfit) self.PushFrame(Hframe) self.RequestSuspension()
from icecube import PROPOSAL from icecube import simclasses import numpy as np import os import sys os.chdir(sys.path[0]) ptype = dc.I3Particle.STauMinus stau = dc.I3Particle() stau.type = ptype stau.pos = dc.I3Position(0, 0, 0) stau.dir = dc.I3Direction(0, 0) stau.energy = 100 * I3Units.TeV stau.time = 0 * I3Units.ns stau.location_type = dc.I3Particle.InIce propagator = PROPOSAL.I3PropagatorServicePROPOSAL( config_file="$I3_BUILD/PROPOSAL/resources/config_icesim.json") propagator.register_particletype(ptype) mu_length = list() n_daughters = list() primary_energy_epair = list() secondary_energy_epair = list()
def create_muon( azimuth_range=[0,360], zenith_range=[0,180], energy_range=[10000,10000], anchor_time_range=[9000,12000], anchor_x_range=[-400,400], anchor_y_range=[-400,400], anchor_z_range=[-400,400], length_to_go_back=2000, convex_hull=None, extend_past_hull=0., random_service=None, ): ''' Generates muon where energy, direction and position is uniformly sampled within given range. First samples direction and anchor point. Then calculates the vertex by going back along the track from the anchor point. The distance how far to go back along the track is given by length_to_go_back. If a convex_hull is given, length_to_go_back is ignored and instead, the intersection point with the convex hull will be used as a vertex. Optionally, the vertex can be moved further out. This is defined by extend_past_hull. azimuth_range: [min, max] in degree zenith_range: [min, max] in degree energy_range: [min, max] in GeV anchor_time_range: [min, max] in ns Approximate time when muon is in detector at the simulated anchor point anchor_i_range: [min, max] in m The anchor point coordinate i. Anchor point must be inside convex hull if given. length_to_go_back: float in m Length to go back along track from anchor point, e.g. how far away to set the vertex of the point convex_hull : scipy.spatial.ConvexHull defining the desired convex volume extend_past_hull: float in m Length to extend past convex hull random_service: random number service ''' #------ # sample direction and energy #------ azimuth = random_service.uniform(*azimuth_range) * I3Units.deg zenith = random_service.uniform(*zenith_range) * I3Units.deg energy = random_service.uniform(*energy_range) * I3Units.GeV # create particle muon = dataclasses.I3Particle() muon.speed = dataclasses.I3Constants.c muon.location_type = dataclasses.I3Particle.LocationType.InIce muon.type = dataclasses.I3Particle.ParticleType.MuMinus muon.dir = dataclasses.I3Direction(zenith,azimuth) muon.energy = energy * I3Units.GeV #------ # get anchor point and time in detector #------ anchor_x = random_service.uniform(*anchor_x_range) anchor_y = random_service.uniform(*anchor_y_range) anchor_z = random_service.uniform(*anchor_z_range) anchor = dataclasses.I3Position( anchor_x * I3Units.m, anchor_y * I3Units.m, anchor_z * I3Units.m) anchor_time = random_service.uniform(*anchor_time_range) * I3Units.ns #------ # calculate vertex #------ if not convex_hull is None: t_s = get_intersections(convex_hull, v_pos = (anchor_x, anchor_y, anchor_z), v_dir = (muon.dir.x, muon.dir.y, muon.dir.z), eps=1e-4) length_to_go_back = - t_s[t_s <= 0.0 ] assert len(length_to_go_back) == 1, 'Is anchor point within convex_hull?' length_to_go_back = length_to_go_back[0] # extend past convex hull length_to_go_back += extend_past_hull vertex = anchor - length_to_go_back*I3Units.m * muon.dir travel_time = length_to_go_back * I3Units.m / muon.speed vertex_time = anchor_time - travel_time * I3Units.ns muon.pos = vertex muon.time = vertex_time * I3Units.ns return muon
def _create_particles( self, zenith, azimuth, vertex, vertex_time, primary_energy, daughter_energy, hadron_energy, interaction_type, flavor, ): """Create primary and daughter particles """ primary = dataclasses.I3Particle() daughter = dataclasses.I3Particle() primary.time = vertex_time * I3Units.ns primary.dir = dataclasses.I3Direction(zenith, azimuth) primary.energy = primary_energy * I3Units.GeV primary.pos = vertex primary.speed = dataclasses.I3Constants.c # Assume the vertex position in range is in ice, so the primary is the # in ice neutrino that interacts primary.location_type = dataclasses.I3Particle.LocationType.InIce daughter.location_type = dataclasses.I3Particle.LocationType.InIce daughter.time = primary.time daughter.dir = primary.dir daughter.speed = primary.speed daughter.pos = primary.pos daughter.energy = daughter_energy * I3Units.GeV if interaction_type == 'cc' and flavor == 'numu': daughter.shape = dataclasses.I3Particle.InfiniteTrack else: daughter.shape = dataclasses.I3Particle.Cascade if flavor == 'numu': primary.type = dataclasses.I3Particle.ParticleType.NuMu if interaction_type == 'cc': daughter.type = dataclasses.I3Particle.ParticleType.MuMinus elif interaction_type == 'nc': daughter.type = dataclasses.I3Particle.ParticleType.NuMu elif flavor == 'nutau': primary.type = dataclasses.I3Particle.ParticleType.NuTau if interaction_type == 'cc': daughter.type = dataclasses.I3Particle.ParticleType.TauMinus elif interaction_type == 'nc': daughter.type = dataclasses.I3Particle.ParticleType.NuTau elif flavor == 'nue': primary.type = dataclasses.I3Particle.ParticleType.NuE if interaction_type == 'cc': daughter.type = dataclasses.I3Particle.ParticleType.EMinus elif interaction_type == 'nc': daughter.type = dataclasses.I3Particle.ParticleType.NuE else: raise ValueError(('particle_type {!r} not known or not ' + 'implemented'.format(self.particle_type))) # add hadrons hadrons = dataclasses.I3Particle() hadrons.energy = hadron_energy * I3Units.GeV hadrons.pos = daughter.pos hadrons.time = daughter.time hadrons.dir = daughter.dir hadrons.speed = daughter.speed hadrons.type = dataclasses.I3Particle.ParticleType.Hadrons hadrons.location_type = daughter.location_type hadrons.shape = dataclasses.I3Particle.Cascade return primary, daughter, hadrons
def get_cascade_of_primary_nu(frame, primary, convex_hull=None, extend_boundary=200, sanity_check=False): """Get cascade of a primary particle. The I3MCTree is traversed to find the first interaction inside the convex hull. Parameters ---------- frame : I3Frame Current I3Frame needed to retrieve I3MCTree primary : I3Particle Primary Nu Particle for which the cascade interaction is returned. convex_hull : scipy.spatial.ConvexHull, optional Defines the desired convex volume. If None, the IceCube detector volume is assumed. extend_boundary : float, optional Extend boundary of IceCube detector by this distance [in meters]. This option is only used if convex_hull is None, e.g. if the IceCube detector is used. sanity_check : bool, optional If true, the neutrino is obtained by two different methods and cross checked to see if results match. Returns ------- I3Particle, None Returns None if no cascade interaction exists inside the convex hull Returns the found cascade as an I3Particle. The returned I3Particle will have the vertex, direction and total visible energy (EM equivalent) of the cascade. In addition it will have the type of the interaction NEUTRINO. The visible energy is defined here as the sum of the EM equivalent energies of the daugther particles, unless these are neutrinos. Only energies of particles that have 'InIce' location_type are considered. This meas that energies from hadron daughter particles get converted to the EM equivalent energy. (Does not account for energy carried away by neutrinos of tau decay) float The total EM equivalent energy of the EM cascade. float The total EM equivalent energy of the hadronic cascade. float The total EM equivalent energy in muons and taus (tracks). """ neutrino = get_interaction_neutrino(frame, primary, convex_hull=convex_hull, extend_boundary=extend_boundary, sanity_check=sanity_check) if neutrino is None or not neutrino.is_neutrino: return None, None, None, None mctree = frame['I3MCTree'] # traverse I3MCTree until first interaction inside the convex hull is found daughters = mctree.get_daughters(neutrino) # ----------------------- # Sanity Checks # ----------------------- assert len(daughters) > 0, 'Expected at least one daughter!' # check if point is inside if convex_hull is None: point_inside = geometry.is_in_detector_bounds( daughters[0].pos, extend_boundary=extend_boundary) else: point_inside = geometry.point_is_inside(convex_hull, (daughters[0].pos.x, daughters[0].pos.y, daughters[0].pos.z)) assert point_inside, 'Expected interaction to be inside defined volume!' # ----------------------- # interaction is inside the convex hull/extension boundary: cascade found! # get cascade cascade = dataclasses.I3Particle(neutrino) cascade.shape = dataclasses.I3Particle.ParticleShape.Cascade cascade.dir = dataclasses.I3Direction(primary.dir) cascade.pos = dataclasses.I3Position(daughters[0].pos) cascade.time = daughters[0].time cascade.length = get_interaction_extension_length(frame, neutrino) # sum up energies for daughters if not neutrinos # tau can immediately decay in neutrinos which carry away energy # that would not be visible, this is currently not accounted for e_total, e_em, e_hadron, e_track = get_cascade_em_equivalent( mctree, neutrino) cascade.energy = e_total return cascade, e_em, e_hadron, e_track
def DAQ(self, frame): sample = sampleFromMap(self.the_map, self.random_state, ptype=self.particle_type, pos_sigma=self.pos_sigma) primary = dataclasses.I3Particle() daughter = dataclasses.I3Particle() primary.time = sample['time'] * I3Units.ns primary.dir = dataclasses.I3Direction(sample['zenith'], sample['azimuth']) primary.energy = sample['energy'] * I3Units.GeV primary.pos = dataclasses.I3Position(sample['posX'] * I3Units.m, sample['posY'] * I3Units.m, sample['posZ'] * I3Units.m) primary.speed = dataclasses.I3Constants.c primary.location_type = dataclasses.I3Particle.LocationType.Anywhere if self.particle_type == 'numu': primary.type = dataclasses.I3Particle.ParticleType.NuMu daughter.type = dataclasses.I3Particle.ParticleType.MuMinus elif self.particle_type == 'nutau': primary.type = dataclasses.I3Particle.ParticleType.NuTau daughter.type = dataclasses.I3Particle.ParticleType.TauMinus elif self.particle_type == 'nue': primary.type = dataclasses.I3Particle.ParticleType.NuE daughter.type = dataclasses.I3Particle.ParticleType.EMinus else: raise ValueError(('particle_type {} not known or not ' + 'implemented'.format(self.particle_type))) # Load xsec tables # Draw muon energy from xsec base_path = os.path.join('$I3_DATA', 'neutrino-generator', 'cross_section_data', 'csms_differential_v1.0') base_path = os.path.expandvars(base_path) cross_section = sim_services.I3CrossSection( os.path.join(base_path, 'dsdxdy_nu_CC_iso.fits'), os.path.join(base_path, 'sigma_nu_CC_iso.fits')) final_state_record = cross_section.sample_final_state( primary.energy, primary.type, self.random_service) daughter.energy = primary.energy * (1 - final_state_record.y) daughter.time = primary.time daughter.dir = primary.dir daughter.speed = primary.speed daughter.pos = dataclasses.I3Position(primary.pos.x, primary.pos.y, primary.pos.z) daughter.location_type = dataclasses.I3Particle.LocationType.InIce daughter.shape = dataclasses.I3Particle.InfiniteTrack # ################################################ # Add hadrons to the mctree with E_h = E_nu * y # # ################################################ hadrons = dataclasses.I3Particle() hadrons.energy = primary.energy - daughter.energy hadrons.pos = dataclasses.I3Position(primary.pos.x, primary.pos.y, primary.pos.z) hadrons.time = daughter.time hadrons.dir = daughter.dir hadrons.speed = daughter.speed hadrons.type = dataclasses.I3Particle.ParticleType.Hadrons hadrons.location_type = daughter.location_type hadrons.shape = dataclasses.I3Particle.Cascade # Fill primary and daughter particles into a MCTree mctree = dataclasses.I3MCTree() mctree.add_primary(primary) mctree.append_child(primary, daughter) mctree.append_child(primary, hadrons) frame["I3MCTree"] = mctree self.PushFrame(frame) self.events_done += 1 if self.events_done >= self.num_events: self.RequestSuspension()
def get_cascade_parameters(frame, primary, convex_hull, extend_boundary=200, write_mc_cascade_to_frame=True): """Get cascade parameters. Parameters ---------- frame : I3Frame Current I3Frame needed to retrieve I3MCTree primary : I3Particle Primary Nu Particle for which the cascade interaction is returned. convex_hull : scipy.spatial.ConvexHull, optional Defines the desired convex volume. Will be used to compute muon entry point for an entering muon. extend_boundary : float, optional Extend boundary of convex_hull by this distance [in meters]. Returns ------- I3MapStringDouble Cascade parameters of primary neutrino: x, y, z, t, azimuth, zenith, E """ labels = dataclasses.I3MapStringDouble() cascade, e_em, e_hadron, e_track = get_cascade_of_primary_nu( frame, primary, convex_hull=None, extend_boundary=extend_boundary, ) if cascade is None: # -------------------- # not a starting event # -------------------- muon = mu_utils.get_muon_of_inice_neutrino(frame) if muon is None: # -------------------- # Cascade interaction outside of defined volume # -------------------- cascade, e_em, e_hadron, e_track = get_cascade_of_primary_nu( frame, primary, convex_hull=None, extend_boundary=float('inf'), sanity_check=False, ) else: # ------------------------------ # NuMu CC Muon entering detector # ------------------------------ # set cascade parameters to muon entry information entry, time, energy = mu_utils.get_muon_entry_info( frame, muon, convex_hull) length = mu_utils.get_muon_track_length_inside(muon, convex_hull) cascade = dataclasses.I3Particle() cascade.pos.x = entry.x cascade.pos.y = entry.y cascade.pos.z = entry.z cascade.time = time cascade.energy = energy cascade.dir = dataclasses.I3Direction(muon.dir) cascade.length = length e_em = 0. e_hadron = 0. e_track = energy if write_mc_cascade_to_frame: frame['MCCascade'] = cascade labels['cascade_x'] = cascade.pos.x labels['cascade_y'] = cascade.pos.y labels['cascade_z'] = cascade.pos.z labels['cascade_t'] = cascade.time labels['cascade_energy'] = cascade.energy labels['cascade_azimuth'] = cascade.dir.azimuth labels['cascade_zenith'] = cascade.dir.zenith labels['cascade_max_extension'] = cascade.length # compute fraction of energy for each component: EM, hadronic, track labels['energy_fraction_em'] = e_em / cascade.energy labels['energy_fraction_hadron'] = e_hadron / cascade.energy labels['energy_fraction_track'] = e_track / cascade.energy return labels
def main(): for infile in infileList: for frame in infile: if SimAnalysis.passFrame(frame, domsUsed, hitThresh, domThresh, maxResidual, geometry.omgeo): frame = SimAnalysis.writeSigHitsMapToFrame( frame, domsUsed, hitThresh, domThresh, maxResidual, geometry.omgeo) t_0 = get_t_0(frame) initialGuess = calculateInitialGuess(frame, domsUsed, t_0) qFunctor = QualityFunctor(frame, t_0) initialGuessQ = qFunctor(initialGuess[0], initialGuess[1], initialGuess[2], initialGuess[3], initialGuess[4]) # record seed values for comparison printOutFile.write("initial guess: " + str(initialGuess) + ", \nvalue of Q: " + str(initialGuessQ) + '\n') minimizer = Minuit(qFunctor, q_x=initialGuess[0], q_y=initialGuess[1], q_z=initialGuess[2], u_z=initialGuess[3], phi=initialGuess[4], error_q_x=1, error_q_y=1, error_q_z=1, error_u_z=0.05, error_phi=1, errordef=1, limit_u_z=(-1, 1), limit_phi=(0, 360)) minimizer.migrad() # record minimizer results in output file printOutFile.write("results:\n") printOutFile.write(str(minimizer.get_fmin()) + '\n') printOutFile.write(str(minimizer.values) + '\n') printOutFile.write('\n\n') solution = minimizer.values q = dataclasses.I3Position(solution['q_x'], solution['q_y'], solution['q_z']) phi = solution['phi'] * I3Units.deg theta = np.arccos(solution['u_z']) u = dataclasses.I3Direction( np.sin(theta) * np.cos(phi), np.sin(theta) * np.sin(phi), solution['u_z']) # record final q function breakdown in output file printQFunctor = QualityFunctor(frame, t_0, printout=True) printQFunctor(solution['q_x'], solution['q_y'], solution['q_z'], solution["u_z"], solution["phi"]) recoParticle = dataclasses.I3Particle() recoParticle.shape = dataclasses.I3Particle.InfiniteTrack # record on particle whether reconstruction was successful if minimizer.get_fmin()["is_valid"]: recoParticle.fit_status = dataclasses.I3Particle.OK else: recoParticle.fit_status = dataclasses.I3Particle.InsufficientQuality recoParticle.dir = u recoParticle.speed = c recoParticle.pos = calculateVertex(q, u, t_0) recoParticle.time = 0 # include both linefit and improved recos for comparison frame.Put('ImprovedRecoParticle', recoParticle) frame.Put('LineFitRecoParticle', initialGuess[5]) outfile.push(frame) outfile.close() printOutFile.close()
cascade_position = (0, 0, 0) else: raise ValueError("Invalid value for argument cascade-position!") elif isinstance(args.cascade_position, tuple): if len(args.cascade_position) == 3: cascade_position = args.cascade_position else: raise ValueError("Invalid value for argument cascade-position!") print("---> Cascade position is:", cascade_position) p = dataclasses.I3Particle() p.type = p.EMinus p.energy = args.energy p.time = 0 p.pos = dataclasses.I3Position(*cascade_position) p.dir = dataclasses.I3Direction(0, 0) for i in range(1): stepGenerator.EnqueueLightSource(clsim.I3CLSimLightSource(p), 0) stepGenerator.EnqueueBarrier() photons = defaultdict(clsim.I3CLSimPhotonSeries) i = 0 while True: steps, markers, particleHistories, barrierWasReset = \ stepGenerator.GetConversionResultWithBarrierInfoAndMarkers() print('---> sending %d photons in bunch %d' % (sum( (s.num for s in steps)), i)) clsimer_CUDA.EnqueueSteps(steps, i)
def Physics(self, frame): if not self.input_pulses in frame: print 'CorridorCut: No pulse series with name: ' + self.input_pulses self.PushFrame(frame) return True if type(frame[self.input_pulses]) == dataclasses.I3RecoPulseSeriesMap: ic_pulses = frame.Get(self.input_pulses) elif type(frame[ self.input_pulses]) == dataclasses.I3RecoPulseSeriesMapMask: ic_pulses = frame[self.input_pulses].apply(frame) geometry = frame['I3Geometry'] if not self.santa in frame: noiseless_map = frame[self.noiseless_hs].apply(frame) # Get string with most hits noiseless_doms = zeros([len(noiseless_map), 4]) for domindex, one_dom in enumerate(noiseless_map): noiseless_doms[domindex, :] = [ self.stringx[one_dom[0].string], self.stringy[one_dom[0].string], geometry.omgeo[one_dom[0]].position.z, one_dom[1][0].time ] cogx = noiseless_doms[:, 0].mean() cogy = noiseless_doms[:, 1].mean() dist_to_hqstrings = sqrt((cogx - self.stringx[79:87])**2 + (cogy - self.stringy[79:87])**2) main_string = 79 + dist_to_hqstrings.argmin() if sqrt((cogx - self.stringx[36])**2 + (cogy - self.stringy[36])**2) > 180: print 'CorridorCut: CoG is too far from DC strings, skipping' frame[self.nchannel] = dataclasses.I3Double(0.) self.PushFrame(frame) return cogz = noiseless_doms[:, 2].mean() tini = noiseless_doms[:, 3].mean() else: santafit = frame[self.santa] main_string = santafit.string cogz = santafit.zc tini = santafit.tc if not main_string in self.dcstrings: print 'CorridorCut: Main string is not in inner DC, skipping' frame[self.nchannel] = dataclasses.I3Double(0.) self.PushFrame(frame) return # First put all of the pulses in a huge numpy array. If several in one dom, take earliest one final_zenith = None final_azimuth = None max_counts = 0 mc_error = 9e10 allpulses = zeros([len(ic_pulses), 8]) for index, onedom in enumerate(ic_pulses): charge = 0 for onehit in onedom[1]: charge += onehit.charge try: allpulses[index] = [ onedom[0].string, onedom[0].om, self.stringx[onedom[0].string], self.stringy[onedom[0].string], geometry.omgeo[onedom[0]].position.z, onedom[1][0].time, charge, 0. ] except: allpulses[index] = [ onedom[0].string, onedom[0].om, self.stringx[onedom[0].string], self.stringy[onedom[0].string], geometry.omgeo[onedom[0]].position.z, 10E9, 0., 0. ] allpulses = allpulses[allpulses[:, 5] < tini, :] if (len(allpulses) == 0): return True # For each event, one santa.string exists for az_index, azimuth in enumerate(self.anglesdict[main_string]): inrange_mask = array([False] * allpulses.shape[0]) # if(not(allpulses.shape[0]) or allpulses.shape[0]==0): # inrange_mask = ([False]) for p_index in range(0, allpulses.shape[0]): if allpulses[p_index, 0] in self.stringdict[main_string][az_index]: inrange_mask[p_index] = True pulses_in_range = allpulses[inrange_mask, :] for zenith in arange(0.05, 1.2, self.zenith_steps): # Calculate the distance of each hit to the track. x1 = zeros([1, 3]) x1[0, 0:2] = self.vertexdict[main_string] x1[0, 2] = cogz x2 = zeros([1, 3]) x2[0, 0:3] = [ sin(zenith) * cos(azimuth), sin(zenith) * sin(azimuth), cos(zenith) ] x2 = x1 + x2 * 600. pulses_dist = self.dist(pulses_in_range[:, 2:5], x1, x2) # Transforming coordinates new_theta = zenith - pi / 2 new_phi = mod((azimuth + pi), 2 * pi) # Direction ux = cos(new_theta) * cos(new_phi) uy = cos(new_theta) * sin(new_phi) uz = sin(new_theta) # Point of closest approach zc = (cogz - uz * (self.vertexdict[main_string][0] * ux + self.vertexdict[main_string][1] * uy + cogz * uz) + uz * (pulses_in_range[:, 2] * ux + pulses_in_range[:, 3] * uy) ) / (1 - uz**2) tc = tini + (pulses_in_range[:, 2] * ux + pulses_in_range[:, 3] * uy + cogz * uz - (self.vertexdict[main_string][0] * ux + self.vertexdict[main_string][1] * uy + cogz * uz) ) / (dataclasses.I3Constants.c * (1 - uz**2)) dc = sqrt((self.vertexdict[main_string][0] + dataclasses.I3Constants.c * ux * (tc - tini) - pulses_in_range[:, 2])**2 + (self.vertexdict[main_string][1] + dataclasses.I3Constants.c * uy * (tc - tini) - pulses_in_range[:, 3])**2) tarrival = self.tgamma(pulses_in_range[:, 4], uz, zc, dc, tc, tini, dataclasses.I3Constants.c, dataclasses.I3Constants.n_ice) timeres = tarrival - pulses_in_range[:, 5] mask = (-self.wminus < timeres) & (timeres < self.wplus) & ( pulses_dist < 130.) distpass = pulses_dist[mask] if distpass.shape[0] >= max_counts and distpass.shape[0] > 0: tr2 = sum(distpass**2) / distpass.shape[0] if distpass.shape[0] > max_counts or (distpass.shape[0] == max_counts and tr2 < mc_error): max_counts = distpass.shape[0] final_zenith = zenith final_azimuth = azimuth mc_error = tr2 veto_hits = pulses_in_range[mask, 0:2] if max_counts > 0: output_track = dataclasses.I3Particle() output_track.pos.x = self.vertexdict[main_string][0] output_track.pos.y = self.vertexdict[main_string][1] output_track.pos.z = cogz ccDir = dataclasses.I3Direction(final_zenith, final_azimuth) output_track.dir = ccDir output_track.time = tini frame[self.track] = output_track new_pulse_map = dataclasses.I3RecoPulseSeriesMapMask( frame, self.input_pulses) new_pulse_map.set_none() for one_hit in veto_hits: new_pulse_map.set( icetray.OMKey(int(one_hit[0]), int(one_hit[1])), True) frame[self.out_pulses] = new_pulse_map frame[self.nchannel] = dataclasses.I3Double(max_counts) self.PushFrame(frame)
for i in range(10000): particle = dataclasses.I3Particle() x = 0. * I3Units.m y = 0. * I3Units.m z = 0. * I3Units.m t = 0. * I3Units.s zenith = 0. * I3Units.deg azimuth = 270. * I3Units.deg e = 40000. * I3Units.GeV particle.type = dataclasses.I3Particle.ParticleType.Hadrons particle.location_type = dataclasses.I3Particle.LocationType.InIce particle.pos = dataclasses.I3Position(x, y, z) particle.time = t particle.dir = dataclasses.I3Direction(zenith, azimuth) particle.energy = e daughters = c.Propagate(particle, icetray.I3Frame()) nstochastics_l.append(len(daughters)) try: import pylab pylab.figure() pylab.title("Number of Stochastics") pylab.xlabel("N") pylab.hist(nstochastics_l, histtype="step", log=True) pylab.show()
# create new geometry object geometry = dataclasses.I3Geometry() # fill new geometry geometry.start_time = gcdHelpers.start_time geometry.end_time = gcdHelpers.end_time geometry.omgeo = dataclasses.I3OMGeoMap() # generate distortions offset = gcdHelpers.generateOffsetList(offset_type, linesPerLayer) spacing = gcdHelpers.generateSpacingList(spacing_type, basicSpacing, domsPerLine) # loop to create DOM lines for i in xrange(0, linesPerLayer): direction = dataclasses.I3Direction(np.cos(i * dphi), np.sin(i * dphi), 0) lineStart = dataclasses.I3Position(xpos + offset[i] * direction.x, ypos + offset[i] * direction.y, zpos) startingStringNum = 1 + i * domsPerLine lineMap = gcdHelpers.generateDOMLine(startingStringNum, lineStart, spacing, direction, verticalSpacing, domsPerLine, layers) geometry.omgeo.update(lineMap) # generate new frames gframe = icetray.I3Frame(icetray.I3Frame.Geometry) cframe = gcdHelpers.generateCFrame(geometry) dframe = gcdHelpers.generateDFrame(geometry) # add keys and values to G frame gframe["I3Geometry"] = geometry