summaryrefslogtreecommitdiff
path: root/generator/photon.py
diff options
context:
space:
mode:
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)
+
+
+