diff options
| author | Stan Seibert <stan@mtrr.org> | 2011-08-16 13:52:00 -0400 | 
|---|---|---|
| committer | Stan Seibert <stan@mtrr.org> | 2011-08-16 13:52:00 -0400 | 
| commit | 7d9b50e9e64c9d8d9a25942e2ffaca52142c6c2b (patch) | |
| tree | 6eaf16ef125df0b02cff8198e6bece51a093c8fa /g4gen.py | |
| parent | 0dbfc2d7dc547452372d776ba74ec77838300a9a (diff) | |
| download | chroma-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 'g4gen.py')
| -rw-r--r-- | g4gen.py | 165 | 
1 files changed, 0 insertions, 165 deletions
diff --git a/g4gen.py b/g4gen.py deleted file mode 100644 index 6766d42..0000000 --- a/g4gen.py +++ /dev/null @@ -1,165 +0,0 @@ -from Geant4 import * -import g4py.ezgeom -import g4py.NISTmaterials -import g4py.ParticleGun -import pyublas -import numpy as np -import pi0 - -try: -    import G4chroma -except: -    # Try building the module -    import subprocess -    import sys, os -    module_dir = os.path.split(os.path.realpath(__file__))[0] -    print >>sys.stderr, 'Compiling G4chroma.so...' -    retcode = subprocess.call('g++ -o \'%s/G4chroma.so\' -shared \'%s/G4chroma.cc\' -fPIC `geant4-config --cflags --libs` `python-config --cflags --libs --ldflags` -lboost_python' % (module_dir, module_dir), shell=True) -    assert retcode == 0 -    import G4chroma - -class G4Generator(object): -    def __init__(self, material, seed=None): -        '''Create generator to produce photons inside the specified material. - -           material: chroma.geometry.Material object with density,  -                     composition dict and refractive_index. - -                     composition dictionary should be  -                        { element_symbol : fraction_by_weight, ... }. -           seed: Random number generator seed for HepRandom. If None, -                 generator is not seeded. -        ''' -        if seed is not None: -            HepRandom.setTheSeed(seed) - -        g4py.NISTmaterials.Construct() -        g4py.ezgeom.Construct() -        self.physics_list = G4chroma.ChromaPhysicsList() -        gRunManager.SetUserInitialization(self.physics_list) -        self.particle_gun = g4py.ParticleGun.Construct() -         -        self.world_material = self.create_g4material(material) -        g4py.ezgeom.SetWorldMaterial(self.world_material) - -        self.world = g4py.ezgeom.G4EzVolume('world') -        self.world.CreateBoxVolume(self.world_material, 100*m, 100*m, 100*m) -        self.world.PlaceIt(G4ThreeVector(0,0,0)) - -        self.tracking_action = G4chroma.PhotonTrackingAction() -        gRunManager.SetUserAction(self.tracking_action) -        gRunManager.Initialize() - -    def create_g4material(self, material): -        g4material = G4Material('world_material', material.density * g / cm3, -                                len(material.composition)) - -        # Add elements -        for element_name, element_frac_by_weight in material.composition.items(): -            g4material.AddElement(G4Element.GetElement(element_name, True), -                                  element_frac_by_weight) - -        # Set index of refraction -        prop_table = G4MaterialPropertiesTable() -        # Reverse entries so they are in ascending energy order rather -        # than wavelength -        energy = list((2*pi*hbarc / (material.refractive_index[::-1,0] * nanometer)).astype(float)) -        values = list(material.refractive_index[::-1, 1].astype(float)) -        prop_table.AddProperty('RINDEX', energy, values) - -        # Load properties -        g4material.SetMaterialPropertiesTable(prop_table) -        return g4material - -    def generate_pi0(self, total_energy, position, direction): -        '''Use GEANT4 to generate photons produced by a pi0 decay. - -        pi0 event will be generated by running two gammas with the appropriate -        energy and angular distribution. - -               total_energy: Total energy of pi0 (incl rest mass) in MeV -               position: 3-tuple of position of particle in global coordinates -               direction: 3-tuple direction vector.   -                          Does not have to be normalized. -        ''' -        direction = direction / np.linalg.norm(direction) -         -        cos_theta_rest = np.random.random_sample() * 2 - 1 -        theta_rest = np.arccos(cos_theta_rest) -        phi_rest = np.random.random_sample() * 2 * np.pi - -        (gamma1_e, gamma1_dir), (gamma2_e, gamma2_dir) = pi0.pi0_decay(energy=total_energy, -                                                                       direction=direction, -                                                                       theta=theta_rest, -                                                                       phi=phi_rest) - -        gamma1 = self.generate_photons('gamma', gamma1_e, position, gamma1_dir) -        gamma2 = self.generate_photons('gamma', gamma2_e, position, gamma2_dir) - -        photons = {'subtracks' : [ {'name':'gamma', 'pos': position, 't0' : 0.0, -                                    'dir' : gamma1_dir, 'total_e' : gamma1_e }, -                                   {'name':'gamma', 'pos': position, 't0' : 0.0, -                                    'dir' : gamma2_dir, 'total_e' : gamma2_e } ] -                    } -        for key in gamma1.keys(): -            photons[key] = np.concatenate((gamma1[key], gamma2[key])) -                                                                        -        return photons - -    def generate_photons(self, particle_name, total_energy, position, direction): -        '''Use GEANT4 to generate photons produced by the given particle. -            -               particle_name: GEANT4 name of particle.  'e-', 'mu-', etc -               total_energy: Total energy of particle (incl rest mass) in MeV -               position: 3-tuple of position of particle in global coordinates -               direction: 3-tuple direction vector.   -                          Does not have to be normalized. -        ''' -        self.particle_gun.SetParticleByName(particle_name) -        self.particle_gun.SetParticleEnergy(total_energy * MeV) -        self.particle_gun.SetParticlePosition(G4ThreeVector(*position)) -        self.particle_gun.SetParticleMomentumDirection(G4ThreeVector(*direction).unit()) - -        self.tracking_action.Clear() - -        gRunManager.BeamOn(1) -        n = self.tracking_action.GetNumPhotons()         -        pos = np.zeros(shape=(n,3), dtype=np.float32) -        pos[:,0] = self.tracking_action.GetX() -        pos[:,1] = self.tracking_action.GetY() -        pos[:,2] = self.tracking_action.GetZ() - -        dir = np.zeros(shape=(n,3), dtype=np.float32) -        dir[:,0] = self.tracking_action.GetDirX() -        dir[:,1] = self.tracking_action.GetDirY() -        dir[:,2] = self.tracking_action.GetDirZ() - -        pol = np.zeros(shape=(n,3), dtype=np.float32) -        pol[:,0] = self.tracking_action.GetPolX() -        pol[:,1] = self.tracking_action.GetPolY() -        pol[:,2] = self.tracking_action.GetPolZ() -         -        wavelength = self.tracking_action.GetWavelength().astype(np.float32) -        t0 = self.tracking_action.GetT0().astype(np.float32) -        return { 'pos' : pos,  -                 'dir' : dir,  -                 'pol' : pol, -                 'wavelength' : wavelength,  -                 't0' : t0 } - -if __name__ == '__main__': -    import time -    import optics -    gen = G4Generator(optics.water) -    # prime things -    gen.generate_photons('e-', 1, (0,0,0), (1,0,0)) - -    start = time.time()    -    n = 0 -    for i in xrange(100): -        photons = gen.generate_photons('mu-', 700, (0,0,0), (1,0,0)) -        n += len(photons['t0']) -        print photons['pos'][0].min(), photons['pos'][0].max() -    stop = time.time() -    print stop - start, 'sec' -    print n / (stop-start), 'photons/sec'  | 
