1"""! Tools that can be used in HPSMC jobs."""
9from subprocess
import PIPE
17 Run the SLIC Geant4 simulation.
19 Optional parameters are: **nevents**, **macros**, **run_number**, **disable_particle_table** \n
20 Required parameters are: **detector** \n
21 Required configurations are: **slic_dir**, **detector_dir**
36 Component.__init__(self,
44 Setup command arguments.
45 @return list of arguments
48 raise Exception(
"No inputs given for SLIC.")
59 args.extend([
"-m",
"run_number.mac"])
63 if os.path.exists(tbl):
64 args.extend([
"-P", tbl])
66 raise Exception(
'SLIC particle.tbl does not exist: %s' % tbl)
71 if macro ==
"run_number.mac":
72 raise Exception(
"Macro name '%s' is not allowed." % macro)
73 if not os.path.isabs(macro):
74 raise Exception(
"Macro '%s' is not an absolute path." % macro)
75 args.extend([
"-m", macro])
82 """! Return path to detector file."""
86 """! Return path to particle table."""
87 return os.path.join(self.
slic_dir,
"share",
"particle.tbl")
90 """! Configure SLIC component."""
96 raise Exception(
'Failed to find valid detector_dir')
100 """! Setup SLIC component."""
101 if not os.path.exists(self.
slic_dir):
102 raise Exception(
"slic_dir does not exist: %s" % self.
slic_dir)
106 raise Exception(
'SLIC setup script does not exist: %s' % self.
namename)
109 run_number_cmd =
"/lcio/runNumber %d" % self.
run_number
110 run_number_mac = open(
"run_number.mac",
'w')
111 run_number_mac.write(run_number_cmd)
112 run_number_mac.close()
116 Return list of optional parameters.
118 Optional parameters are: **nevents**, **macros**, **run_number**
119 @return list of optional parameters
121 return [
'nevents',
'macros',
'run_number',
'disable_particle_table']
125 Return list of required parameters.
127 Required parameters are: **detector**
128 @return list of required parameters
134 Return list of required configurations.
136 Required configurations are: **slic_dir**, **detector_dir**
137 @return list of required configurations
139 return [
'slic_dir',
'detector_dir']
143 Execute SLIC component.
145 Component is executed by creating command line input
146 from command and command arguments.
147 @return return code of process
153 proc = subprocess.Popen(cl, shell=
True, stdout=log_out, stderr=log_err)
157 return proc.returncode
163 Copy the SQLite database file to the desired location.
168 Initialize SQLiteProc to copy the SQLite file.
183 self.
logger.debug(
"Setting SQLite local copy source file from config: %s" + self.
source_file)
190 Component.__init__(self, name=
'sqlite_file_copy', **kwargs)
195 Return dummy command arguments to satisfy the parent class.
197 cmd_args = [
"(no-command-needed)"]
199 if not all(isinstance(arg, str)
for arg
in cmd_args):
200 raise ValueError(
"All arguments must be strings.")
206 Execute the file copy operation.
212 self.
logger.info(f
"Copying file from {self.source_file} to {self.destination_file}")
216 self.
logger.info(f
"Successfully copied file to {self.destination_file}")
220 except Exception
as e:
221 self.
logger.error(f
"Error during file copy: {e}")
227 Run the hps-java JobManager class.
229 Input files have slcio format.
231 Required parameters are: **steering_files** \n
232 Optional parameters are: **detector**, **run_number**, **defs**
264 if 'overlay_file' in kwargs:
269 Component.__init__(self,
272 description=
'HPS Java Job Manager',
282 """! Configure JobManager component."""
286 if os.getenv(
'HPS_JAVA_BIN_JAR',
None)
is not None:
290 raise Exception(
'hps_java_bin_jar not set in environment or config file!')
292 if os.getenv(
"CONDITIONS_URL",
None)
is not None:
298 Return list of required configurations.
300 Required configurations are: **hps_java_bin_jar**
301 @retun list of required configurations.
303 return [
'hps_java_bin_jar']
306 """! Setup JobManager component."""
308 raise Exception(
"No inputs provided to hps-java.")
316 Setup command arguments.
317 @return list of arguments
322 self.
logger.debug(
'Setting java_args from config: %s' % self.
java_args)
337 self.
logger.debug(
'Setting conditions_password from config (not shown)')
361 args.append(
"outputFile=" + os.path.splitext(self.
output_files()[0])[0])
364 for k, v
in self.
defs.items():
366 args.append(k +
"=" + str(v))
370 self.
logger.debug(
"Steering does not exist at '%s' so assuming it is a resource." % self.
steering_file)
373 raise Exception(
'Steering looks like a file but is not an abs path: %s' % self.
steering_file)
382 args.append(input_file)
386 args.append(
"overlayFile=" + os.path.splitext(self.
overlay_file)[0])
392 Return list of required parameters.
394 Required parameters are: **steering_files**
395 @return list of required parameters
397 return [
'steering_files']
401 Return list of optional parameters.
403 Optional parameters are: **detector**, **run_number**, **defs**
404 @return list of optional parameters
406 return [
'detector',
'run_number',
'defs',
'nevents']
411 Run the hpstr analysis tool.
413 Required parameters are: **config_files** \n
414 Optional parameters are: **year**, **is_data**, **nevents** \n
415 Required configs are: **hpstr_install_dir**, **hpstr_base**
418 def __init__(self, cfg=None, is_data=0, year=None, tracking=None, **kwargs):
431 Component.__init__(self,
437 """! Setup HPSTR component."""
446 if len(os.path.dirname(config_file)):
448 if os.path.isabs(config_file):
452 raise Exception(
'The config has a directory but is not an abs path: %s' % self.
cfg)
459 if os.path.splitext(self.
input_files()[0])[1] ==
'.root':
465 Return list of required parameters.
467 Required parameters are: **config_files**
468 @return list of required parameters
470 return [
'config_files']
474 Return list of optional parameters.
476 Optional parameters are: **year**, **is_data**, **nevents**
477 @return list of optional parameters
479 return [
'year',
'is_data',
'nevents',
'tracking']
483 Return list of required configs.
485 Required configs are: **hpstr_install_dir**, **hpstr_base**
486 @return list of required configs
488 return [
'hpstr_install_dir',
'hpstr_base']
492 Setup command arguments.
493 @return list of arguments
501 if self.
year is not None:
502 args.extend([
"-y", str(self.
year)])
504 args.extend([
"-w", str(self.
tracking)])
508 """! Adjust names of output files."""
511 return [
'%s.root' % f]
518 """! Execute HPSTR component."""
524 proc = subprocess.Popen(cl, shell=
True, stdout=log_out, stderr=log_err)
528 return proc.returncode
535 Generic class for StdHep tools.
539 seed_names = [
'beam_coords',
542 'lhe_tridents_displacetime',
543 'lhe_tridents_displaceuni',
550 Component.__init__(self,
552 command=
"stdhep_" + name,
557 Setup command arguments.
558 @return list of arguments
562 if self.
name in StdHepTool.seed_names:
568 raise Exception(
"Too many outputs specified for StdHepTool.")
570 raise Exception(
"No outputs specified for StdHepTool.")
573 for i
in self.
inputs[::-1]:
576 raise Exception(
"No inputs specified for StdHepTool.")
583 Transform StdHep events into beam coordinates.
585 Optional parameters are: **beam_sigma_x**, **beam_sigma_y**, **beam_rot_x**,
586 **beam_rot_y**, **beam_rot_z**, **target_x**, **target_y**, **target_z**
608 StdHepTool.__init__(self,
615 Setup command arguments.
616 @return list of arguments
618 args = StdHepTool.cmd_args(self)
633 args.extend([
'-X', str(self.
target_x)])
635 args.extend([
'-Y', str(self.
target_y)])
637 args.extend([
'-Z', str(self.
target_z)])
643 Return list of optional parameters.
645 Optional parameters are: **beam_sigma_x**, **beam_sigma_y**, **beam_rot_x**,
646 **beam_rot_y**, **beam_rot_z**, **target_x**, **target_y**, **target_z**
647 @return list of optional parameters
649 return [
'beam_sigma_x',
'beam_sigma_y',
'beam_rot_x',
650 'beam_rot_y',
'beam_rot_z',
651 'target_x',
'target_y',
'target_z']
656 Randomly sample StdHep events into a new file.
658 Optional parameters are: **nevents**, **mu**
662 StdHepTool.__init__(self,
663 name=
'random_sample',
664 append_tok=
'sampled',
671 Setup command arguments.
672 @return list of arguments
676 if self.
name in StdHepTool.seed_names:
679 args.extend([
"-N", str(1)])
684 if self.
mu is not None:
685 args.extend([
"-m", str(self.
mu)])
689 args.insert(0, os.path.splitext(self.
output_files()[0])[0])
691 raise Exception(
"Too many outputs specified for RandomSample.")
693 raise Exception(
"No outputs specified for RandomSample.")
696 for i
in self.
inputs[::-1]:
699 raise Exception(
"No inputs were provided.")
705 Return list of optional parameters.
707 Optional parameters are: **nevents**, **mu**
708 @return list of optional parameters
710 return [
'nevents',
'mu']
713 """! Execute RandomSample component"""
714 returncode = Component.execute(self, log_out, log_err)
717 src =
'%s_1.stdhep' % os.path.splitext(self.
output_files()[0])[0]
718 dest =
'%s.stdhep' % os.path.splitext(self.
output_files()[0])[0]
719 self.
logger.debug(
"Moving '%s' to '%s'" % (src, dest))
720 shutil.move(src, dest)
727 Convert LHE files to StdHep, displacing the time by given ctau.
729 Optional parameters are: **ctau**
735 StdHepTool.__init__(self,
736 name=
'lhe_tridents_displacetime',
737 output_ext=
'.stdhep',
742 Setup command arguments.
743 @return list of arguments
745 args = StdHepTool.cmd_args(self)
746 if self.
ctau is not None:
747 args.extend([
"-l", str(self.
ctau)])
752 Return list of optional parameters.
754 Optional parameters are: **ctau**
755 @return list of optional parameters
762 Convert LHE files to StdHep, displacing the time by given ctau.
764 Optional parameters are: **ctau**
770 StdHepTool.__init__(self,
771 name=
'lhe_tridents_displaceuni',
772 output_ext=
'.stdhep',
777 Setup command arguments.
778 @return list of arguments
780 args = StdHepTool.cmd_args(self)
781 if self.
ctau is not None:
782 args.extend([
"-l", str(self.
ctau)])
787 Return list of optional parameters.
789 Optional parameters are: **ctau**
790 @return list of optional parameters
797 Add mother particles for physics samples.
801 StdHepTool.__init__(self,
808 """! Add full truth mother particles for physics samples"""
811 StdHepTool.__init__(self,
812 'add_mother_full_truth',
813 append_tok=
'mom_full_truth',
816 raise Exception(
"Must have 2 input files: a stdhep file and a lhe file in order")
820 raise Exception(
"The first input file must be a stdhep file")
824 raise Exception(
"The second input file must be a lhe file")
828 Setup command arguments.
829 @return list of arguments
836 Merge StdHep files, applying poisson sampling.
838 Required parameters are: **target_thickness**, **num_electrons**
849 StdHepTool.__init__(self,
850 name=
'merge_poisson',
851 append_tok=
'sampled',
855 """! Setup MergePoisson component."""
859 raise Exception(
"Cross section is missing.")
860 self.
logger.info(
"mu is %f", self.
mu)
864 Return list of required parameters.
866 Required parameters are: **target_thickness**, **num_electrons**
867 @return list of required parameters
869 return [
'target_thickness',
'num_electrons']
873 Setup command arguments.
874 @return list of arguments
877 if self.
name in StdHepTool.seed_names:
884 args.insert(0, os.path.splitext(self.
output_files()[0])[0])
886 raise Exception(
"Too many outputs specified for MergePoisson.")
888 raise Exception(
"No outputs specified for MergePoisson.")
891 for i
in self.
inputs[::-1]:
894 raise Exception(
"No inputs were provided.")
899 """! Execute MergePoisson component."""
900 returncode = Component.execute(self, log_out, log_err)
903 src =
'%s_1.stdhep' % os.path.splitext(self.
output_files()[0])[0]
904 dest =
'%s.stdhep' % os.path.splitext(self.
output_files()[0])[0]
905 self.
logger.debug(
"Moving '%s' to '%s'" % (src, dest))
906 shutil.move(src, dest)
915 Optional parameters are: none \n
916 Required parameters are: none
920 StdHepTool.__init__(self,
926 Return list of optional parameters.
928 Optional parameters are: none
929 @return list of optional parameters
935 Return list of required parameters.
937 Required parameters are: none
938 @return list of required parameters
945 Count number of events in a StdHep file.
949 Component.__init__(self,
951 command=
'stdhep_count.sh',
956 Setup command arguments.
957 @return list of arguments
963 """! Execute StdHepCount component."""
966 proc = subprocess.Popen(cl, stdout=PIPE)
967 (output, err) = proc.communicate()
969 nevents = int(output.split()[1])
970 print(
"StdHep file '%s' has %d events." % (self.
input_files()[0], nevents))
972 return proc.returncode
977 Generic base class for Java based tools.
987 Component.__init__(self,
994 Return list of required config.
996 Required config are: **hps_java_bin_jar**
997 @return list of required config
999 return [
'hps_java_bin_jar']
1003 Setup command arguments.
1004 @return list of arguments
1008 self.
logger.debug(
"Setting java_args from config: %s" + self.
java_args)
1024 Convert EVIO events to LCIO using the hps-java EvioToLcio command line tool.
1026 Input files have evio format (format used by DAQ system).
1028 Required parameters are: **detector**, **steering_files** \n
1029 Optional parameters are: **run_number**, **skip_events**, **nevents**, **event_print_interval**
1044 JavaTool.__init__(self,
1045 name=
'evio_to_lcio',
1046 java_class=
'org.hps.evio.EvioToLcio',
1047 output_ext=
'.slcio',
1052 Return list of required parameters.
1054 Required parameters are: **detector**, **steering_files**
1055 @return list of required parameters
1057 return [
'detector',
'steering_files']
1061 Return list of optional parameters.
1063 Optional parameters are: **run_number**, **skip_events**, **nevents**, **event_print_interval**
1064 @return list of optional parameters
1066 return [
'run_number',
'skip_events',
'nevents',
'event_print_interval']
1069 """! Setup EvioToLcio component."""
1077 Setup command arguments.
1078 @return list of arguments
1080 args = JavaTool.cmd_args(self)
1082 raise Exception(
'No output files were provided.')
1084 args.append(
'-DoutputFile=%s' % os.path.splitext(output_file)[0])
1093 self.
logger.debug(
"Steering does not exist at '%s' so assuming it is a resource." % self.
steering_file)
1096 raise Exception(
"Steering looks like a file but is not an abs path: %s" % self.
steering_file)
1105 args.append(inputfile)
1115 Space MC events and apply energy filters to process before readout.
1117 Optional parameters are: **filter_ecal_hit_ecut**, **filter_event_interval**,
1118 **filter_nevents_read**, **filter_nevents_write**, **filter_no_cuts** \n
1119 Required config are: **hps_java_bin_jar**
1123 if 'filter_no_cuts' in kwargs:
1129 if 'filter_ecal_pairs' in kwargs:
1134 if 'filter_ecal_hit_ecut' in kwargs:
1141 if 'filter_event_interval' in kwargs:
1147 if 'filter_nevents_read' in kwargs:
1153 if 'filter_nevents_write' in kwargs:
1161 JavaTool.__init__(self,
1162 name=
'filter_bunches',
1163 java_class=
'org.hps.util.FilterMCBunches',
1168 """! Configure FilterBunches component."""
1171 if os.getenv(
'HPS_JAVA_BIN_JAR',
None)
is not None:
1177 Setup command arguments.
1178 @return list of arguments
1180 args = JavaTool.cmd_args(self)
1203 Return list of optional parameters.
1205 Optional parameters are: **filter_ecal_hit_ecut**, **filter_event_interval**,
1206 **filter_nevents_read**, **filter_nevents_write**, **filter_no_cuts** \n
1207 @return list of optional parameters
1209 return [
'filter_ecal_hit_ecut',
1210 'filter_event_interval',
1211 'filter_nevents_read',
1212 'filter_nevents_write',
1217 Return list of required config.
1219 Required config are: **hps_java_bin_jar**
1220 @return list of required config
1222 return [
'hps_java_bin_jar']
1227 Apply hodo-hit filter and space MC events to process before readout.
1229 The nevents parameter is not settable from JSON in this class. It should
1230 be supplied as an init argument in the job script if it needs to be
1231 customized (the default nevents and event_interval used to apply spacing
1232 should usually not need to be changed by the user). \n
1234 Optional parameters are: **num_hodo_hits**, **event_interval**
1238 if "num_hodo_hits" in kwargs:
1243 if "event_interval" in kwargs:
1248 JavaTool.__init__(self,
1249 name=
'filter_events',
1250 java_class=
'org.hps.util.ExtractEventsWithHitAtHodoEcal',
1256 Setup command arguments.
1257 @return list of arguments
1259 args = JavaTool.cmd_args(self)
1275 Return list of optional parameters.
1277 Optional parameters are: **num_hodo_hits**, **event_interval**
1278 @return list of optional parameters
1280 return [
'num_hodo_hits',
'event_interval']
1285 Unzip the input files to outputs.
1289 Component.__init__(self,
1295 """! Return list of output files."""
1298 return [os.path.splitext(i)[0]
for i
in self.
input_files()]
1301 """! Execute Unzip component."""
1305 with gzip.open(inputfile,
'rb')
as in_file, open(outputfile,
'wb')
as out_file:
1306 shutil.copyfileobj(in_file, out_file)
1307 self.
logger.debug(
"Unzipped '%s' to '%s'" % (inputfile, outputfile))
1313 Dump LCIO event information.
1315 Required parameters are: none \n
1316 Required config are: **lcio_dir**
1322 Component.__init__(self,
1323 name=
'lcio_dump_event',
1324 command=
'dumpevent',
1327 if "event_num" in kwargs:
1333 """! Configure LCIODumpEvent component."""
1339 """! Setup LCIODumpEvent component."""
1344 Setup command arguments.
1345 @return list of arguments
1348 raise Exception(
"Missing required inputs for LCIODumpEvent.")
1356 Return list of required config.
1358 Required config are: **lcio_dir**
1359 @return list of required config
1365 Return list of required parameters.
1367 Required parameters are: none
1368 @return list of required parameters
1375 Count events in an LHE file.
1378 def __init__(self, minevents=0, fail_on_underflow=False, **kwargs):
1380 Component.__init__(self,
1385 """! Setup LHECount component."""
1387 raise Exception(
"Missing at least one input file.")
1391 Check if command exists.
1392 @return True if command exists
1397 """! Execute LHECount component."""
1399 with gzip.open(i,
'rb')
as in_file:
1400 lines = in_file.readlines()
1404 if "<event>" in line:
1407 print(
"LHE file '%s' has %d events." % (i, nevents))
1410 msg =
"LHE file '%s' does not contain the minimum %d events." % (i, nevents)
1411 if self.fail_on_underflow:
1412 raise Exception(msg)
1420 Tar files into an archive.
1424 Component.__init__(self,
1430 Check if command exists.
1431 @return True if command exists
1436 """! Execute TarFiles component."""
1437 self.
logger.debug(
"Opening '%s' for writing ..." % self.
outputs[0])
1438 tar = tarfile.open(self.
outputs[0],
"w")
1440 self.
logger.debug(
"Adding '%s' to archive" % i)
1449 Move input files to new locations.
1453 Component.__init__(self,
1459 Check if command exists.
1460 @return True if command exists
1465 """! Execute TarFiles component."""
1467 raise Exception(
"Input and output lists are not the same length!")
1471 self.
logger.info(
"Moving %s -> %s" % (src, dest))
1472 shutil.move(src, dest)
1478 Generic component for LCIO tools.
1480 Required parameters are: none \n
1481 Required config are: **lcio_bin_jar**
1487 Component.__init__(self,
1493 """! Configure LCIOTool component."""
1500 Setup command arguments.
1501 @return list of arguments
1504 raise Exception(
"Name required to write cmd args for LCIOTool.")
1509 Return list of required config.
1511 Required config are: **lcio_bin_jar**
1512 @return list of required config
1514 return [
'lcio_bin_jar']
1518 Return list of required parameters.
1520 Required parameters are: none
1521 @return list of required parameters
1528 Concatenate LCIO files together.
1532 LCIOTool.__init__(self,
1538 Setup command arguments.
1539 @return list of arguments
1541 args = LCIOTool.cmd_args(self)
1543 raise Exception(
"Missing at least one input file.")
1545 raise Exception(
"Missing an output file.")
1547 args.extend([
"-f", i])
1548 args.extend([
"-o", self.
outputs[0]])
1554 Count events in LCIO files.
1556 Required parameters are: none \n
1557 Optional parameters are: none
1561 LCIOTool.__init__(self,
1567 Setup command arguments.
1568 @return list of arguments
1570 args = LCIOTool.cmd_args(self)
1572 raise Exception(
"Missing an input file.")
1578 Return list of required parameters.
1580 Required parameters are: none
1581 @return list of required parameters
1587 Return list of optional parameters.
1589 Optional parameters are: none
1590 @return list of optional parameters
1601 LCIOTool.__init__(self,
1607 Setup command arguments.
1608 @return list of arguments
1610 args = LCIOTool.cmd_args(self)
1612 raise Exception(
"Missing at least one input file.")
1614 raise Exception(
"Missing an output file.")
1616 args.extend([
"-f", i])
1617 args.extend([
"-o", self.
outputs[0]])
Base class for components in a job.
output_files(self)
Return a list of output files created by this component.
config_from_environ(self)
Configure component from environment variables which are just upper case versions of the required con...
cmd_args(self)
Return the command arguments of this component.
input_files(self)
Get a list of input files for this component.
Miscellaneous math functions.