Back to home page

EIC code displayed by LXR

 
 

    


Warning, /epic/bin/generate_prim_file is written in an unsupported language. File is not indexed.

0001 #!/usr/bin/env python3
0002 
0003 # same as make_dawn_views but stops at generating the prim file.
0004 # W. Armstrong (ANL), original bash script
0005 # C. Peng (ANL), translate to python and add flexible run time for simulation
0006 
0007 import os
0008 import signal
0009 import subprocess
0010 import argparse
0011 import atexit
0012 import time
0013 from datetime import datetime
0014 import fcntl
0015 
0016 
0017 def readline_nonblocking(output):
0018     fd = output.fileno()
0019     fl = fcntl.fcntl(fd, fcntl.F_GETFL)
0020     fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
0021     try:
0022         return output.readline()
0023     except:
0024         return ''
0025 
0026 
0027 # arguments
0028 parser = argparse.ArgumentParser()
0029 
0030 parser.add_argument('-c', '--compact-file', type=str, dest='compact',
0031         default=os.path.join(os.environ.get('DETECTOR_PATH', '.'), 'epic.xml'),
0032         help='Top level compact file for detectors')
0033 
0034 parser.add_argument('-s', '--skip', type=int,
0035         default=0,
0036         help='Number of events number to skip in the input')
0037 
0038 parser.add_argument('-i', '--input', type=str,
0039         default='scripts/input_data/few_events.hepmc',
0040         help='Input hepmc file')
0041 
0042 parser.add_argument('-o', '--output-dir', type=str, dest='out_dir',
0043         default='sim_output',
0044         help='output directory')
0045 
0046 parser.add_argument('-D', '--detector-only', action='store_true', dest='detector_only',
0047         help='only generate the prim files for the detector geometry')
0048 
0049 parser.add_argument('-t', '--tag', type=str,dest='file_tag',
0050         default='view',
0051         help='Output file tag')
0052 
0053 parser.add_argument('--timeout', type=int,
0054         default=3600,
0055         help='Timeout in seconds')
0056 
0057 parser.add_argument('passthrough', nargs='*')
0058 
0059 args = parser.parse_args()
0060 
0061 macro = 'macro/dawn_picture.mac' if args.detector_only else 'macro/dawn_picture2.mac'
0062 
0063 # raise error if cannot create a temporary working dir
0064 # os.makedirs('dawn_view_tmp', exist_ok=False)
0065 os.makedirs(args.out_dir, exist_ok=True)
0066 
0067 # use absolute path so the chdir does not affect them
0068 args.input = os.path.abspath(args.input)
0069 args.out_dir = os.path.abspath(args.out_dir)
0070 args.compact = os.path.abspath(args.compact)
0071 macro = os.path.abspath(macro)
0072 
0073 # adjust fiber radius to reduce the number of fibers
0074 #compact_dir = os.path.dirname(os.path.realpath(args.compact))
0075 #ci_ecal = os.path.join(compact_dir, 'compact', 'ci_ecal_scfi.xml')
0076 #os.system('sed -i \'s/radius=\"EcalEndcapP_FiberRadius\"/radius=\"EcalEndcapP_FiberRadius*10\"/\' {}'.format(ci_ecal))
0077 
0078 prim_file = 'g4_0000.prim'
0079 dawn_env = os.environ.copy()
0080 dawn_env['DAWN_BATCH'] = 'a'
0081 # sdir = os.path.dirname(os.path.realpath(__file__))
0082 
0083 # Using a python warpper such as npsim introduces some problem in managing the subprocess.
0084 # The process1 managed by subprocess will generate another process with proc2_pid = proc1_pid + 1, which will not
0085 # be terminated by terminating or killing the process1.
0086 # In addition, running Geant4 with vis mode will never exit automatically (it waits for input).
0087 # Thus the created process 2 will occupy the system resources.
0088 sim_cmd = ['npsim', '--runType', 'vis',
0089         '--compact', args.compact,
0090         '--inputFiles', args.input,
0091         '--outputFile', 'derp.root',
0092         '--numberOfEvents', '1',
0093         '--skipNEvents', str(args.skip),
0094         '--macroFile', macro]
0095 
0096 start = datetime.now()
0097 elapse = datetime.now() - start
0098 last_update = datetime.now()
0099 finished = False
0100 
0101 # run simulation
0102 print(' '.join(sim_cmd))
0103 p = subprocess.Popen(args=sim_cmd, env=dawn_env,
0104                      stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE,
0105                      preexec_fn=os.setsid)
0106 __child_pid = p.pid
0107 while elapse.seconds < args.timeout:
0108     line = readline_nonblocking(p.stdout)
0109     elapse = datetime.now() - start
0110     time_left = args.timeout - elapse.seconds
0111     time_str = '[{:02d}:{:02d}]'.format(elapse.seconds // 60, elapse.seconds % 60)
0112 
0113     if time_left < 10:
0114         print('{} === TIMEOUT ===: Terminating in {:d} seconds'.format(time_str, time_left))
0115 
0116     if line:
0117         decoded_line = line.decode('utf-8').strip()
0118         print('{} {}'.format(time_str, decoded_line))
0119         # what we are looking for
0120         if decoded_line == 'File  {}  is generated.'.format(prim_file):
0121             print('{} === FINISHED ===: Got the prim file, terminating.'.format(time_str))
0122             finished = True
0123             break
0124         if decoded_line == 'Idle>':
0125             p.stdin.write(b'exit')
0126             break
0127         # do not sleep
0128         continue
0129 
0130     # ended early before file
0131     if p.poll() is not None:
0132         print(p.poll())
0133         break
0134 
0135     time.sleep(1)
0136 
0137 try:
0138     os.killpg(os.getpgid(p.pid), signal.SIGTERM)
0139 except ProcessLookupError:
0140     pass # assume process is dead
0141 
0142 # revert the change
0143 #os.system('sed -i \'s/radius=\"EcalEndcapP_FiberRadius*10\"/radius=\"EcalEndcapP_FiberRadius\"/\' {}'.format(ci_ecal))
0144 
0145 line = b'stderr outputs:\n'
0146 while line:
0147     print(line.decode('utf-8'), end='')
0148     line = readline_nonblocking(p.stderr)
0149 
0150 if finished:
0151     print('Simulation finished')
0152 else:
0153     print('Simulation failed')
0154     exit(1)
0155 
0156 # move the prim files (which can be quite large)
0157 # to the local pipeline storage path
0158 os.system('mv g4_0000.prim {}/{}.prim'.format(args.out_dir,args.file_tag))