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.
175 self.
logger.debug(
"Setting SQLite local copy source file from config: %s" + self.
source_file)
182 Component.__init__(self, name=
'sqlite_file_copy', **kwargs)
187 Return dummy command arguments to satisfy the parent class.
189 cmd_args = [
"(no-command-needed)"]
191 if not all(isinstance(arg, str)
for arg
in cmd_args):
192 raise ValueError(
"All arguments must be strings.")
198 Execute the file copy operation.
204 self.
logger.info(f
"Copying file from {self.source_file} to {self.destination_file}")
208 self.
logger.info(f
"Successfully copied file to {self.destination_file}")
212 except Exception
as e:
213 self.
logger.error(f
"Error during file copy: {e}")
219 Run the hps-java JobManager class.
221 Input files have slcio format.
223 Required parameters are: **steering_files** \n
224 Optional parameters are: **detector**, **run_number**, **defs**
256 if 'overlay_file' in kwargs:
261 Component.__init__(self,
264 description=
'HPS Java Job Manager',
274 """! Configure JobManager component."""
278 if os.getenv(
'HPS_JAVA_BIN_JAR',
None)
is not None:
282 raise Exception(
'hps_java_bin_jar not set in environment or config file!')
284 if os.getenv(
"CONDITIONS_URL",
None)
is not None:
290 Return list of required configurations.
292 Required configurations are: **hps_java_bin_jar**
293 @retun list of required configurations.
295 return [
'hps_java_bin_jar']
298 """! Setup JobManager component."""
300 raise Exception(
"No inputs provided to hps-java.")
308 Setup command arguments.
309 @return list of arguments
314 self.
logger.debug(
'Setting java_args from config: %s' % self.
java_args)
329 self.
logger.debug(
'Setting conditions_password from config (not shown)')
353 args.append(
"outputFile=" + os.path.splitext(self.
output_files()[0])[0])
356 for k, v
in self.
defs.items():
358 args.append(k +
"=" + str(v))
362 self.
logger.debug(
"Steering does not exist at '%s' so assuming it is a resource." % self.
steering_file)
365 raise Exception(
'Steering looks like a file but is not an abs path: %s' % self.
steering_file)
374 args.append(input_file)
378 args.append(
"overlayFile=" + os.path.splitext(self.
overlay_file)[0])
384 Return list of required parameters.
386 Required parameters are: **steering_files**
387 @return list of required parameters
389 return [
'steering_files']
393 Return list of optional parameters.
395 Optional parameters are: **detector**, **run_number**, **defs**
396 @return list of optional parameters
398 return [
'detector',
'run_number',
'defs',
'nevents']
403 Run the hpstr analysis tool.
405 Required parameters are: **config_files** \n
406 Optional parameters are: **year**, **is_data**, **nevents** \n
407 Required configs are: **hpstr_install_dir**, **hpstr_base**
410 def __init__(self, cfg=None, is_data=0, year=None, tracking=None, **kwargs):
423 Component.__init__(self,
429 """! Setup HPSTR component."""
438 if len(os.path.dirname(config_file)):
440 if os.path.isabs(config_file):
444 raise Exception(
'The config has a directory but is not an abs path: %s' % self.
cfg)
451 if os.path.splitext(self.
input_files()[0])[1] ==
'.root':
457 Return list of required parameters.
459 Required parameters are: **config_files**
460 @return list of required parameters
462 return [
'config_files']
466 Return list of optional parameters.
468 Optional parameters are: **year**, **is_data**, **nevents**
469 @return list of optional parameters
471 return [
'year',
'is_data',
'nevents',
'tracking']
475 Return list of required configs.
477 Required configs are: **hpstr_install_dir**, **hpstr_base**
478 @return list of required configs
480 return [
'hpstr_install_dir',
'hpstr_base']
484 Setup command arguments.
485 @return list of arguments
493 if self.
year is not None:
494 args.extend([
"-y", str(self.
year)])
496 args.extend([
"-w", str(self.
tracking)])
500 """! Adjust names of output files."""
503 return [
'%s.root' % f]
510 """! Execute HPSTR component."""
516 proc = subprocess.Popen(cl, shell=
True, stdout=log_out, stderr=log_err)
520 return proc.returncode
527 Generic class for StdHep tools.
531 seed_names = [
'beam_coords',
534 'lhe_tridents_displacetime',
535 'lhe_tridents_displaceuni',
542 Component.__init__(self,
544 command=
"stdhep_" + name,
549 Setup command arguments.
550 @return list of arguments
554 if self.
name in StdHepTool.seed_names:
560 raise Exception(
"Too many outputs specified for StdHepTool.")
562 raise Exception(
"No outputs specified for StdHepTool.")
565 for i
in self.
inputs[::-1]:
568 raise Exception(
"No inputs specified for StdHepTool.")
575 Transform StdHep events into beam coordinates.
577 Optional parameters are: **beam_sigma_x**, **beam_sigma_y**, **beam_rot_x**,
578 **beam_rot_y**, **beam_rot_z**, **target_x**, **target_y**, **target_z**
600 StdHepTool.__init__(self,
607 Setup command arguments.
608 @return list of arguments
610 args = StdHepTool.cmd_args(self)
625 args.extend([
'-X', str(self.
target_x)])
627 args.extend([
'-Y', str(self.
target_y)])
629 args.extend([
'-Z', str(self.
target_z)])
635 Return list of optional parameters.
637 Optional parameters are: **beam_sigma_x**, **beam_sigma_y**, **beam_rot_x**,
638 **beam_rot_y**, **beam_rot_z**, **target_x**, **target_y**, **target_z**
639 @return list of optional parameters
641 return [
'beam_sigma_x',
'beam_sigma_y',
'beam_rot_x',
642 'beam_rot_y',
'beam_rot_z',
643 'target_x',
'target_y',
'target_z']
648 Randomly sample StdHep events into a new file.
650 Optional parameters are: **nevents**, **mu**
654 StdHepTool.__init__(self,
655 name=
'random_sample',
656 append_tok=
'sampled',
663 Setup command arguments.
664 @return list of arguments
668 if self.
name in StdHepTool.seed_names:
671 args.extend([
"-N", str(1)])
676 if self.
mu is not None:
677 args.extend([
"-m", str(self.
mu)])
681 args.insert(0, os.path.splitext(self.
output_files()[0])[0])
683 raise Exception(
"Too many outputs specified for RandomSample.")
685 raise Exception(
"No outputs specified for RandomSample.")
688 for i
in self.
inputs[::-1]:
691 raise Exception(
"No inputs were provided.")
697 Return list of optional parameters.
699 Optional parameters are: **nevents**, **mu**
700 @return list of optional parameters
702 return [
'nevents',
'mu']
705 """! Execute RandomSample component"""
706 returncode = Component.execute(self, log_out, log_err)
709 src =
'%s_1.stdhep' % os.path.splitext(self.
output_files()[0])[0]
710 dest =
'%s.stdhep' % os.path.splitext(self.
output_files()[0])[0]
711 self.
logger.debug(
"Moving '%s' to '%s'" % (src, dest))
712 shutil.move(src, dest)
719 Convert LHE files to StdHep, displacing the time by given ctau.
721 Optional parameters are: **ctau**
727 StdHepTool.__init__(self,
728 name=
'lhe_tridents_displacetime',
729 output_ext=
'.stdhep',
734 Setup command arguments.
735 @return list of arguments
737 args = StdHepTool.cmd_args(self)
738 if self.
ctau is not None:
739 args.extend([
"-l", str(self.
ctau)])
744 Return list of optional parameters.
746 Optional parameters are: **ctau**
747 @return list of optional parameters
754 Convert LHE files to StdHep, displacing the time by given ctau.
756 Optional parameters are: **ctau**
762 StdHepTool.__init__(self,
763 name=
'lhe_tridents_displaceuni',
764 output_ext=
'.stdhep',
769 Setup command arguments.
770 @return list of arguments
772 args = StdHepTool.cmd_args(self)
773 if self.
ctau is not None:
774 args.extend([
"-l", str(self.
ctau)])
779 Return list of optional parameters.
781 Optional parameters are: **ctau**
782 @return list of optional parameters
789 Add mother particles for physics samples.
793 StdHepTool.__init__(self,
800 """! Add full truth mother particles for physics samples"""
803 StdHepTool.__init__(self,
804 'add_mother_full_truth',
805 append_tok=
'mom_full_truth',
808 raise Exception(
"Must have 2 input files: a stdhep file and a lhe file in order")
812 raise Exception(
"The first input file must be a stdhep file")
816 raise Exception(
"The second input file must be a lhe file")
820 Setup command arguments.
821 @return list of arguments
828 Merge StdHep files, applying poisson sampling.
830 Required parameters are: **target_thickness**, **num_electrons**
841 StdHepTool.__init__(self,
842 name=
'merge_poisson',
843 append_tok=
'sampled',
847 """! Setup MergePoisson component."""
851 raise Exception(
"Cross section is missing.")
852 self.
logger.info(
"mu is %f", self.
mu)
856 Return list of required parameters.
858 Required parameters are: **target_thickness**, **num_electrons**
859 @return list of required parameters
861 return [
'target_thickness',
'num_electrons']
865 Setup command arguments.
866 @return list of arguments
869 if self.
name in StdHepTool.seed_names:
876 args.insert(0, os.path.splitext(self.
output_files()[0])[0])
878 raise Exception(
"Too many outputs specified for MergePoisson.")
880 raise Exception(
"No outputs specified for MergePoisson.")
883 for i
in self.
inputs[::-1]:
886 raise Exception(
"No inputs were provided.")
891 """! Execute MergePoisson component."""
892 returncode = Component.execute(self, log_out, log_err)
895 src =
'%s_1.stdhep' % os.path.splitext(self.
output_files()[0])[0]
896 dest =
'%s.stdhep' % os.path.splitext(self.
output_files()[0])[0]
897 self.
logger.debug(
"Moving '%s' to '%s'" % (src, dest))
898 shutil.move(src, dest)
907 Optional parameters are: none \n
908 Required parameters are: none
912 StdHepTool.__init__(self,
918 Return list of optional parameters.
920 Optional parameters are: none
921 @return list of optional parameters
927 Return list of required parameters.
929 Required parameters are: none
930 @return list of required parameters
937 Count number of events in a StdHep file.
941 Component.__init__(self,
943 command=
'stdhep_count.sh',
948 Setup command arguments.
949 @return list of arguments
955 """! Execute StdHepCount component."""
958 proc = subprocess.Popen(cl, stdout=PIPE)
959 (output, err) = proc.communicate()
961 nevents = int(output.split()[1])
962 print(
"StdHep file '%s' has %d events." % (self.
input_files()[0], nevents))
964 return proc.returncode
969 Generic base class for Java based tools.
979 Component.__init__(self,
986 Return list of required config.
988 Required config are: **hps_java_bin_jar**
989 @return list of required config
991 return [
'hps_java_bin_jar']
995 Setup command arguments.
996 @return list of arguments
1000 self.
logger.debug(
"Setting java_args from config: %s" + self.
java_args)
1016 Convert EVIO events to LCIO using the hps-java EvioToLcio command line tool.
1018 Input files have evio format (format used by DAQ system).
1020 Required parameters are: **detector**, **steering_files** \n
1021 Optional parameters are: **run_number**, **skip_events**, **nevents**, **event_print_interval**
1036 JavaTool.__init__(self,
1037 name=
'evio_to_lcio',
1038 java_class=
'org.hps.evio.EvioToLcio',
1039 output_ext=
'.slcio',
1044 Return list of required parameters.
1046 Required parameters are: **detector**, **steering_files**
1047 @return list of required parameters
1049 return [
'detector',
'steering_files']
1053 Return list of optional parameters.
1055 Optional parameters are: **run_number**, **skip_events**, **nevents**, **event_print_interval**
1056 @return list of optional parameters
1058 return [
'run_number',
'skip_events',
'nevents',
'event_print_interval']
1061 """! Setup EvioToLcio component."""
1069 Setup command arguments.
1070 @return list of arguments
1072 args = JavaTool.cmd_args(self)
1074 raise Exception(
'No output files were provided.')
1076 args.append(
'-DoutputFile=%s' % os.path.splitext(output_file)[0])
1085 self.
logger.debug(
"Steering does not exist at '%s' so assuming it is a resource." % self.
steering_file)
1088 raise Exception(
"Steering looks like a file but is not an abs path: %s" % self.
steering_file)
1097 args.append(inputfile)
1107 Space MC events and apply energy filters to process before readout.
1109 Optional parameters are: **filter_ecal_hit_ecut**, **filter_event_interval**,
1110 **filter_nevents_read**, **filter_nevents_write**, **filter_no_cuts** \n
1111 Required config are: **hps_java_bin_jar**
1115 if 'filter_no_cuts' in kwargs:
1121 if 'filter_ecal_pairs' in kwargs:
1126 if 'filter_ecal_hit_ecut' in kwargs:
1133 if 'filter_event_interval' in kwargs:
1139 if 'filter_nevents_read' in kwargs:
1145 if 'filter_nevents_write' in kwargs:
1153 JavaTool.__init__(self,
1154 name=
'filter_bunches',
1155 java_class=
'org.hps.util.FilterMCBunches',
1160 """! Configure FilterBunches component."""
1163 if os.getenv(
'HPS_JAVA_BIN_JAR',
None)
is not None:
1169 Setup command arguments.
1170 @return list of arguments
1172 args = JavaTool.cmd_args(self)
1195 Return list of optional parameters.
1197 Optional parameters are: **filter_ecal_hit_ecut**, **filter_event_interval**,
1198 **filter_nevents_read**, **filter_nevents_write**, **filter_no_cuts** \n
1199 @return list of optional parameters
1201 return [
'filter_ecal_hit_ecut',
1202 'filter_event_interval',
1203 'filter_nevents_read',
1204 'filter_nevents_write',
1209 Return list of required config.
1211 Required config are: **hps_java_bin_jar**
1212 @return list of required config
1214 return [
'hps_java_bin_jar']
1219 Apply hodo-hit filter and space MC events to process before readout.
1221 The nevents parameter is not settable from JSON in this class. It should
1222 be supplied as an init argument in the job script if it needs to be
1223 customized (the default nevents and event_interval used to apply spacing
1224 should usually not need to be changed by the user). \n
1226 Optional parameters are: **num_hodo_hits**, **event_interval**
1230 if "num_hodo_hits" in kwargs:
1235 if "event_interval" in kwargs:
1240 JavaTool.__init__(self,
1241 name=
'filter_events',
1242 java_class=
'org.hps.util.ExtractEventsWithHitAtHodoEcal',
1248 Setup command arguments.
1249 @return list of arguments
1251 args = JavaTool.cmd_args(self)
1267 Return list of optional parameters.
1269 Optional parameters are: **num_hodo_hits**, **event_interval**
1270 @return list of optional parameters
1272 return [
'num_hodo_hits',
'event_interval']
1277 Unzip the input files to outputs.
1281 Component.__init__(self,
1287 """! Return list of output files."""
1290 return [os.path.splitext(i)[0]
for i
in self.
input_files()]
1293 """! Execute Unzip component."""
1297 with gzip.open(inputfile,
'rb')
as in_file, open(outputfile,
'wb')
as out_file:
1298 shutil.copyfileobj(in_file, out_file)
1299 self.
logger.debug(
"Unzipped '%s' to '%s'" % (inputfile, outputfile))
1305 Dump LCIO event information.
1307 Required parameters are: none \n
1308 Required config are: **lcio_dir**
1314 Component.__init__(self,
1315 name=
'lcio_dump_event',
1316 command=
'dumpevent',
1319 if "event_num" in kwargs:
1325 """! Configure LCIODumpEvent component."""
1331 """! Setup LCIODumpEvent component."""
1336 Setup command arguments.
1337 @return list of arguments
1340 raise Exception(
"Missing required inputs for LCIODumpEvent.")
1348 Return list of required config.
1350 Required config are: **lcio_dir**
1351 @return list of required config
1357 Return list of required parameters.
1359 Required parameters are: none
1360 @return list of required parameters
1367 Count events in an LHE file.
1370 def __init__(self, minevents=0, fail_on_underflow=False, **kwargs):
1372 Component.__init__(self,
1377 """! Setup LHECount component."""
1379 raise Exception(
"Missing at least one input file.")
1383 Check if command exists.
1384 @return True if command exists
1389 """! Execute LHECount component."""
1391 with gzip.open(i,
'rb')
as in_file:
1392 lines = in_file.readlines()
1396 if "<event>" in line:
1399 print(
"LHE file '%s' has %d events." % (i, nevents))
1402 msg =
"LHE file '%s' does not contain the minimum %d events." % (i, nevents)
1403 if self.fail_on_underflow:
1404 raise Exception(msg)
1412 Tar files into an archive.
1416 Component.__init__(self,
1422 Check if command exists.
1423 @return True if command exists
1428 """! Execute TarFiles component."""
1429 self.
logger.debug(
"Opening '%s' for writing ..." % self.
outputs[0])
1430 tar = tarfile.open(self.
outputs[0],
"w")
1432 self.
logger.debug(
"Adding '%s' to archive" % i)
1441 Move input files to new locations.
1445 Component.__init__(self,
1451 Check if command exists.
1452 @return True if command exists
1457 """! Execute TarFiles component."""
1459 raise Exception(
"Input and output lists are not the same length!")
1463 self.
logger.info(
"Moving %s -> %s" % (src, dest))
1464 shutil.move(src, dest)
1470 Generic component for LCIO tools.
1472 Required parameters are: none \n
1473 Required config are: **lcio_bin_jar**
1479 Component.__init__(self,
1485 """! Configure LCIOTool component."""
1492 Setup command arguments.
1493 @return list of arguments
1496 raise Exception(
"Name required to write cmd args for LCIOTool.")
1501 Return list of required config.
1503 Required config are: **lcio_bin_jar**
1504 @return list of required config
1506 return [
'lcio_bin_jar']
1510 Return list of required parameters.
1512 Required parameters are: none
1513 @return list of required parameters
1520 Concatenate LCIO files together.
1524 LCIOTool.__init__(self,
1530 Setup command arguments.
1531 @return list of arguments
1533 args = LCIOTool.cmd_args(self)
1535 raise Exception(
"Missing at least one input file.")
1537 raise Exception(
"Missing an output file.")
1539 args.extend([
"-f", i])
1540 args.extend([
"-o", self.
outputs[0]])
1546 Count events in LCIO files.
1548 Required parameters are: none \n
1549 Optional parameters are: none
1553 LCIOTool.__init__(self,
1559 Setup command arguments.
1560 @return list of arguments
1562 args = LCIOTool.cmd_args(self)
1564 raise Exception(
"Missing an input file.")
1570 Return list of required parameters.
1572 Required parameters are: none
1573 @return list of required parameters
1579 Return list of optional parameters.
1581 Optional parameters are: none
1582 @return list of optional parameters
1593 LCIOTool.__init__(self,
1599 Setup command arguments.
1600 @return list of arguments
1602 args = LCIOTool.cmd_args(self)
1604 raise Exception(
"Missing at least one input file.")
1606 raise Exception(
"Missing an output file.")
1608 args.extend([
"-f", i])
1609 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.