2
Class that runs the envelope tool according to below parameters set by user
11
import gui.gui_exception_handler
12
from gui.window import Window
14
ENV_DIR = os.path.expandvars("${MAUS_ROOT_DIR}/bin/utilities/envelope_tool/")
15
sys.path.append(ENV_DIR+"lib")
17
# pylint: disable=F0401
19
from lattice import Lattice
20
from plot_setup import PlotSetup
21
from magnet_setup import MagnetSetup
23
SHARE_DIR = (ENV_DIR+"share/")
27
Setup share directories in submodules (used for loading aux files)
29
Lattice.share_dir = SHARE_DIR
30
PlotSetup.share_dir = SHARE_DIR
31
MagnetSetup.share_dir = SHARE_DIR
32
beam_setup.SHARE_DIR = SHARE_DIR
34
class MainWindow(): # pylint: disable=R0902
36
Defines the main window for the envelope tool GUI
39
"""Initialise the main window"""
40
self.window = Window(ROOT.gClient.GetRoot(), # pylint: disable=E1101
41
ROOT.gClient.GetRoot(), # pylint: disable=E1101
42
SHARE_DIR+"main_frame2.json")
44
self.geom_input_obj = None
45
self.beam_input_obj = None
46
self.root_input_obj = None
47
self.geom_option_input = [0, None]
48
self.beam_option_input = [0, None]
49
self.root_option_input = [0, None]
51
self.window.main_frame.Resize(600,80)
52
self.pos_resize = self.window.get_frame("Initial_Beam_Position", "drop_down").Resize(230,20)
53
self.pos_resize = self.window.get_frame("Root_File", "drop_down").Resize(180,20)
55
self.window.set_action("Geometry_File", "drop_down",
56
"Selected(Int_t)", self.geom_action)
57
self.window.set_action("Initial_Beam_Position", "drop_down",
58
"Selected(Int_t)", self.beam_action)
59
self.window.set_action("Root_File", "drop_down",
60
"Selected(Int_t)", self.root_action)
62
self.window.set_button_action("&Okay", self.okay_action)
63
self.window.set_button_action("&Cancel", self.cancel_action)
65
def geom_action(self):
67
Selects action based on dropbox selection for Geometry File
69
geom_int = self.window.get_frame_dict("Geometry_File",
70
"drop_down")["frame"].GetSelected()
72
print "Select Geometry"
74
self.geom_option_input[0] = geom_int
76
self.geom_input_obj = RunNumberAction(self.window.main_frame)
77
self.geom_option_input[0] = geom_int
79
self.geom_input_obj = IDAction(self.window.main_frame)
80
self.geom_option_input[0] = geom_int
82
self.geom_input_obj = ExistingGeomAction(self.window.main_frame)
83
self.geom_option_input[0] = geom_int
86
def beam_action(self):
88
Selects action based on dropbox selection for initial beam pos/mom
90
beam_int = self.window.get_frame_dict("Initial_Beam_Position",
91
"drop_down")["frame"].GetSelected()
93
print "Select initial beam"
95
self.beam_option_input[0] = beam_int
97
self.beam_option_input[0] = beam_int
98
self.beam_input_obj = SetInitialBeamAction(self.window.main_frame)
101
def root_action(self):
103
Selects action based on dropbox selection for Root File
105
root_int = self.window.get_frame_dict("Root_File",
106
"drop_down")["frame"].GetSelected()
108
print "Select MC Data"
110
self.root_option_input[0] = root_int
112
self.root_option_input[0] = root_int
113
self.root_input_obj = ExistingRootAction(self.window.main_frame)
115
self.root_option_input[0] = root_int
117
def okay_action(self):
119
Handle Okay button press; get the inputs from each dropbox selection and push it to the
122
if self.geom_option_input[0] != 0 and self.geom_option_input[0] != 1:
123
self.geom_option_input[1] = self.geom_input_obj.input
124
if self.beam_option_input[0] != 0 and self.beam_option_input[0] != 1:
125
self.beam_option_input[1] = self.beam_input_obj.input
126
if self.root_option_input[0] != 0 and self.root_option_input[0] != 1 and self.root_option_input[0] != 3:
127
self.root_option_input[1] = self.root_input_obj.input
128
self.window.close_window()
130
def cancel_action(self):
131
"""Handle a click on the Cancel button"""
132
self.window.close_window()
137
#Geometry File Classes
139
class RunNumberAction:
140
"""GUI window to get geometry by runnumber"""
141
def __init__(self, root_frame):
142
"""Initialise the window"""
145
self.window = Window(ROOT.gClient.GetRoot(), # pylint: disable = E1101
147
SHARE_DIR+"run_number.json")
149
self.window.set_button_action("&Okay", self.okay_action)
150
self.window.set_button_action("&Cancel", self.cancel_action)
152
def okay_action(self):
154
Handle Okay button press; get the plot selection and push it to the
157
self.entry = [self.window.get_text_entry("Run_Number", type(1)), self.window.get_text_entry("Name_of_File", type(""))]
158
self.input = self.entry
159
self.window.close_window()
161
def cancel_action(self):
162
"""Handle a click on the Cancel button"""
163
self.window.close_window()
167
"""GUI window to get geometry by ID"""
168
def __init__(self, root_frame):
169
"""Initialise the window"""
172
self.window = Window(ROOT.gClient.GetRoot(), # pylint: disable = E1101
174
SHARE_DIR+"geomid_setup.json")
176
self.window.set_button_action("&Okay", self.okay_action)
177
self.window.set_button_action("&Cancel", self.cancel_action)
179
def okay_action(self):
181
Handle Okay button press; get the plot selection and push it to the
184
self.entry = [self.window.get_text_entry("Geometry_ID", type(1)), \
185
self.window.get_text_entry("Cooling_Channel_Tag", type("")), \
186
self.window.get_text_entry("Beamline_Tag", type("")), \
187
self.window.get_text_entry("Name_of_File", type(""))]
188
self.input = self.entry
189
self.window.close_window()
191
def cancel_action(self):
192
"""Handle a click on the Cancel button"""
193
self.window.close_window()
196
class ExistingGeomAction:
197
"""GUI window to get existing geometry file"""
198
def __init__(self, root_frame):
199
"""Initialise the window"""
202
output = os.popen("find -name 'ParentGeometryFile.dat'").read()
203
output2 = output.splitlines()
204
output2 = [i[2:] for i in output2]
205
testoutput = os.popen("find -name 'TestGeometry.dat'").read()
206
testoutput2 = testoutput.splitlines()
207
testoutput2 = [i[2:] for i in testoutput2]
208
with open(SHARE_DIR+"geomfile_list.json") as geomfile:
209
data = geomfile.read()
210
geomjson = json.loads(data)
211
geomjson["children"][0]["children"][0]["entries"] = ['<Select Geometry File>'] + output2 + testoutput2
212
with open(SHARE_DIR+"geomfile_list.json", 'w') as geomfile:
213
geomfile.write(json.dumps(geomjson))
215
self.window = Window(ROOT.gClient.GetRoot(), # pylint: disable = E1101
217
SHARE_DIR+"geomfile_list.json")
218
self.window.main_frame.Resize(560,80)
219
self.root_resize = self.window.get_frame("Geometry_File_List", "drop_down").Resize(470,20)
220
self.window.set_button_action("&Okay", self.okay_action)
221
self.window.set_button_action("&Cancel", self.cancel_action)
223
def okay_action(self):
225
Handle Okay button press; get the plot selection and push it to the
228
self.entry = self.window.get_frame_dict("Geometry_File_List",
229
"drop_down")["frame"].GetSelectedEntry().GetText()
230
self.input = self.entry
231
self.window.close_window()
233
def cancel_action(self):
234
"""Handle a click on the Cancel button"""
235
self.window.close_window()
238
#Beam Position/Momentum Classes
240
class SetInitialBeamAction:
241
"""GUI window to setup a initial beam for 'set beam' option"""
242
def __init__(self, root_frame):
243
"""Initialise the window"""
246
self.window = Window(ROOT.gClient.GetRoot(), # pylint: disable = E1101
248
SHARE_DIR+"set_initialbeam.json")
250
self.window.set_button_action("&Okay", self.okay_action)
251
self.window.set_button_action("&Cancel", self.cancel_action)
253
def okay_action(self):
255
Handle Okay button press; get the plot selection and push it to the
258
self.entry = [self.window.get_text_entry("initial_x", type(1.)), self.window.get_text_entry("initial_y", type(1.)), \
259
self.window.get_text_entry("initial_z", type(1.)), self.window.get_text_entry("initial_px", type(1.)), \
260
self.window.get_text_entry("initial_py", type(1.)), self.window.get_text_entry("initial_pz", type(1.))]
261
self.input = self.entry
262
self.window.close_window()
264
def cancel_action(self):
265
"""Handle a click on the Cancel button"""
266
self.window.close_window()
269
#MC Data Root File Classes
271
class ExistingRootAction:
272
"""GUI window to get existing Root file with MC simulation data"""
273
def __init__(self, root_frame):
274
"""Initialise the window"""
277
output = os.popen("find -type d -name 'third_party' -prune -o -type d -name 'tmp' -prune -o -name '*.root'").read()
278
output2 = output.splitlines()
279
output2 = [i[2:] for i in output2]
280
with open(SHARE_DIR+"mcroot_file.json") as mcfile:
282
mcjson = json.loads(data)
283
mcjson["children"][0]["children"][0]["entries"] = ['<Select MC Root File>'] + output2
284
with open(SHARE_DIR+"mcroot_file.json", 'w') as mcfile:
285
mcfile.write(json.dumps(mcjson))
287
self.window = Window(ROOT.gClient.GetRoot(), # pylint: disable = E1101
289
SHARE_DIR+"mcroot_file.json")
290
self.window.main_frame.Resize(560,80)
291
self.root_resize = self.window.get_frame("Root_File_List", "drop_down").Resize(470,20)
292
self.window.set_button_action("&Okay", self.okay_action)
293
self.window.set_button_action("&Cancel", self.cancel_action)
295
def okay_action(self):
297
Handle Okay button press; get the plot selection and push it to the
300
self.entry = self.window.get_frame_dict("Root_File_List",
301
"drop_down")["frame"].GetSelectedEntry().GetText()
302
self.input = self.entry
303
self.window.close_window()
305
def cancel_action(self):
306
"""Handle a click on the Cancel button"""
307
self.window.close_window()
310
class RunEnvtool(): # pylint: disable=R0902
312
Envelope Tool Parameters:
314
- Geometry file: Download from CDB by run # or ID (Current option has a bug), or specify existing geometry file path (must be in MAUS folder)
315
- Initial beam position/momentum: Use default position/momentum (center of D2 rotated 21 degrees) or specify position/momentum
316
- ROOT file: Run MC simulation of MICE to produce ROOT file with track data, specify existing ROOT file path or run envelope tool without track comparison
319
def __init__(self, geominput, beaminput, rootinput): # pylint: disable=R0902
321
self.geominput = geominput
322
self.beaminput = beaminput
323
self.rootinput = rootinput
325
self.geom_dir = self.geom_prompt(self.geominput)
326
self.new_geom_dir = self.set_apertures(self.geom_dir)
327
self.dipole2_x, self.dipole2_y, self.dipole2_z = self.get_dipole2_position(self.new_geom_dir)
328
self.data_card_dir, self.data_card_f = self.change_beam_pos(self.dipole2_x, self.dipole2_z, self.beaminput)
329
self.rootfile_prompt(self.new_geom_dir, self.data_card_dir, self.data_card_f, self.rootinput)
330
os.system("python bin/utilities/envelope_tool/envelope_tool.py --simulation_geometry_file %s --configuration_file %s" % (self.new_geom_dir, self.data_card_dir))
331
os.remove(self.data_card_dir)
333
def set_apertures(self, geom_dir):
335
Makes new geometry file (ParentGeometry_apert.dat) similar to original except apertures are added based on magnet dimensions
337
self.indexarray = [[],[]]
339
self.name_lib = ["Module CenterCoil", "Module MatchCoil", "Module EndCoil", "Module FCoil"]
341
self.new_geom_dir = geom_dir[:[i for i in range(len(geom_dir) - 1, -1, -1) if geom_dir[i] == "/"][0] + 1] + "ParentGeometryFile_apert.dat"
342
new_geom = open(self.new_geom_dir, "a+")
344
with open(geom_dir, "r+") as apert_f:
346
self.lines2 = apert_f.readlines()
348
for i in range(len(self.lines2)):
350
if "Module Q" in self.lines2[i] and "{" in self.lines2[i + 1]:
352
self.quadindex = self.lines2[i].index("M")
353
self.index = [j + self.count for j in range(i, len(self.lines2)) if "}" in self.lines2[j] and self.lines2[j + 1].strip() == ''][0]
354
self.indexarray[0].append(self.quadindex)
355
self.indexarray[1].append(self.index)
358
for line_num in range(len(self.indexarray[0])):
360
self.lines2.insert(self.indexarray[1][line_num], (" ")*self.indexarray[0][line_num] + \
361
"PropertyHep3Vector NominalAperture 172. 172. 550 mm\n" + (" ")*self.indexarray[0][line_num] + \
362
"PropertyHep3Vector NominalOuter 250. 250. 550 mm\n")
366
for i in self.name_lib:
368
for j in range(len(self.lines2)):
370
if i in self.lines2[j] and "{" in self.lines2[j + 1]:
372
self.quadindex = self.lines2[j].index("M")
373
self.index = [k + self.count for k in range(j, len(self.lines2)) if "}" in self.lines2[k] and self.lines2[k + 1].strip() == ''][0]
374
self.length = [k for k in range(j, self.index) if "Length" in self.lines2[k]][0]
375
self.thickness = [k for k in range(j, self.index) if "Thickness" in self.lines2[k]][0]
376
self.innerradius = [k for k in range(j, self.index) if "InnerRadius" in self.lines2[k]][0]
377
self.length_index = self.lines2[self.length][self.lines2[self.length].index("Length"):].split(" ")[:2][1].rstrip()
378
self.thickness_index = self.lines2[self.thickness][self.lines2[self.thickness].index("Thickness"):].split(" ")[:2][1].rstrip()
379
self.innerradius_index = self.lines2[self.innerradius][self.lines2[self.innerradius].index("InnerRadius"):].split(" ")[:2][1].rstrip()
382
self.lines2.insert(self.index, "%sPropertyHep3Vector NominalAperture %s %s %s mm\n%sPropertyHep3Vector NominalOuter %s %s %s mm\n" % ((" ")*self.quadindex, str(self.innerradius_index), str(self.innerradius_index), str(self.length_index), (" ")*self.quadindex, str(float(self.innerradius_index) + float(self.thickness_index)), str(float(self.innerradius_index) + float(self.thickness_index)), str(self.length_index)))
384
new_geom.writelines(self.lines2)
388
return self.new_geom_dir
390
def change_beam_pos(self, dipole2_x, dipole2_z, beaminput):
392
Creates temporary data card that passes parameters below to envelope tool:
394
- Sets initial position of beam to the center of D2 magnet and rotates 21 degrees toward -z axis if not user specified
395
- Sets log_level (1 to create log of run (maus.log), 0 for none)
396
- Sets number of spills per run for the MICE MC simulation
397
- Sets verbose_level which determines what level of c++ log messages are reported to user:
399
0 = debug info (and std::cout)
402
3 = errors (and std::cerr)
406
- Sets initial beam parameters (everything is the same as the configuration defaults except for the parameters above)
408
self.beaminput_int = beaminput[0]
409
self.specify_beam = beaminput[1]
411
if self.beaminput_int == 1:
413
x_pos, y_pos, z_pos = dipole2_x, 0.0, dipole2_z
414
x_momentum, y_momentum, z_momentum = float(math.sin(math.radians(-15.0))), 0.0, float(math.cos(math.radians(-15.0)))
416
elif self.beaminput_int == 2:
418
x_pos, y_pos, z_pos = float(self.specify_beam[0]), float(self.specify_beam[1]), float(self.specify_beam[2])
419
x_momentum, y_momentum, z_momentum = float(self.specify_beam[3]), float(self.specify_beam[4]), float(self.specify_beam[5])
421
self.simulation_ref = {"position":{"x":x_pos, "y":y_pos, "z":z_pos}, "momentum":{"x":x_momentum, "y":y_momentum, "z":z_momentum}, \
422
"particle_id":-13, "energy":226.0, "time":0.0, "random_seed":10, "spin":{"x":0.0, "y":0.0, "z":1.0}}
425
self.number_of_spills = 10
426
self.verbose_level = 5
429
"particle_generator":"binomial", # routine for generating empty primaries
430
"binomial_n":50, # number of coin tosses
431
"binomial_p":0.5, # probability of making a particle on each toss
432
"random_seed":5, # random seed for beam generation; controls also how the MC
433
# seeds are generated
435
# "particle_generator":"g4bl", # Uses G4BL as input for MAUS
436
# "g4bl_generator":"True", # Call G4BL each time new spill is created
441
"reference":self.simulation_ref, # reference particle
442
"random_seed_algorithm":"incrementing_random", # algorithm for seeding MC
443
"weight":90., # probability of generating a particle
445
"transverse_mode":"constant_solenoid", # transverse distribution matched to constant solenoid field
446
"emittance_4d":6., # 4d emittance
447
"normalised_angular_momentum":0.1, # angular momentum from diffuser
448
"bz":4.e-3 # magnetic field strength for angular momentum calculation
450
"longitudinal":{"longitudinal_mode":"sawtooth_time", # longitudinal distribution sawtooth in time
451
"momentum_variable":"p", # Gaussian in total momentum (options energy, pz)
452
"sigma_p":25., # RMS total momentum
453
"t_start":-1.e6, # start time of sawtooth
454
"t_end":+1.e6}, # end time of sawtooth
455
"coupling":{"coupling_mode":"none"} # no dispersion
456
#"spin":{"x":0.0, "y":0.0, "z":1.0}
461
"position":{"x":x_pos, "y":y_pos, "z":z_pos},
462
"momentum":{"x":x_momentum, "y":y_momentum, "z":z_momentum},
463
"spin":{"x":0.0, "y":0.0, "z":1.0},
464
"particle_id":211, "energy":285.0, "time":0.0, "random_seed":10
466
"random_seed_algorithm":"incrementing_random",
468
"transverse":{"transverse_mode":"constant_solenoid", "emittance_4d":6.,
469
"normalised_angular_momentum":0.1, "bz":4.e-3},
470
"longitudinal":{"longitudinal_mode":"sawtooth_time",
471
"momentum_variable":"p",
475
"coupling":{"coupling_mode":"none"}
476
# "spin":{"x":0.0, "y":0.0, "z":1.0}
478
##### ELECTRONS #####
481
"position":{"x":x_pos, "y":y_pos, "z":z_pos},
482
"momentum":{"x":x_momentum, "y":y_momentum, "z":z_momentum},
483
"spin":{"x":0.0, "y":0.0, "z":1.0},
484
"particle_id":-11, "energy":200.0, "time":0.0, "random_seed":10
486
"random_seed_algorithm":"incrementing_random",
488
"transverse":{"transverse_mode":"constant_solenoid", "emittance_4d":6.,
489
"normalised_angular_momentum":0.1, "bz":4.e-3},
490
"longitudinal":{"longitudinal_mode":"sawtooth_time",
491
"momentum_variable":"p",
495
"coupling":{"coupling_mode":"none"}
496
# "spin":{"x":0.0, "y":0.0, "z":1.0}
500
data_card_f = open('bin/utilities/envelope_tool/data_card_temp.py', 'a+')
501
data_card_f.write('simulation_reference_particle = ' + repr(self.simulation_ref) + '\n\n')
502
data_card_f.write('beam = ' + repr(self.beam) + '\n\n')
503
data_card_f.write('log_level = ' + repr(self.log_level) + '\n\n')
504
data_card_f.write('spill_generator_number_of_spills = ' + repr(self.number_of_spills) + '\n\n')
505
data_card_f.write('verbose_level = ' + repr(self.verbose_level) + '\n\n')
506
self.data_card_dir = "bin/utilities/envelope_tool/data_card_temp.py"
508
return(self.data_card_dir, data_card_f)
511
def get_dipole2_position(self, geom_dir):
513
Gets the position of D2 from the geometry file and returns values
516
with open(geom_dir, "r+") as dipole2_file:
518
self.lines = dipole2_file.readlines()
519
self.dipole2_module = [self.lines[i:i+10] for i in range(len(self.lines)) if "Module D2" in self.lines[i]][0]
520
self.dipole2_position = [i[i.index("Position"):] for i in self.dipole2_module if "Position" in i][0].split(" ")[:4]
521
self.dipole2_x, self.dipole2_y, self.dipole2_z = float(self.dipole2_position[1]), float(self.dipole2_position[2]), float(self.dipole2_position[3])
523
return(self.dipole2_x, self.dipole2_y, self.dipole2_z)
525
dipole2_file.close() # pylint: disable=W0101
528
def geom_prompt(self, geominput):
530
Prompts the user if they want to download the geometry from CDB or use existing geometry file (don't use Current option as it does not download the right geometry)
532
self.geominput_int = geominput[0]
533
self.specify_geom = geominput[1]
535
if self.geominput_int == 1:
537
self.geom_folder_name = raw_input('Name of New Geometry Folder: ')
538
os.system("mkdir files/geometry/download/%s" % self.geom_folder_name)
539
os.system("python bin/utilities/download_geometry.py --geometry_download_by current "\
540
"--geometry_download_directory files/geometry/download/%s" % self.geom_folder_name)
541
self.geom_dir = "files/geometry/download/%s/ParentGeometryFile.dat" % self.geom_folder_name
544
elif self.geominput_int == 2:
546
self.geom_folder_name = self.specify_geom[1]
547
os.system("mkdir files/geometry/download/%s" % self.geom_folder_name)
548
self.run_numb = self.specify_geom[0]
549
os.system("python bin/utilities/download_geometry.py --geometry_download_by run_number "\
550
"--geometry_download_run_number %s --geometry_download_directory files/geometry/download/%s" \
551
% (self.run_numb, self.geom_folder_name))
552
self.geom_dir = "files/geometry/download/%s/ParentGeometryFile.dat" % self.geom_folder_name
555
elif self.geominput_int == 3:
557
self.geom_folder_name = self.specify_geom[3]
558
os.system("mkdir files/geometry/download/%s" % self.geom_folder_name)
559
self.geom_id, self.coolingchannel_tag, self.beamline_tag = self.specify_geom[0], self.specify_geom[1], self.specify_geom[2]
560
os.system("python bin/utilities/download_geometry.py --geometry_download_by id "\
561
"--geometry_download_id %s --geometry_download_coolingchannel_tag %s "\
562
"--geometry_download_beamline_tag %s --geometry_download_directory files/geometry/download/%s" \
563
% (self.geom_id, self.coolingchannel_tag, self.beamline_tag, self.geom_folder_name))
564
self.geom_dir = "files/geometry/download/%s/ParentGeometryFile.dat" % self.geom_folder_name
567
elif self.geominput_int == 4:
569
self.geom_path = self.specify_geom
570
self.geom_dir = str(self.geom_path)
575
print "did not recognize response"
578
def rootfile_prompt(self, geom_dir, data_card_dir, data_card_file, rootinput):
580
Prompts the user to run MICE MC simulation to produce ROOT file with track data, use an existing ROOT file or run envelope tool without ROOT file
582
self.rootinput_int = rootinput[0]
583
self.specify_sim = rootinput[1]
585
if self.rootinput_int == 1:
587
self.run_mc_sim = "True"
588
data_card_file.write('Run_mc_sim = ' + repr(self.run_mc_sim))
589
data_card_file.close()
590
os.system("python bin/simulate_mice.py --simulation_geometry_file %s --configuration_file %s" % (geom_dir, data_card_dir))
592
elif self.rootinput_int == 2:
594
self.rootfile_dir = self.specify_sim
595
self.run_mc_sim = "True"
596
data_card_file.write('Run_mc_sim = ' + repr(self.run_mc_sim) + '\n\n')
597
data_card_file.write("""output_root_file_name = os.path.expandvars("${MAUS_ROOT_DIR}/""" + str(self.rootfile_dir) + """")""")
599
data_card_file.close()
601
elif self.rootinput_int == 3:
603
self.run_mc_sim = "False"
604
data_card_file.write('Run_mc_sim = ' + repr(self.run_mc_sim))
605
data_card_file.close()
609
print "did not recognize response"
613
The main function - build a MainWindow and poll to see if it has been closed
618
main_window = MainWindow()
620
gui.gui_exception_handler.set_error_level("exceptions")
621
while main_window.window.main_frame != None:
623
RunEnvtool(main_window.geom_option_input, main_window.beam_option_input, main_window.root_option_input)
625
except KeyboardInterrupt:
626
print "Pressed Ctrl-C"
628
if __name__ == '__main__':