Making ProMC single-particle gun for HEP
Source code name: "particle_gun.py"
Programming language: Python
Topic: Physics/HEP
DMelt Version 1.4. Last modified: 02/17/1970. License: Free
https://datamelt.org/code/cache/particle_gun_6209.py
To run this script using the DMelt IDE, copy the above URL link to the menu [File]→[Read script from URL] of the DMelt IDE.


# Single particle gun implemented using Jython/Python and Java
# Run this script using DMelt Java program
# S.Chekanov (ANL)

from java.io import *
from java.util import *
from java.net import *
from java.util import *
from proto import *
from promc.io import *
from hepsim import *
from java.util import *
from hephysics.particle import *
from java.util.zip import *
from java.lang import *
import re

outFilename="outfile.promc"
momentum = 1 # 1 GeV
xPID = 211   # pions
Ntot=100     # number of events

print "output=",outFilename

# write a single entry
def writeInfo(key,data):
      entry = ZipEntry(key)
      zout.putNextEntry(entry)
      entry.setSize(len(data))
      zout.write(data)
      zout.closeEntry()

# add one particle
def addParticle(b,unit,lunit,Id,M,M1,M2,PdgId,px,py,pz,e,status,weight,charge,barcode,x,y,z,t,D1,D2):
         b.addId(Id)
         b.addMass( (int)(M*unit) )
         b.addMother1(M1)
         b.addMother2(M2)
         b.addPdgId(PdgId)
         b.addPx( (int)(px*unit) )
         b.addPy( (int)(py*unit) )
         b.addPz( (int)(pz*unit) )
         b.addEnergy( (int)(e*unit) )
         b.addStatus(status)
         b.addWeight(weight)
         b.addCharge(charge)
         b.addBarcode(barcode)
         b.addX(  (int)(x*lunit) )
         b.addY(  (int)(y*lunit) )
         b.addZ(  (int)(z*lunit) )
         b.addT(  (int)(t*lunit) )
         b.addDaughter1(D1)
         b.addDaughter2(D2)



fout = FileOutputStream(outFilename)
zout = ZipOutputStream(BufferedOutputStream(fout))

random=Random()
PI2=2*Math.PI
PI=Math.PI
deg= 180 / Math.PI
txtdescription="Single particles. PID="+str(xPID)+" max E(GeV)="+str(momentum) 
print txtdescription

# create a header
b_desc= ProMCDescriptionFile.ProMCDescription.newBuilder()
b_desc.setVersion(4L)
b_desc.setEvents(Ntot)
b_desc.setTimestamp(1L)
b_desc.setDescription(txtdescription)
writeInfo("version",Long.toString(4).encode())

b_header = ProMCHeaderFile.ProMCHeader.newBuilder()
unit = 1000*100
lunit = 1000
b_header.setId1(xPID)
b_header.setId2(xPID)
b_header.setCrossSection(1)
b_header.setCrossSectionError(0)
b_header.setLengthUnit(lunit)
b_header.setMomentumUnit(unit)
b_header.setName("Single particles")
b_header.setNameLengthUnit("mm")
b_header.setNameMomentumUnit("GeV")


# get PDG table from the jar file (not external)
# Add PDG table to the output file
loader = ClassLoader.getSystemClassLoader()
stream = loader.getResourceAsStream("probrowser/resources/particle.tbl")
reader = BufferedReader(InputStreamReader(stream))
line = reader.readLine()
xmass=0
xcharge=0
while line is not None:
        line = reader.readLine()
        line=line.strip()
        parts=re.findall(r'\S+', line)
        if (len(parts)!=6): continue
        # print parts[0]," ",parts[1]," ",parts[2]," ",parts[3]," ",parts[4]," ",parts[5]
        b_pdg=ProMCHeaderFile.ProMCHeader.ParticleData.newBuilder()
        b_pdg.setId(int(parts[0]))
        b_pdg.setName(parts[1].strip())
        b_pdg.setMass(float(parts[3]))
        b_pdg.setWidth(float(parts[4]))
        b_pdg.setLifetime(float(parts[5]))
        charge=int(parts[2])
        b_pdg.setCharge( charge  )
        pdg=b_pdg.build()
        b_header.addParticleData(pdg) # add to the header file  
        if (xPID==int(parts[0])): 
                xmass=float(parts[3])
                xcharge= charge
                break
reader.close()

# build header now
header = b_header.build()
writeInfo("header",header.toByteArray())
desc = b_desc.build()
writeInfo("description",desc.toByteArray())

# make collision events:
oldPercentComplete = 0
for  eventNo in range(Ntot):
    percentComplete = (eventNo * 100.0 / Ntot)
    if(percentComplete % 5 == 0 and percentComplete > oldPercentComplete): 
         print percentComplete,"% complete"
         oldPercentComplete = percentComplete
    b_event = ProMC.ProMCEvent.newBuilder()
    event_builder=ProMC.ProMCEvent.Event.newBuilder()
    b_particles = ProMC.ProMCEvent.Particles.newBuilder()
    count=1

    addParticle(b_particles,unit,lunit,Id=0,M=0,M1=0,M2=0,PdgId=90,px=0,py=0,pz=0,e=14000,\
                     status=11,weight=1,charge=0,barcode=0,x=0,y=0,z=0,t=0,D1=0,D2=0)

    # proton -> 
    addParticle(b_particles,unit,lunit,Id=1,M=0.938272,M1=0,M2=0,PdgId=2212,px=0,py=0,pz=7000,e=7000,\
                     status=4,weight=1,charge=1,barcode=0,x=0,y=0,z=0,t=0,D1=0,D2=0)

    # proton <- 
    addParticle(b_particles,unit,lunit,Id=2,M=0.938272,M1=0,M2=0,PdgId=2212,px=0,py=0,pz=-7000,e=7000,\
                     status=4,weight=1,charge=1,barcode=0,x=0,y=0,z=0,t=0,D1=0,D2=0)

    # some gluon
    addParticle(b_particles,unit,lunit,Id=3,M=0,M1=0,M2=0,PdgId=21,px=0,py=0,pz=0,e=1400,\
                     status=4,weight=1,charge=0,barcode=0,x=0,y=0,z=0,t=0,D1=0,D2=0)

          
    # add single final-state particle with random Phi, Eta
    G=LParticle()
    phi   = -Math.PI + 2*Math.PI*random.nextDouble()
    eta   = -4.5 + 9*random.nextDouble()
    theta=2.0*Math.atan(Math.exp(-1*eta))
    G.setMass(xmass)
    G.setCharge(xcharge)
    G.setThetaPhiP(theta,phi,momentum)
    # G.setPtEtaPhiM(pt, eta, phi, xmass) 

    # Change origin too. mm in Z (-150 - 150 mm) 
    # assume a particle was produced uniformly a cylinder with R=4 mm
    Dz   = -150.0+300.0*random.nextDouble()
    A = random.nextDouble()
    B = random.nextDouble()
    T1=A
    T2=B
    if T2