2 from __future__
import print_function
4 from optparse
import OptionParser
6 from math
import pi,sin,cos,sqrt
11 pid = {
"pi0":111,
"pi+":211,
"k0l":130,
"k0s":310,
"k+":321,
12 "e+":-11,
"mu+":-13,
"tau+":-15,
13 "nue":12,
"nuebar":-12,
14 "numu":14,
"numubar":-14,
15 "nutau":16,
"nutaubar":-16,
19 detectors = {
"SuperK":[3368.15/2., 3620.],
20 "Cylinder_60x74_20inchBandL_14perCent":[7400./2., 6000.],
21 "Cylinder_60x74_20inchBandL_40perCent":[7400./2., 6000.],
22 "HyperK":[7080./2., 5480.]}
24 for pname, no
in list(pid.items()):
25 if pname.endswith(
'+'):
26 pid[pname.replace(
'+',
'-')] = -1*pid[pname]
32 parser = OptionParser()
34 parser.add_option(
"-N",
"--nfiles", dest=
"nfiles",
35 help=
"number of files of particles to produce. Default: %s" \
37 metavar=
"#", default=optdefault)
39 parser.add_option(
"-n",
"--npart", dest=
"npart",
40 help=
"number of particles to simulate per file. Default: %s" \
42 metavar=
"#", default=optdefault)
43 verticesPerEventDefault = 1
44 parser.add_option(
"-V",
"--nVerticesPerEvent",dest=
"verticesPerEvent",
45 help=
" Average number of vertices to simulate per event. Default: %s" \
46 % (verticesPerEventDefault),
47 metavar=
"#", default=verticesPerEventDefault)
49 parser.add_option(
"-s",
"--seed", dest=
"seed",
50 help=
"Random number seed to use. Default: None.",
51 metavar=
"SEED", default=optdefault)
52 optchoices = list(pid.keys())
54 parser.add_option(
"-t",
"--type", dest=
"type",
55 help=
"Particle type to be generated. Choices: %s. Default: %s" \
56 % (optchoices, optdefault),
58 choices=optchoices, default=optdefault)
60 parser.add_option(
"-e",
"--energy", dest=
"energy",
61 help=
"Particle energy to be generated in MeV. Default: %s" \
63 metavar=
"ENERGY",default=optdefault)
64 optchoices = [
"center",
"random",
"minusx",
"plusx",
"minusz",
"plusz"]
65 optdefault = optchoices[0]
66 parser.add_option(
"-v",
"--vertex", dest=
"vertname",
67 help=
"Type of vertex. Choices: %s. Default: %s" \
68 % (optchoices, optdefault),
69 choices=optchoices, default=optdefault)
70 optchoices = [
"4pi",
"towall",
"tocap"]
71 optdefault = optchoices[0]
72 parser.add_option(
"-d",
"--direction", dest=
"dirname",
73 help=
"Type of direction. Choices: %s. Default: %s" \
74 % (optchoices, optdefault),
75 choices=optchoices, default=optdefault)
76 optchoices = list(detectors.keys())
78 parser.add_option(
"-w",
"--detector", dest=
"detector",
79 help=
"Detector water volume to use (for vertex positioning). Choices: %s. Default: %s" \
80 % (optchoices, optdefault),
81 choices=optchoices, default=optdefault)
83 (options, args) = parser.parse_args()
85 options.vertname = options.vertname.lower()
86 options.dirname = options.dirname.lower()
88 random.seed(options.seed)
90 nfiles = int(options.nfiles)
91 npart = int(options.npart)
92 verticesPerEvent=int(options.verticesPerEvent)
93 energy = float(options.energy)
97 particle = {
"vertex":(0, 0, 0),
99 "type":pid[options.type],
105 if options.vertname ==
"center":
107 elif options.vertname ==
"random":
109 elif options.vertname ==
"wall":
110 print(
"Wall not implemented yet", file=sys.stderr)
112 elif options.vertname ==
"minusx":
113 if options.detector ==
"SuperK":
114 particle[
"vertex"] = (-1000,0,0)
116 particle[
"vertex"] = (-1000. * detectors[options.detector][0] / detectors[
"SuperK"][0], 0, 0)
117 elif options.vertname ==
"plusx":
118 if options.detector ==
"SuperK":
119 particle[
"vertex"] = (+1000,0,0)
121 particle[
"vertex"] = (+1000. * detectors[options.detector][0] / detectors[
"SuperK"][0], 0, 0)
122 elif options.vertname ==
"minusz":
123 if options.detector ==
"SuperK":
124 particle[
"vertex"] = (0, 0, -1000)
126 particle[
"vertex"] = (0, 0, -1000. * detectors[options.detector][1] / detectors[
"SuperK"][1])
127 elif options.vertname ==
"plusz":
128 if options.detector ==
"SuperK":
129 particle[
"vertex"] = (0, 0, +1000)
131 particle[
"vertex"] = (0, 0, +1000. * detectors[options.detector][1] / detectors[
"SuperK"][1])
133 print(
"Don't understand vertex", options.vertname, file=sys.stderr)
136 if options.dirname ==
"towall":
138 particle[
"direction"] = (1,0,0)
139 elif options.dirname ==
"tocap":
141 particle[
"direction"] = (0,0,1)
142 elif options.dirname ==
"4pi":
144 elif options.dirname ==
"wall":
145 print(
"Wall not implemented yet", file=sys.stderr)
148 print(
"Don't understand direction", options.dirname, file=sys.stderr)
155 nu = {
"type":pid[
"numu"],
"energy":energy+1000.0,
156 "direction":(1, 0, 0)}
157 prot = {
"type":pid[
"p+"],
"energy":935.9840,
158 "direction":(0, 0, 1)}
173 f.write(
"$ nuance 0\n")
175 rad = detectors[options.detector][0] - 20.
176 height = detectors[options.detector][1] - 20.
178 x = random.uniform(-rad,rad)
179 y = random.uniform(-rad,rad)
180 if x**2 + y**2 < rad**2:
break
181 z = random.uniform(-height/2,height/2)
182 f.write(
"$ vertex %.5f %.5f %.5f %.5f\n" % (x, y, z, p[
"time"]))
184 f.write(
"$ vertex %.5f %.5f %.5f %.5f\n" % (p[
"vertex"]+(p[
"time"],)) )
187 f.write(
"$ info 0 0 %i\n" % recno)
189 th = random.random()*2*pi
190 u = 1.-2*random.random()
191 x = sqrt(1.-u**2)*cos(th)
192 y = sqrt(1.-u**2)*sin(th)
194 p[
"direction"] = (x, y, z)
202 f.write(
"$ track %(type)i %(energy).5f " % p)
203 f.write(
"%.5f %.5f %.5f %i\n" % (p[
"direction"]+(code,)))
206 for fileno
in range(nfiles):
207 typestr = options.type.replace(
"+",
"plus").replace(
"-",
"minus")
209 filename=
"%s_%.0fMeV_%s_%s_%s_%03i.kin" % (typestr, energy, options.vertname, options.dirname, options.detector, fileno)
211 outfile = open(filename,
'w')
213 if(verticesPerEvent == 1 ) :
214 print(
"Writing", npart,
"particles to", filename)
216 for i
in range(npart):
219 print(
"Writing", npart,
"particles with an average of", verticesPerEvent,
"vertices per event to", filename)
221 sigma = sqrt(verticesPerEvent)
222 while numberDone < npart:
223 numberToProcess = int(round(random.gauss(verticesPerEvent,sigma)))
224 eventPrint(numberToProcess,particle,outfile,numberDone)
225 numberDone = numberDone + numberToProcess
226 outfile.write(
"$ stop")