#!/usr/bin/env python3 # -*- encoding: utf-8 -*- ''' Description: geat4_pybind simulation @Date : 2021/09/02 12:46:27 @Author : tanyuhang @version : 1.0 @Date : 2023/04/18 @Author : xingchenli @version : 2.0 ''' import sys import random import math import json import numpy as np import geant4_pybind as g4b verbose = 0 # Geant4 main process class Particles: #model name for other class to use _model = None #other pars may use in other class define here #use in pixel_detector _randx = None _randy = None def __init__(self, my_d, absorber, g4_seed = random.randint(0, 1e7)): """ Description: Geant4 main process Simulate s_num particles through device Record the energy depositon in the device Parameters: --------- energy_steps : list Energy deposition of each step in simulation edep_devices : list Total energy deposition in device @Modify: --------- 2023/04/18 """ geant4_json = "./setting/absorber/" + absorber + ".json" with open(geant4_json) as f: g4_dic = json.load(f) self.geant4_model = g4_dic['geant4_model'] detector_material=my_d.device_dict['material'] if(self.geant4_model=='pixel_detector'): my_g4d = PixelDetectorConstruction(g4_dic,g4_dic['maxstep']) Particles._model = self.geant4_model Particles._randx = g4_dic['par_randx'] Particles._randy = g4_dic['par_randy'] #there's some parameter only use by this model global s_devicenames,s_localposition s_devicenames,s_localposition=[],[] print("end g4") else: my_g4d = MyDetectorConstruction(my_d,g4_dic,detector_material,g4_dic['maxstep']) if g4_dic['g4_vis']: ui = None ui = g4b.G4UIExecutive(len(sys.argv), sys.argv) g4RunManager = g4b.G4RunManagerFactory.CreateRunManager(g4b.G4RunManagerType.Default) rand_engine= g4b.RanecuEngine() g4b.HepRandom.setTheEngine(rand_engine) g4b.HepRandom.setTheSeed(g4_seed) g4RunManager.SetUserInitialization(my_g4d) # set physics list physics_list = g4b.FTFP_BERT() physics_list.RegisterPhysics(g4b.G4StepLimiterPhysics()) g4RunManager.SetUserInitialization(physics_list) # define global parameter global s_eventIDs,s_edep_devices,s_p_steps,s_energy_steps,s_events_angle s_eventIDs,s_edep_devices,s_p_steps,s_energy_steps,s_events_angle=[],[],[],[],[] #define action g4RunManager.SetUserInitialization(MyActionInitialization( g4_dic['par_in'], g4_dic['par_out'], g4_dic['par_type'], g4_dic['par_energy'], self.geant4_model)) if g4_dic['g4_vis']: visManager = g4b.G4VisExecutive() visManager.Initialize() UImanager = g4b.G4UImanager.GetUIpointer() UImanager.ApplyCommand('/control/execute param_file/g4macro/init_vis.mac') else: UImanager = g4b.G4UImanager.GetUIpointer() # reduce verbose from physics list UImanager.ApplyCommand('/process/em/verbose %d'%(verbose)) UImanager.ApplyCommand('/process/had/verbose %d'%(verbose)) UImanager.ApplyCommand('/run/initialize') g4RunManager.BeamOn(int(g4_dic['total_events'])) if g4_dic['g4_vis']: ui.SessionStart() self.p_steps=s_p_steps self.init_tz_device = 0 self.p_steps_current=[[[single_step[0]+my_d.l_x/2, single_step[1]+my_d.l_y/2, single_step[2]-self.init_tz_device]\ for single_step in p_step] for p_step in self.p_steps] self.energy_steps=s_energy_steps self.edep_devices=s_edep_devices self.events_angle=s_events_angle if(self.geant4_model=='pixel_detector'): #record localpos in logicvolume self.devicenames = s_devicenames self.localposition = s_localposition for i in range (0,len(s_devicenames)): #print("eventID:",i) #print("totalhits:",len(s_localposition[i])) pass del s_devicenames,s_localposition if(self.geant4_model=="beam_monitor"): hittotal=0 for particleenergy in s_edep_devices: if(particleenergy>0): hittotal=hittotal+1 self.hittotal=hittotal #count the numver of hit particles number=0 total_steps=0 for step in s_p_steps: total_steps=len(step)+total_steps average_steps=total_steps/len(s_p_steps) for step in s_p_steps: if(len(step)>=average_steps*0.9): break number=number+1 newtype_step=s_p_steps[number] #new particle's step self.p_steps_current=[[[single_step[0]+my_d.l_x/2, single_step[1]+my_d.l_y/2, single_step[2]-self.init_tz_device]\ for single_step in newtype_step]] newtype_energy=[0 for i in range(len(newtype_step))] for energy in s_energy_steps: for i in range(len(newtype_step)): if(len(energy)>i): newtype_energy[i]+=energy[i] self.energy_steps=[newtype_energy] #new particle's every step energy del s_eventIDs,s_edep_devices,s_p_steps,s_energy_steps,s_events_angle def __del__(self): pass #Geant4 for pixel_detector class PixelDetectorConstruction(g4b.G4VUserDetectorConstruction): "Pixel Detector Construction" def __init__(self,g4_dic,maxStep=0.5): g4b.G4VUserDetectorConstruction.__init__(self) self.g4_dic = g4_dic self.solid = {} self.logical = {} self.physical = {} self.checkOverlaps = True self.maxStep = maxStep*g4b.um self.fStepLimit = g4b.G4UserLimits(self.maxStep) self.create_world(g4_dic['world']) if(g4_dic['object']): for object_type in g4_dic['object']:#build all pixel first before build layer if(object_type=="pixel"): for every_object in g4_dic['object'][object_type]: self.create_pixel(g4_dic['object'][object_type][every_object]) print("end pixel constrution") for object_type in g4_dic['object']: if(object_type=="layer"): for every_object in g4_dic['object'][object_type]: self.create_layer(g4_dic['object'][object_type][every_object]) def create_world(self,world_type): self.nist = g4b.G4NistManager.Instance() material = self.nist.FindOrBuildMaterial(world_type) self.solid['world'] = g4b.G4Box("world", 25000*g4b.um, 25000*g4b.um, 50*g4b.cm) self.logical['world'] = g4b.G4LogicalVolume(self.solid['world'], material, "world") self.physical['world'] = g4b.G4PVPlacement(None, g4b.G4ThreeVector(0,0,0), self.logical['world'], "world", None, False, 0,self.checkOverlaps) visual = g4b.G4VisAttributes() #visual.SetVisibility(False) self.logical['world'].SetVisAttributes(visual) def create_pixel(self,object):#build pixel #pixel logicvolumn name = object['name'] material_type = self.nist.FindOrBuildMaterial(object['material'], False) print(type(material_type)) visual = g4b.G4VisAttributes(g4b.G4Color(object['colour'][0],object['colour'][1],object['colour'][2])) sidex = object['side_x']*g4b.um sidey = object['side_y']*g4b.um sidez = object['side_z']*g4b.um self.solid[name] = g4b.G4Box(name, sidex/2., sidey/2., sidez/2.) self.logical[name] = g4b.G4LogicalVolume(self.solid[name], material_type, name) #different part define for every_object in object: if(every_object.startswith("part")): part = object[every_object] p_name = part['name'] p_element_1 = self.nist.FindOrBuildElement(part['element_1'],False) p_element_2 = self.nist.FindOrBuildElement(part['element_2'],False) p_natoms_1 = part['natoms_1'] p_natoms_2 = part['natoms_2'] p_density = part['density']*g4b.g/g4b.cm3 p_mixture=g4b.G4Material(part['mixture_name'],p_density,2) p_mixture.AddElement(p_element_1,p_natoms_1*g4b.perCent) p_mixture.AddElement(p_element_2,p_natoms_2*g4b.perCent) p_translation = g4b.G4ThreeVector(part['position_x']*g4b.um, part['position_y']*g4b.um, part['position_z']*g4b.um) p_visual = g4b.G4VisAttributes(g4b.G4Color(part['colour'][0],part['colour'][1],part['colour'][2])) p_sidex = part['side_x']*g4b.um p_sidey = part['side_y']*g4b.um p_sidez = part['side_z']*g4b.um p_mother = self.logical[name] self.solid[p_name] = g4b.G4Box(p_name, p_sidex/2., p_sidey/2., p_sidez/2.) self.logical[p_name] = g4b.G4LogicalVolume(self.solid[p_name], p_mixture, p_name) g4b.G4PVPlacement(None, p_translation, self.logical[p_name],p_name, p_mother, False, 0,self.checkOverlaps) p_visual.SetVisibility(False) self.logical[p_name].SetVisAttributes(p_visual) visual.SetVisibility(True) self.logical[name].SetVisAttributes(visual) self.logical[name].SetUserLimits(self.fStepLimit) def create_layer(self,object):#build layer name = object['name']#temp use,muti layer need change Stepaction material_type = self.nist.FindOrBuildMaterial("G4_Galactic", False) pixel_type = object['pixel_type'] row = object['row'] column = object['column'] mother = self.physical['world'] translation = g4b.G4ThreeVector(object['position_x']*g4b.um, object['position_y']*g4b.um, object['position_z']*g4b.um) rotation = g4b.G4RotationMatrix() rotation.rotateX(object['rotation_xyz'][0]*g4b.degree) rotation.rotateY(object['rotation_xyz'][1]*g4b.degree) rotation.rotateZ(object['rotation_xyz'][2]*g4b.degree) visual = g4b.G4VisAttributes(g4b.G4Color(object['colour'][0],object['colour'][1],object['colour'][2])) motherBox = g4b.G4Box("MotherBox", 1.0 * g4b.cm, 1.0 * g4b.cm, 250 * g4b.um) self.logical[name] = g4b.G4LogicalVolume(motherBox, material_type, name) for i in range(0,int(row)): for j in range(0,int(column)): pixel = self.g4_dic['object']['pixel'][pixel_type] t_translation = g4b.G4ThreeVector((pixel['side_x']*(j+1/2-column/2))*g4b.um, (pixel['side_y']*(i+1/2-row/2))*g4b.um,0.0*g4b.um) t_pixelname = pixel_type+'_'+str(i)+'_'+str(j)+'_'+name g4b.G4PVPlacement(None, t_translation, self.logical[pixel_type],t_pixelname, self.logical[name], False, i*int(column)+j,self.checkOverlaps) self.physical[name] = g4b.G4PVPlacement(rotation,translation, name,self.logical[name], mother, False, 0,True) visual.SetVisibility(False) self.logical[name].SetVisAttributes(visual) self.logical[name].SetUserLimits(self.fStepLimit) def Construct(self): # return the world volume self.fStepLimit.SetMaxAllowedStep(self.maxStep) return self.physical['world'] #Geant4 for object class MyDetectorConstruction(g4b.G4VUserDetectorConstruction): "My Detector Construction" def __init__(self,my_d,g4_dic,detector_material,maxStep=0.5): g4b.G4VUserDetectorConstruction.__init__(self) self.solid = {} self.logical = {} self.physical = {} self.checkOverlaps = True self.create_world(g4_dic['world']) self.geant4_model = g4_dic['geant4_model'] if(detector_material=='Si'): detector={ "name" : "Device", "material" : "G4_Si", "side_x" : my_d.l_x, "side_y" : my_d.l_y, "side_z" : my_d.l_z, "colour" : [1,0,0], "position_x" : 0, "position_y" : 0, "position_z" : my_d.l_z/2.0 } self.create_elemental(detector) if(detector_material=='SiC' and self.geant4_model != 'cflm'): detector={ "name" : "Device", "material_1" : "Si", "material_2" : "C", "compound_name" :"SiC", "density" : 3.2, "natoms_1" : 50, "natoms_2" : 50, "side_x" : my_d.l_x, "side_y" : my_d.l_y, "side_z" : my_d.l_z, "colour" : [1,0,0], "position_x" : 0, "position_y" : 0, "position_z" : my_d.l_z/2.0, "tub" : {} } self.create_binary_compounds(detector) if(g4_dic['object']): for object_type in g4_dic['object']: if(object_type=="elemental"): for every_object in g4_dic['object'][object_type]: self.create_elemental(g4_dic['object'][object_type][every_object]) if(object_type=="binary_compounds"): for every_object in g4_dic['object'][object_type]: self.create_binary_compounds(g4_dic['object'][object_type][every_object]) self.maxStep = maxStep*g4b.um self.fStepLimit = g4b.G4UserLimits(self.maxStep) if (self.geant4_model == 'cflm'): self.logical["detector"].SetUserLimits(self.fStepLimit) else: self.logical["Device"].SetUserLimits(self.fStepLimit) def create_world(self,world_type): self.nist = g4b.G4NistManager.Instance() material = self.nist.FindOrBuildMaterial(world_type) self.solid['world'] = g4b.G4Box("world", 500000*g4b.um, 500000*g4b.um, 500000*g4b.um) self.logical['world'] = g4b.G4LogicalVolume(self.solid['world'], material, "world") self.physical['world'] = g4b.G4PVPlacement(None, g4b.G4ThreeVector(0,0,0), self.logical['world'], "world", None, False, 0,self.checkOverlaps) self.logical['world'].SetVisAttributes(g4b.G4VisAttributes.GetInvisible()) def create_elemental(self,object): name = object['name'] print(name) if name == 'pipe': material_type = self.nist.FindOrBuildMaterial(object['material'], False) self.rotation = g4b.G4RotationMatrix() self.rotation.rotateX(3*math.pi/2) translation = g4b.G4ThreeVector(object['position_x']*g4b.um, object['position_y']*g4b.um, object['position_z']*g4b.um) visual = g4b.G4VisAttributes(g4b.G4Color(object['colour'][0],object['colour'][1],object['colour'][2])) mother = self.physical['world'] Rmin = object['Rmin']*g4b.um Rmax = object['Rmax']*g4b.um Pipe_Z = object['Pipe_Z']*g4b.um PipeSphi = object['PipeSphi']*g4b.deg PipeDphi = object['PipeDphi']*g4b.deg self.solid[name] = g4b.G4Tubs("Pipe", Rmin, Rmax, Pipe_Z/2,PipeSphi,PipeDphi) self.logical[name] = g4b.G4LogicalVolume(self.solid[name], material_type, name) self.physical[name] = g4b.G4PVPlacement(self.rotation,translation, name,self.logical[name], mother, False, 0,self.checkOverlaps) self.logical[name].SetVisAttributes(visual) else: material_type = self.nist.FindOrBuildMaterial(object['material'], False) translation = g4b.G4ThreeVector(object['position_x']*g4b.um, object['position_y']*g4b.um, object['position_z']*g4b.um) visual = g4b.G4VisAttributes(g4b.G4Color(object['colour'][0],object['colour'][1],object['colour'][2])) mother = self.physical['world'] sidex = object['side_x']*g4b.um sidey = object['side_y']*g4b.um sidez = object['side_z']*g4b.um self.solid[name] = g4b.G4Box(name, sidex/2., sidey/2., sidez/2.) self.logical[name] = g4b.G4LogicalVolume(self.solid[name], material_type, name) self.physical[name] = g4b.G4PVPlacement(None,translation, name,self.logical[name], mother, False, 0,self.checkOverlaps) self.logical[name].SetVisAttributes(visual) def create_binary_compounds(self,object): name = object['name'] material_1 = self.nist.FindOrBuildElement(object['material_1'],False) material_2 = self.nist.FindOrBuildElement(object['material_2'],False) material_density = object['density']*g4b.g/g4b.cm3 compound=g4b.G4Material(object['compound_name'],material_density,2) compound.AddElement(material_1,object['natoms_1']*g4b.perCent) compound.AddElement(material_2,object['natoms_2']*g4b.perCent) translation = g4b.G4ThreeVector(object['position_x']*g4b.um, object['position_y']*g4b.um, object['position_z']*g4b.um) visual = g4b.G4VisAttributes(g4b.G4Color(object['colour'][0],object['colour'][1],object['colour'][2])) mother = self.physical['world'] sidex = object['side_x']*g4b.um sidey = object['side_y']*g4b.um sidez = object['side_z']*g4b.um if not(object['tub']): self.solid[name] = g4b.G4Box(name, sidex/2., sidey/2., sidez/2.) else: self.solid[name+"box"] = g4b.G4Box(name+"box", sidex/2., sidey/2., sidez/2.) self.solid[name+"tub"] = g4b.G4Tubs(name+"tub", 0,object['tub']['tub_radius']*g4b.um, object['tub']['tub_depth']*g4b.um, 0,360*g4b.deg) self.solid[name] = g4b.G4SubtractionSolid(name, self.solid[name+"box"], self.solid[name+"tub"]) self.logical[name] = g4b.G4LogicalVolume(self.solid[name], compound, name) self.physical[name] = g4b.G4PVPlacement(None,translation, name,self.logical[name], mother, False, 0,self.checkOverlaps) self.logical[name].SetVisAttributes(visual) def Construct(self): # return the world volume self.fStepLimit.SetMaxAllowedStep(self.maxStep) return self.physical['world'] class MyPrimaryGeneratorAction(g4b.G4VUserPrimaryGeneratorAction): "My Primary Generator Action" def __init__(self,par_in,par_out,par_type,par_energy,geant4_model): g4b.G4VUserPrimaryGeneratorAction.__init__(self) self.geant4_model=geant4_model par_direction = [ par_out[i] - par_in[i] for i in range(3) ] particle_table = g4b.G4ParticleTable.GetParticleTable() particle = particle_table.FindParticle(par_type) # define particle beam = g4b.G4ParticleGun(1) beam.SetParticleEnergy(par_energy*g4b.MeV) beam.SetParticleMomentumDirection(g4b.G4ThreeVector(par_direction[0], par_direction[1], par_direction[2])) beam.SetParticleDefinition(particle) beam.SetParticlePosition(g4b.G4ThreeVector(par_in[0]*g4b.um, par_in[1]*g4b.um, par_in[2]*g4b.um)) self.particleGun = beam self.position = par_in if(self.geant4_model=="time_resolution"): beam2 = g4b.G4ParticleGun(1) beam2.SetParticleEnergy(0.546*g4b.MeV) beam2.SetParticleMomentumDirection(g4b.G4ThreeVector(par_direction[0], par_direction[1], par_direction[2])) beam2.SetParticleDefinition(particle) beam2.SetParticlePosition(g4b.G4ThreeVector(par_in[0]*g4b.um, par_in[1]*g4b.um, par_in[2]*g4b.um)) self.particleGun2 = beam2 if(self.geant4_model=="pixel_detector"): self.directionx = par_direction[0] self.directiony = par_direction[1] self.directionz = par_direction[2] def GeneratePrimaries(self, event): if(self.geant4_model=="time_resolution"): self.particleGun.GeneratePrimaryVertex(event) self.particleGun2.GeneratePrimaryVertex(event) pass elif(self.geant4_model=="pixel_detector"): randx = Particles._randx randy = Particles._randy rdo_x = random.uniform(-randx,randx) rdo_y = random.uniform(-randy,randy) rdi_x = random.uniform(-randx,randx) rdi_y = random.uniform(-randy,randy) direction = g4b.G4ThreeVector(rdo_x,rdo_y,self.directionz) self.particleGun.SetParticleMomentumDirection(direction) self.particleGun.SetParticlePosition(g4b.G4ThreeVector(self.position[0]*g4b.um, self.position[1]*g4b.um, self.position[2]*g4b.um)) self.particleGun.GeneratePrimaryVertex(event) #print("direction:",rdo_x-rdi_x,rdo_y-rdi_y,self.directionz) #print(rdi_x,rdi_y,self.position[2]) else: self.particleGun.GeneratePrimaryVertex(event) class MyRunAction(g4b.G4UserRunAction): def __init__(self): g4b.G4UserRunAction.__init__(self) milligray = 1.e-3*g4b.gray microgray = 1.e-6*g4b.gray nanogray = 1.e-9*g4b.gray picogray = 1.e-12*g4b.gray g4b.G4UnitDefinition("milligray", "milliGy", "Dose", milligray) g4b.G4UnitDefinition("microgray", "microGy", "Dose", microgray) g4b.G4UnitDefinition("nanogray", "nanoGy", "Dose", nanogray) g4b.G4UnitDefinition("picogray", "picoGy", "Dose", picogray) def BeginOfRunAction(self, run): g4b.G4RunManager.GetRunManager().SetRandomNumberStore(False) def EndOfRunAction(self, run): nofEvents = run.GetNumberOfEvent() if nofEvents == 0: print("nofEvents=0") return class MyEventAction(g4b.G4UserEventAction): "My Event Action" def __init__(self, runAction, point_in, point_out): g4b.G4UserEventAction.__init__(self) self.fRunAction = runAction self.point_in = point_in self.point_out = point_out def BeginOfEventAction(self, event): self.edep_device=0. self.event_angle = 0. self.p_step = [] self.energy_step = [] #use in pixel_detector self.volume_name = [] self.localposition = [] def EndOfEventAction(self, event): eventID = event.GetEventID() #print("eventID:%s"%eventID) if len(self.p_step): point_a = [ b-a for a,b in zip(self.point_in,self.point_out)] point_b = [ c-a for a,c in zip(self.point_in,self.p_step[-1])] self.event_angle = cal_angle(point_a,point_b) else: self.event_angle = None save_geant4_events(eventID,self.edep_device, self.p_step,self.energy_step,self.event_angle) if(Particles._model == "pixel_detector"): save_pixel_detector_events(self.volume_name,self.localposition) #print("Detector: total energy:", g4b.G4BestUnit(self.edep_device, "Energy"), end="") def RecordDevice(self, edep,point_in,point_out): self.edep_device += edep self.p_step.append([point_in.getX()*1000, point_in.getY()*1000,point_in.getZ()*1000]) self.energy_step.append(edep) def RecordDetector(self, edep,point_in,point_out): self.edep_device += edep self.p_step.append([point_in.getX()*1000, point_in.getY()*1000,point_in.getZ()*1000]) self.energy_step.append(edep) def RecordPixel(self,step): edep = step.GetTotalEnergyDeposit() point_pre = step.GetPreStepPoint() point_post = step.GetPostStepPoint() point_in = point_pre.GetPosition() point_out = point_post.GetPosition() if(edep<=0.0): return touchable = point_pre.GetTouchable() volume = touchable.GetVolume() transform = touchable.GetHistory().GetTopTransform() localpos = transform.TransformPoint(point_in) self.edep_device += edep self.p_step.append([point_in.getX()*1000, point_in.getY()*1000,point_in.getZ()*1000]) self.energy_step.append(edep) #save only in RecordPixel self.volume_name.append(volume.GetName()) self.localposition.append([localpos.getX()/g4b.um,localpos.getY()/g4b.um,localpos.getZ()/g4b.um]) #print("edep:", edep) #print("Volume Name:", volume.GetName()) #print("Global Position in Worlds Volume:",point_in/g4b.um) #print("Local Position in Pixel:", localpos/g4b.um) def save_geant4_events(eventID,edep_device,p_step,energy_step,event_angle): if(len(p_step)>0): s_eventIDs.append(eventID) s_edep_devices.append(edep_device) s_p_steps.append(p_step) s_energy_steps.append(energy_step) s_events_angle.append(event_angle) else: s_eventIDs.append(eventID) s_edep_devices.append(edep_device) s_p_steps.append([[0,0,0]]) s_energy_steps.append([0]) s_events_angle.append(event_angle) def save_pixel_detector_events(volume_name,localposition): global s_devicenames,s_localposition s_devicenames.append(volume_name) s_localposition.append(localposition) #print("volume_name len:",len(volume_name)) #print("localposition len: ",len(localposition)) def cal_angle(point_a,point_b): "Calculate the angle between point a and b" x=np.array(point_a) y=np.array(point_b) l_x=np.sqrt(x.dot(x)) l_y=np.sqrt(y.dot(y)) dot_product=x.dot(y) if l_x*l_y > 0: cos_angle_d=dot_product/(l_x*l_y) angle_d=np.arccos(cos_angle_d)*180/np.pi else: angle_d=9999 return angle_d class MySteppingAction(g4b.G4UserSteppingAction): "My Stepping Action" def __init__(self, eventAction): g4b.G4UserSteppingAction.__init__(self) self.fEventAction = eventAction def UserSteppingAction(self, step): edep = step.GetTotalEnergyDeposit() point_pre = step.GetPreStepPoint() point_post = step.GetPostStepPoint() point_in = point_pre.GetPosition() point_out = point_post.GetPosition() volume = step.GetPreStepPoint().GetTouchable().GetVolume().GetLogicalVolume() volume_name = volume.GetName() if(volume_name == "Device"): self.fEventAction.RecordDevice(edep,point_in,point_out) if(volume_name.startswith("Taichu")): self.fEventAction.RecordPixel(step) if(volume_name == "detector"): self.fEventAction.RecordDetector(edep, point_in, point_out) return class MyActionInitialization(g4b.G4VUserActionInitialization): def __init__(self,par_in,par_out,par_type,par_energy,geant4_model): g4b.G4VUserActionInitialization.__init__(self) self.par_in = par_in self.par_out = par_out self.par_type=par_type self.par_energy=par_energy self.geant4_model=geant4_model def Build(self): self.SetUserAction(MyPrimaryGeneratorAction(self.par_in, self.par_out, self.par_type, self.par_energy, self.geant4_model)) # global myRA_action myRA_action = MyRunAction() self.SetUserAction(myRA_action) myEA = MyEventAction(myRA_action,self.par_in,self.par_out) self.SetUserAction(myEA) self.SetUserAction(MySteppingAction(myEA))