summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--__init__.py8
-rwxr-xr-xchroma-sim87
-rw-r--r--event.py2
-rw-r--r--fileio/root.py24
-rw-r--r--generator/g4gen.py4
-rw-r--r--generator/vertex.py12
-rw-r--r--gpu.py25
-rw-r--r--itertoolset.py16
-rwxr-xr-xsim.py132
-rw-r--r--solids/__init__.py2
-rw-r--r--tests/test_fileio.py3
-rw-r--r--tests/test_pdf.py8
-rw-r--r--tests/test_propagation.py3
-rw-r--r--tests/test_rayleigh.py5
14 files changed, 157 insertions, 174 deletions
diff --git a/__init__.py b/__init__.py
index 07a096c..3359bbc 100644
--- a/__init__.py
+++ b/__init__.py
@@ -1,15 +1,15 @@
from camera import Camera, EventViewer, view, build
import geometry
import event
-import fileio
-#import generator
+from fileio import root
+import generator
import gpu
import itertoolset
-#import likelihood
+import likelihood
import make
import optics
import project
import sample
-#import sim
+from sim import Simulation
from stl import mesh_from_stl
import transform
diff --git a/chroma-sim b/chroma-sim
new file mode 100755
index 0000000..fa106a2
--- /dev/null
+++ b/chroma-sim
@@ -0,0 +1,87 @@
+#!/usr/bin/env python
+#--*-python-*-
+
+if __name__ == '__main__':
+ import optparse
+ import sys
+ import imp
+ import os
+ import inspect
+ import numpy as np
+
+ from chroma import event
+ from chroma import itertoolset
+ from chroma import Simulation
+ from chroma import root
+
+ parser = optparse.OptionParser('%prog <detector>')
+ parser.add_option('-o', dest='output_filename',
+ help='output filename', default='out.root')
+ parser.add_option('-j', type='int', dest='device',
+ help='CUDA device number', default=None)
+ parser.add_option('-s', type='int', dest='seed',
+ help='random number generator seed')
+ parser.add_option('-g', type='int', dest='ngenerators',
+ help='number of GEANT4 processes', default=4)
+ parser.add_option('-n', '--nevents', type='int', dest='nevents',
+ default=100)
+ parser.add_option('-p', '--particle', dest='particle',
+ help='particle name', default='e-')
+ parser.add_option('-k', '--ke', type='float', dest='ke',
+ help='kinetic energy (MeV)', default=100.0)
+ parser.add_option('--pos', dest='pos',
+ help='particle vertex origin', default='0,0,0')
+ parser.add_option('--dir', dest='dir',
+ help='particle vertex direction', default='1,0,0')
+ parser.add_option('--save-photons-beg', action='store_true',
+ dest='save_photons_beg',
+ help='save initial photons to disk', default=False)
+ parser.add_option('--save-photons-end', action='store_true',
+ dest='save_photons_end',
+ help='save final photons to disk', default=False)
+
+ options, args = parser.parse_args()
+
+ if len(args) < 1:
+ sys.exit(parser.format_help())
+
+ name, attr = args[0].split('.')
+
+ try:
+ file, path, description = imp.find_module(name)
+ except ImportError:
+ raise
+
+ module = imp.load_module(name, file, path, description)
+
+ detector = getattr(module, attr)
+
+ if inspect.isfunction(detector):
+ detector = detector()
+
+ pos = np.array([float(s) for s in options.pos.split(',')], dtype=float)
+ dir = np.array([float(s) for s in options.dir.split(',')], dtype=float)
+
+ vertex = event.Vertex(options.particle, pos, dir, options.ke)
+
+ sim = Simulation(detector, seed=options.seed, cuda_device=options.device,
+ geant4_processes=options.ngenerators)
+
+ print 'RNG seed: %i' % sim.seed
+
+ writer = root.RootWriter(options.output_filename)
+
+ for i, ev in \
+ enumerate(sim.simulate(itertoolset.repeatcopy(vertex,
+ options.nevents),
+ keep_photons_beg=options.save_photons_beg,
+ keep_photons_end=options.save_photons_end)):
+ print '\rEvent: %i' % (i+1),
+ sys.stdout.flush()
+
+ assert ev.nphotons > 0, 'Geant4 generated event with no photons!'
+
+ writer.write_event(ev)
+ print
+
+ writer.close()
diff --git a/event.py b/event.py
index f611edb..a2b99cc 100644
--- a/event.py
+++ b/event.py
@@ -1,7 +1,7 @@
import numpy as np
class Vertex(object):
- def __init__(self, particle_name, pos, dir, pol, ke, t0=0.0):
+ def __init__(self, particle_name, pos, dir, ke, t0=0.0, pol=None):
self.particle_name = particle_name
self.pos = pos
self.dir = dir
diff --git a/fileio/root.py b/fileio/root.py
index 507c249..af86deb 100644
--- a/fileio/root.py
+++ b/fileio/root.py
@@ -25,11 +25,11 @@ def make_photon_with_arrays(size):
def root_vertex_to_python_vertex(vertex):
"Returns a chroma.event.Vertex object from a root Vertex object."
return event.Vertex(str(vertex.particle_name),
- tvector3_to_ndarray(vertex.pos),
- tvector3_to_ndarray(vertex.dir),
- tvector3_to_ndarray(vertex.pol),
- vertex.ke,
- vertex.t0)
+ pos=tvector3_to_ndarray(vertex.pos),
+ dir=tvector3_to_ndarray(vertex.dir),
+ ke=vertex.ke,
+ t0=vertex.t0,
+ pol=tvector3_to_ndarray(vertex.pol))
def root_event_to_python_event(ev):
'''Returns a new chroma.event.Event object created from the
@@ -148,12 +148,14 @@ class RootWriter(object):
"Write an event.Event object to the ROOT tree as a ROOT.Event object."
self.ev.id = pyev.id
- self.ev.primary_vertex.particle_name = pyev.primary_vertex.particle_name
- self.ev.primary_vertex.pos.SetXYZ(*pyev.primary_vertex.pos)
- self.ev.primary_vertex.dir.SetXYZ(*pyev.primary_vertex.dir)
- if pyev.primary_vertex.pol is not None:
- self.ev.primary_vertex.pol.SetXYZ(*pyev.primary_vertex.pol)
- self.ev.primary_vertex.ke = pyev.primary_vertex.ke
+ if pyev.primary_vertex is not None:
+ self.ev.primary_vertex.particle_name = \
+ pyev.primary_vertex.particle_name
+ self.ev.primary_vertex.pos.SetXYZ(*pyev.primary_vertex.pos)
+ self.ev.primary_vertex.dir.SetXYZ(*pyev.primary_vertex.dir)
+ if pyev.primary_vertex.pol is not None:
+ self.ev.primary_vertex.pol.SetXYZ(*pyev.primary_vertex.pol)
+ self.ev.primary_vertex.ke = pyev.primary_vertex.ke
if pyev.photons_beg is not None:
photons = pyev.photons_beg
diff --git a/generator/g4gen.py b/generator/g4gen.py
index 8dca086..3836897 100644
--- a/generator/g4gen.py
+++ b/generator/g4gen.py
@@ -120,7 +120,9 @@ class G4Generator(object):
self.particle_gun.SetParticleEnergy(total_energy)
self.particle_gun.SetParticlePosition(G4ThreeVector(*vertex.pos)*m)
self.particle_gun.SetParticleMomentumDirection(G4ThreeVector(*vertex.dir).unit())
-
+ if vertex.pol is not None:
+ self.particle_gun.SetParticlePolarization(G4ThreeVector(*vertex.pol).unit())
+
self.tracking_action.Clear()
gRunManager.BeamOn(1)
diff --git a/generator/vertex.py b/generator/vertex.py
index 5521d6b..b4e2d23 100644
--- a/generator/vertex.py
+++ b/generator/vertex.py
@@ -4,7 +4,7 @@ from itertools import izip, count
from chroma.pi0 import pi0_decay
from chroma import event
from chroma.sample import uniform_sphere
-from chroma.itertoolset import repeat_func
+from chroma.itertoolset import repeatfunc
# generator parts for use with gun()
@@ -13,7 +13,7 @@ def from_histogram(h):
pdf = h.hist/h.hist.sum()
cdf = np.cumsum(pdf)
- for x in repeat_func(np.random.random_sample):
+ for x in repeatfunc(np.random.random_sample):
yield h.bincenters[np.searchsorted(cdf, x)]
def constant(obj):
@@ -43,14 +43,14 @@ def flat(e_lo, e_hi):
def particle_gun(particle_name_iter, pos_iter, dir_iter, ke_iter, start_id=0):
for i, particle_name, pos, dir, ke in izip(count(start_id), particle_name_iter, pos_iter, dir_iter, ke_iter):
dir /= np.linalg.norm(dir)
- vertex = event.Vertex(particle_name, pos, dir, None, ke)
+ vertex = event.Vertex(particle_name, pos, dir, ke)
ev_vertex = event.Event(i, vertex, [vertex])
yield ev_vertex
def pi0_gun(pos_iter, dir_iter, ke_iter, start_id=0):
for i, pos, dir, ke in izip(count(start_id), pos_iter, dir_iter, ke_iter):
dir /= np.linalg.norm(dir)
- primary_vertex = event.Vertex('pi0', pos, dir, None, ke)
+ primary_vertex = event.Vertex('pi0', pos, dir, ke)
cos_theta_rest = np.random.random_sample() * 2 - 1
theta_rest = np.arccos(cos_theta_rest)
@@ -59,8 +59,8 @@ def pi0_gun(pos_iter, dir_iter, ke_iter, start_id=0):
(gamma1_e, gamma1_dir), (gamma2_e, gamma2_dir) = \
pi0_decay(ke+134.9766, dir, theta_rest, phi_rest)
- gamma1_vertex = event.Vertex('gamma', pos, gamma1_dir, None, gamma1_e)
- gamma2_vertex = event.Vertex('gamma', pos, gamma2_dir, None, gamma2_e)
+ gamma1_vertex = event.Vertex('gamma', pos, gamma1_dir, gamma1_e)
+ gamma2_vertex = event.Vertex('gamma', pos, gamma2_dir, gamma2_e)
ev_vertex = event.Event(i, primary_vertex, [gamma1_vertex, gamma2_vertex])
diff --git a/gpu.py b/gpu.py
index b98d42b..4e2ecf3 100644
--- a/gpu.py
+++ b/gpu.py
@@ -797,28 +797,3 @@ def create_cuda_context(device_id=None):
context.set_cache_config(cuda.func_cache.PREFER_L1)
return context
-
-class GPU(object):
- def __init__(self, device_id=None):
- """Initialize a GPU context on the specified device.
- If device_id is None, the default device is used."""
-
- if device_id is None:
- self.context = pycuda.tools.make_default_context()
- else:
- device = cuda.Device(device_id)
- self.context = device.make_context()
-
- print 'device %s' % self.context.get_device().name()
-
- self.print_mem_info()
-
- self.context.set_cache_config(cuda.func_cache.PREFER_L1)
-
- def print_mem_info(self):
- free, total = cuda.mem_get_info()
-
- print '%.1f %% of device memory is free.' % ((free/float(total))*100)
-
- def __del__(self):
- self.context.pop()
diff --git a/itertoolset.py b/itertoolset.py
index 498b940..4d293e8 100644
--- a/itertoolset.py
+++ b/itertoolset.py
@@ -15,16 +15,16 @@ def peek(iterable):
first_element = next(it)
return first_element, chain([first_element], it)
-def repeat_func(func, times=None, args=()):
- "equivalent to (func(*args) for i in xrange(times))."
+def repeatfunc(func, times=None, *args):
+ """Repeat calls to func with specified arguments.
+
+ Example: repeatfunc(random.random)
+ """
if times is None:
- while True:
- yield func(*args)
- else:
- for i in xrange(times):
- yield func(*args)
+ return starmap(func, repeat(args))
+ return starmap(func, repeat(args, times))
-def repeat_copy(object, times=None):
+def repeatcopy(object, times=None):
"""Returns deep copies of `object` over and over again. Runs indefinitely
unless the `times` argument is specified."""
if times is None:
diff --git a/sim.py b/sim.py
index 7c9720a..2e8f2f9 100755
--- a/sim.py
+++ b/sim.py
@@ -1,19 +1,12 @@
#!/usr/bin/env python
-import sys
import time
import os
import numpy as np
-import itertools
-import threading
-from chroma import detectors
-from chroma import optics
from chroma import generator
from chroma import gpu
-from chroma.fileio import root
-from chroma import tools
from chroma import event
-from chroma.itertoolset import peek, repeat_copy, repeating_iterator
+from chroma import itertoolset
def pick_seed():
"""Returns a seed for a random number generator selected using
@@ -21,7 +14,8 @@ def pick_seed():
return int(time.time()) ^ (os.getpid() << 16)
class Simulation(object):
- def __init__(self, detector, seed=None, cuda_device=None, geant4_processes=4, bvh_bits=11, use_cache=True, nthreads_per_block=64, max_blocks=1024):
+ def __init__(self, detector, seed=None, cuda_device=None,
+ geant4_processes=4, nthreads_per_block=64, max_blocks=1024):
self.detector = detector
self.nthreads_per_block = nthreads_per_block
@@ -32,7 +26,6 @@ class Simulation(object):
else:
self.seed = seed
- print 'RNG seed: %i' % self.seed
# We have three generators to seed: numpy.random, GEANT4, and CURAND.
# The latter two are done below.
np.random.seed(self.seed)
@@ -42,24 +35,24 @@ class Simulation(object):
else:
self.photon_generator = None
+ self.context = gpu.create_cuda_context(cuda_device)
+
if not hasattr(detector, 'mesh'):
# need to build geometry
- print 'Creating BVH with %i bits...' % bvh_bits
- detector.build(bits=bvh_bits, use_cache=use_cache)
-
- self.gpu = gpu.GPU(cuda_device)
+ detector.build()
+
self.gpu_geometry = gpu.GPUGeometry(detector)
self.gpu_daq = gpu.GPUDaq(self.gpu_geometry, max(self.detector.pmtids))
self.gpu_pdf = gpu.GPUPDF()
- print 'Initializing random numbers generators...'
self.rng_states = gpu.get_rng_states(self.nthreads_per_block*self.max_blocks, seed=self.seed)
self.pdf_config = None
- def simulate(self, iterable, keep_photons_beg=False, keep_photons_end=False, run_daq=True, max_steps=10):
+ def simulate(self, iterable, keep_photons_beg=False,
+ keep_photons_end=False, run_daq=True, max_steps=10):
try:
- first_element, iterable = peek(iterable)
+ first_element, iterable = itertoolset.peek(iterable)
except TypeError:
first_element, iterable = iterable, [iterable]
@@ -68,13 +61,16 @@ class Simulation(object):
elif isinstance(first_element, event.Photons):
iterable = (event.Event(photons_beg=x) for x in iterable)
elif isinstance(first_element, event.Vertex):
- iterable = (event.Event(vertices=[vertex]) for vertex in iterable)
+ iterable = (event.Event(primary_vertex=vertex, vertices=[vertex]) for vertex in iterable)
iterable = self.photon_generator.generate_events(iterable)
for ev in iterable:
gpu_photons = gpu.GPUPhotons(ev.photons_beg)
- gpu_photons.propagate(self.gpu_geometry, self.rng_states, nthreads_per_block=self.nthreads_per_block, max_blocks=self.max_blocks, max_steps=max_steps)
+ gpu_photons.propagate(self.gpu_geometry, self.rng_states,
+ nthreads_per_block=self.nthreads_per_block,
+ max_blocks=self.max_blocks,
+ max_steps=max_steps)
ev.nphotons = len(ev.photons_beg.pos)
@@ -93,7 +89,7 @@ class Simulation(object):
def create_pdf(self, iterable, tbins, trange, qbins, qrange, nreps=1):
"""Returns tuple: 1D array of channel hit counts, 3D array of
(channel, time, charge) pdfs."""
- first_element, iterable = peek(iterable)
+ first_element, iterable = itertoolset.peek(iterable)
if isinstance(first_element, event.Event):
iterable = self.photon_generator.generate_events(iterable)
@@ -102,12 +98,12 @@ class Simulation(object):
if pdf_config != self.pdf_config:
self.pdf_config = pdf_config
self.gpu_pdf.setup_pdf(max(self.detector.pmtids), tbins, trange,
- qbins, qrange)
+ qbins, qrange)
else:
self.gpu_pdf.clear_pdf()
if nreps > 1:
- iterable = repeating_iterator(iterable, nreps)
+ iterable = itertoolset.repeating_iterator(iterable, nreps)
for ev in iterable:
gpu_photons = gpu.GPUPhotons(ev.photons_beg)
@@ -132,7 +128,7 @@ class Simulation(object):
min_bin_content=min_bin_content,
time_only=True)
- first_element, iterable = peek(iterable)
+ first_element, iterable = itertoolset.peek(iterable)
if isinstance(first_element, event.Event):
iterable = self.photon_generator.generate_events(iterable)
@@ -149,91 +145,5 @@ class Simulation(object):
return self.gpu_pdf.get_pdf_eval()
-@tools.profile_if_possible
-def main():
- import optparse
-
- parser = optparse.OptionParser('%prog filename')
- parser.add_option('-b', type='int', dest='nbits', default=11)
- parser.add_option('-j', type='int', dest='device', default=None)
- parser.add_option('-s', type='int', dest='seed', default=None,
- help='Set random number generator seed')
- parser.add_option('-g', type='int', dest='ngenerators', default=4,
- help='Number of GEANT4 generator processes')
- 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',
- help='particle name', default='e-')
- parser.add_option('--ke', type='float', dest='ke',
- help='particle kinetic energy in MeV', default=100.0)
- parser.add_option('--pos', type='string', dest='pos',
- help='particle vertex origin.', default='(0,0,0)')
- parser.add_option('--dir', type='string', dest='dir',
- help='particle vertex direction.', default='(1,0,0)')
- parser.add_option('--save-photon-beg', action='store_true',
- dest='save_photons_beg', default=False,
- help='Save initial photon vertices to disk')
- parser.add_option('--save-photon-end', action='store_true',
- dest='save_photons_end', default=False,
- help='Save final photon vertices to disk')
-
- options, args = parser.parse_args()
-
- if len(args) < 1:
- sys.exit(parser.format_help())
- else:
- output_filename = args[0]
-
- if options.nevents <= 0:
- sys.exit('--nevents must be greater than 0!')
-
- pos = np.array(eval(options.pos), dtype=float)
- dir = np.array(eval(options.dir), dtype=float)
-
- print 'Loading detector %s...' % options.detector
- sys.stdout.flush()
- detector = detectors.find(options.detector)
-
- print 'Creating particle vertex generator...'
- sys.stdout.flush()
- if options.particle == 'pi0':
- ev_vertex_iter = itertools.islice(generator.vertex.pi0_gun(itertools.repeat(pos), itertools.repeat(dir), itertools.repeat(options.ke)), options.nevents)
- else:
- vertex = event.Vertex(options.particle, pos, dir, None, options.ke)
- ev_vertex_iter = (event.Event(i, vertex, [vertex]) for i, vertex in zip(range(options.nevents), repeat_copy(vertex)))
-
- # Initializing simulation
- simulation = Simulation(detector=detector, seed=options.seed, cuda_device=options.device, geant4_processes=options.ngenerators, bvh_bits=options.nbits)
-
- # Create output file
- writer = root.RootWriter(output_filename)
-
- # Preheat generator
- ev_iter = simulation.simulate(ev_vertex_iter, keep_photons_beg=options.save_photons_beg, keep_photons_end=options.save_photons_end)
-
- print 'Starting simulation...'
-
- nphotons = 0
- t0 = time.time()
-
- for i, ev in enumerate(ev_iter):
- print "\rEvent: %i" % (i+1),
- sys.stdout.flush()
-
- assert ev.nphotons > 0, 'Geant4 generated event with no photons!'
- nphotons += ev.nphotons
-
- writer.write_event(ev)
- print
-
- elapsed = time.time() - t0
-
- writer.close()
-
- print '%f elapsed, %1.1f events/sec, %1.0f photons/sec.' % \
- (elapsed, options.nevents/elapsed, nphotons/elapsed)
-
-if __name__ == '__main__':
- tools.enable_debug_on_crash()
- main()
+ def __del__(self):
+ self.context.pop()
diff --git a/solids/__init__.py b/solids/__init__.py
index 5ec11cf..c4d227f 100644
--- a/solids/__init__.py
+++ b/solids/__init__.py
@@ -29,7 +29,7 @@ def build_12inch_pmt_with_lc_hd(outer_material=water, nsteps=128):
rmax=lc_12inch_rmax, npoints=100)
def build_8inch_pmt(outer_material=water, nsteps=24):
- return build_pmt(dirname(__file__) + '/sno_pmt_reduced.txt', 0.003,
+ return build_pmt(dirname(__file__) + '/sno_pmt.txt', 0.003,
outer_material, nsteps)
def build_8inch_pmt_with_lc(outer_material=water, nsteps=24):
diff --git a/tests/test_fileio.py b/tests/test_fileio.py
index 2911976..3869a9f 100644
--- a/tests/test_fileio.py
+++ b/tests/test_fileio.py
@@ -5,7 +5,8 @@ import numpy as np
class TestFileIO(unittest.TestCase):
def test_file_write_and_read(self):
- ev = event.Event(1, event.Vertex('e-', (0,0,1), (1,0,0), (0,1,0), 15))
+ ev = event.Event(1, event.Vertex('e-', pos=(0,0,1), dir=(1,0,0),
+ ke=15.0, pol=(0,1,0)))
photons_beg = root.make_photon_with_arrays(1)
photons_beg.pos[0] = (1,2,3)
diff --git a/tests/test_pdf.py b/tests/test_pdf.py
index c7c9394..571cbd4 100644
--- a/tests/test_pdf.py
+++ b/tests/test_pdf.py
@@ -11,7 +11,7 @@ from chroma.sim import Simulation
class TestPDF(unittest.TestCase):
def setUp(self):
- self.detector = chroma.detectors.find("microlbne")
+ self.detector = chroma.detectors.microlbne()
self.detector.build()
self.vertex_gen = constant_particle_gun('e-', (0,0,0), (1,0,0), 10)
@@ -19,7 +19,9 @@ class TestPDF(unittest.TestCase):
'''Create a hit count and (q,t) PDF for 10 MeV events in MicroLBNE'''
g4generator = G4ParallelGenerator(1, water_wcsim)
- gpu_instance = gpu.GPU(0)
+
+ context = gpu.create_cuda_context()
+
gpu_geometry = gpu.GPUGeometry(self.detector)
nthreads_per_block, max_blocks = 64, 1024
@@ -48,6 +50,8 @@ class TestPDF(unittest.TestCase):
for i, nhits in enumerate(hitcount):
self.assertEqual(nhits, pdf[i].sum())
+ context.pop()
+
def testSimPDF(self):
sim = Simulation(self.detector)
diff --git a/tests/test_propagation.py b/tests/test_propagation.py
index 8f9d084..43ecb9b 100644
--- a/tests/test_propagation.py
+++ b/tests/test_propagation.py
@@ -20,7 +20,8 @@ class TestPropagation(unittest.TestCase):
cube = Geometry(vacuum)
cube.add_solid(Solid(box(100,100,100), vacuum, vacuum))
cube.pmtids = [0]
- sim = Simulation(cube, bvh_bits=4, geant4_processes=0, use_cache=False)
+ cube.build(use_cache=False)
+ sim = Simulation(cube, geant4_processes=0)
# Create initial photons
nphotons = 10000
diff --git a/tests/test_rayleigh.py b/tests/test_rayleigh.py
index 7e5fc92..02ccb41 100644
--- a/tests/test_rayleigh.py
+++ b/tests/test_rayleigh.py
@@ -16,8 +16,9 @@ class TestRayleigh(unittest.TestCase):
self.cube = Geometry(water_wcsim)
self.cube.add_solid(Solid(box(100,100,100), water_wcsim, water_wcsim))
self.cube.pmtids = [0]
- self.sim = Simulation(self.cube, bvh_bits=4, geant4_processes=0,
- use_cache=False)
+ self.cube.build(use_cache=False)
+ self.sim = Simulation(self.cube, geant4_processes=0)
+
nphotons = 100000
pos = np.tile([0,0,0], (nphotons,1)).astype(np.float32)
dir = np.tile([0,0,1], (nphotons,1)).astype(np.float32)