summaryrefslogtreecommitdiff
path: root/generator/photon.py
diff options
context:
space:
mode:
authorStan Seibert <stan@mtrr.org>2011-08-16 13:52:00 -0400
committerStan Seibert <stan@mtrr.org>2011-08-16 13:52:00 -0400
commit7d9b50e9e64c9d8d9a25942e2ffaca52142c6c2b (patch)
tree6eaf16ef125df0b02cff8198e6bece51a093c8fa /generator/photon.py
parent0dbfc2d7dc547452372d776ba74ec77838300a9a (diff)
downloadchroma-7d9b50e9e64c9d8d9a25942e2ffaca52142c6c2b.tar.gz
chroma-7d9b50e9e64c9d8d9a25942e2ffaca52142c6c2b.tar.bz2
chroma-7d9b50e9e64c9d8d9a25942e2ffaca52142c6c2b.zip
Epic restructuring of code to switch to a generator-based style of
event creation. Now we have vertex generators (that produce initial particles), photon generators (that create photons to propagate), and a standard data structure using Python class containers and numpy arrays to hand around the code. Also cleaned up some naming of things before they become conventions.
Diffstat (limited to 'generator/photon.py')
-rw-r--r--generator/photon.py74
1 files changed, 74 insertions, 0 deletions
diff --git a/generator/photon.py b/generator/photon.py
new file mode 100644
index 0000000..dcfc292
--- /dev/null
+++ b/generator/photon.py
@@ -0,0 +1,74 @@
+import g4gen
+import multiprocessing
+import threading
+import numpy as np
+import itertools
+
+class G4GeneratorProcess(multiprocessing.Process):
+ def __init__(self, idnum, material, input_queue, output_queue, seed=None):
+ multiprocessing.Process.__init__(self)
+
+ self.idnum = idnum
+ self.material = material
+ self.input_queue = input_queue
+ self.output_queue = output_queue
+ self.seed = seed
+ self.daemon = True
+
+ def run(self):
+ gen = g4gen.G4Generator(self.material, seed=self.seed)
+ while True:
+ ev = self.input_queue.get()
+ ev.photon_start = gen.generate_photons(ev)
+ self.output_queue.put(ev)
+
+class G4VertexGeneratorProcess(multiprocessing.Process):
+ def __init__(self, vertex_iterator, queue):
+ multiprocessing.Process.__init__(self)
+ self.vertex_iterator = vertex_iterator
+ self.queue = queue
+
+ def run(self):
+ for ev in self.vertex_iterator:
+ self.queue.put(ev)
+
+def partition(num, partitions):
+ '''Generator that returns num//partitions, with the last item including the remainder.
+
+ Useful for partitioning a number into mostly equal parts while preserving the sum.
+
+ >>> list(partition(800, 3))
+ [266, 266, 268]
+ >>> sum(list(partition(800, 3)))
+ 800
+ '''
+ step = num // partitions
+ for i in xrange(partitions):
+ if i < partitions - 1:
+ yield step
+ else:
+ yield step + (num % partitions)
+
+def queue_iterator(nelements, queue):
+ for i in xrange(nelements):
+ yield queue.get()
+
+class G4ParallelGenerator(object):
+ def __init__(self, nprocesses, material, base_seed=None):
+ self.material = material
+ self.vertex_queue = multiprocessing.Queue()
+ self.photon_queue = multiprocessing.Queue()
+ self.processes = [ G4GeneratorProcess(i, material, self.vertex_queue, self.photon_queue, seed=base_seed + i)
+ for i in xrange(nprocesses) ]
+ for p in self.processes:
+ p.start()
+
+ def generate_events(self, nevents, vertex_iterator):
+ # Doing this to avoid a deadlock caused by putting to one queue while getting from another
+ for ev in itertools.islice(vertex_iterator, nevents):
+ self.vertex_queue.put(ev)
+
+ return queue_iterator(nevents, self.photon_queue)
+
+
+