summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsim.py132
1 files changed, 132 insertions, 0 deletions
diff --git a/sim.py b/sim.py
new file mode 100755
index 0000000..de219c8
--- /dev/null
+++ b/sim.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python
+import sys
+import optparse
+import time
+
+import detectors
+import optics
+import gpu
+import g4gen
+from io import root
+import numpy as np
+import math
+import ROOT
+
+def info(type, value, tb):
+ if hasattr(sys, 'ps1') or not sys.stderr.isatty():
+ # we are in interactive mode or we don't have a tty-like
+ # device, so we call the default hook
+ sys.__excepthook__(type, value, tb)
+ else:
+ import traceback, pdb
+ # we are NOT in interactive mode, print the exception...
+ traceback.print_exception(type, value, tb)
+ print
+ # ...then start the debugger in post-mortem mode.
+ pdb.pm()
+
+sys.excepthook = info
+
+if __name__ == '__main__':
+
+ parser = optparse.OptionParser('%prog')
+ parser.add_option('-b', type='int', dest='nbits', default=10)
+ parser.add_option('-j', type='int', dest='device', default=None)
+ parser.add_option('-n', type='int', dest='nblocks', default=64)
+
+ parser.add_option('--detector', type='string', dest='detector', default='microlbne')
+ parser.add_option('--nevents', type='int', dest='nevents', default=100)
+ parser.add_option('--particle', type='string', dest='particle', default='e-')
+ parser.add_option('--energy', type='float', dest='energy', default=100.0)
+ parser.add_option('--pos', type='string', dest='pos', default='(0,0,0)')
+ parser.add_option('--dir', type='string', dest='pos', default='(1,0,0)')
+
+ options, args = parser.parse_args()
+ if len(args) != 1:
+ print 'Must specify output filename!'
+ sys.exit(1)
+ else:
+ output_filename = args[0]
+
+ if options.nevents <= 0:
+ print '--nevents must be greater than 0!'
+ sys.exit(1)
+
+ position = np.array(eval(options.pos), dtype=float)
+ direction = np.array(eval(options.pos), dtype=float)
+ detector = detectors.find(options.detector)
+
+ print >>sys.stderr, 'Creating detector...'
+ detector.build(bits=options.nbits)
+
+ print >>sys.stderr, 'Initializing generator...'
+ detector_material = optics.water
+ generator = g4gen.G4Generator(detector_material)
+ print >>sys.stderr, 'WARNING: ASSUMING DETECTOR IS WATER!!'
+
+ print >>sys.stderr, 'Initializing GPU...'
+ gpu_worker = gpu.GPU(options.device)
+
+ print >>sys.stderr, 'Loading detector onto GPU...'
+ gpu_worker.load_geometry(detector)
+
+ print >>sys.stderr, 'Initializing random numbers generators...'
+ gpu_worker.setup_propagate()
+ gpu_worker.setup_daq(max(detector.pmtids))
+
+ # Create output file
+ f = ROOT.TFile(output_filename, 'RECREATE')
+ ev, T = root.make_tree('T')
+
+ print >>sys.stderr, 'Starting simulation...'
+ start_sim = time.time()
+ #### Do the generation and writing in this offset order to ensure
+ #### that propagation on the GPU overlaps with CPU work to create
+ #### and save photons.
+ #### WARNING: THIS MAKES THE CODE LOOK A LITTLE CRAZY. I AM SORRY
+
+ # Do first event
+ photons = generator.generate_photons(particle_name=options.particle,
+ total_energy=options.energy,
+ position=position,
+ direction=direction)
+ nphotons = len(photons['pos'])
+ gpu_worker.load_photons(**photons)
+ gpu_worker.propagate()
+ gpu_worker.run_daq()
+
+ for i in xrange(1, options.nevents-1):
+ # photons for next event while previous event propagates on GPU
+ photons = generator.generate_photons(particle_name=options.particle,
+ total_energy=options.energy,
+ position=position,
+ direction=direction)
+ nphotons += len(photons['pos'])
+
+ # this will stop and wait for event to finish
+ hit_times = gpu_worker.get_hits()
+
+ # turn around next event
+ gpu_worker.load_photons(**photons)
+ gpu_worker.propagate()
+ gpu_worker.run_daq()
+
+ # write out this event
+ root.fill_event(T, ev, i-1, position, len(hit_times), hit_times)
+
+ if i % 10 == 0:
+ print >>sys.stderr, "\rEvent:", i,
+
+ # Get results for last event and write it out
+ hit_times = gpu_worker.get_hits()
+ root.fill_event(T, ev, options.nevents - 1, position, len(hit_times), hit_times)
+
+ end_sim = time.time()
+ print >>sys.stderr, "\rEvent:", options.nevents - 1
+
+ T.Write()
+ f.Close()
+
+ print >>sys.stderr, 'Done. %1.1f events/sec, %1.0f photons/sec.' % (options.nevents/(end_sim - start_sim), nphotons/(end_sim - start_sim))
+
+ gpu_worker.shutdown()