Skip to content

Commit 1e8e765

Browse files
committed
python script
1 parent d3b93c9 commit 1e8e765

File tree

1 file changed

+309
-0
lines changed

1 file changed

+309
-0
lines changed
Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import os
5+
import json
6+
from os.path import join, abspath, exists
7+
import re
8+
import subprocess
9+
import ROOT as root
10+
11+
12+
def clean(dir,name,printtext):
13+
if printtext:
14+
print("==> Delete simulation artefacts in the output directory\n")
15+
for f in os.listdir(dir):
16+
pattern_del=name+"_|o2simtopology|MCStepLogger"
17+
#pattern_keep="Kine.root|serverlog|mergerlog|workerlog"
18+
pattern_keep="Kine.root|serverlog"
19+
if (re.search(pattern_del, f)) and (not re.search(pattern_keep, f) ):
20+
os.remove(abspath(join(dir,f)))
21+
22+
23+
def read_sim_config(args):
24+
IniName = "GeneratorEMCocktail.ini"
25+
generatorName = "${O2DPG_ROOT}/MC/config/PWGEM/external/generator/GeneratorEMCocktailV2.C"
26+
generatorFunc = "GenerateEMCocktail"
27+
28+
# matches GeneratorParamEMlibV2.h
29+
GeneratorParamEMlibV2_CollisionSystem={"kpp900GeV":0x000, "kpp2760GeV":0x64, "kpp7TeV":0xC8, "kpPb":0x12C, "kPbPb":0x190}
30+
GeneratorParamEMlibV2_Centrality={"kpp":0x0, "k0005":0x1, "k0510":0x2, "k1020":0x3, "k2030":0x4, "k3040":0x5, "k4050":0x6, "k5060":0x7, "k0010":0x8, "k2040":0x9, "k4060":0xA, "k6080":0xB, "k0020":0xC, "k0040":0xD, "k2080":0xE, "k4080":0xF, "k2050":0x10, "kCentralities":0x11}
31+
32+
allKeys = ["collisionSystem", "centrality", "decayMode","selectedMothers", "paramFile", "paramFileDir", "numberOfParticles", "minPt", "maxPt", "pythiaErrorTolerance", "externalDecayer", "decayLongLived", "dynamicalPtRange", "useYWeights", "paramV2FileDir", "toFixEP", "yGenRange", "useLMeeDecaytable", "weightingMode"]
33+
if not exists(args.sim_config_file):
34+
print("ERROR: File "+args.sim_config_file+" not found")
35+
return 1
36+
37+
with open(args.sim_config_file, "r") as f:
38+
simConfigs = json.load(f)
39+
40+
print("==> Reading simualtion configuration from "+abspath(args.sim_config_file))
41+
42+
missing_key = False
43+
for key in allKeys:
44+
if not key in simConfigs:
45+
print("ERROR: Missing key \'"+key+"\'")
46+
missing_key = True
47+
if missing_key:
48+
return 1
49+
50+
collisionSystem = GeneratorParamEMlibV2_CollisionSystem[simConfigs["collisionSystem"]]
51+
centrality = GeneratorParamEMlibV2_Centrality[simConfigs["centrality"]]
52+
decayMode = simConfigs["decayMode"]
53+
selectedMothers = simConfigs["selectedMothers"]
54+
paramFile = simConfigs["paramFile"]
55+
paramFileDir = simConfigs["paramFileDir"]
56+
numberOfParticles = simConfigs["numberOfParticles"]
57+
minPt = simConfigs["minPt"]
58+
maxPt = simConfigs["maxPt"]
59+
pythiaErrorTolerance = simConfigs["pythiaErrorTolerance"]
60+
externalDecayer = simConfigs["externalDecayer"]
61+
decayLongLived = simConfigs["decayLongLived"]
62+
dynamicalPtRange = simConfigs["dynamicalPtRange"]
63+
useYWeights = simConfigs["useYWeights"]
64+
paramV2FileDir = simConfigs["paramV2FileDir"]
65+
toFixEP = simConfigs["toFixEP"]
66+
yGenRange = simConfigs["yGenRange"]
67+
useLMeeDecaytable = simConfigs["useLMeeDecaytable"]
68+
weightingMode = simConfigs["weightingMode"]
69+
70+
print(f"collisionSystem\t\t{collisionSystem}\ncentrality\t\t{centrality}\ndecayMode\t\t{decayMode}\nselectedMothers\t\t{selectedMothers}\nparamFile\t\t{paramFile}\nparamFileDir\t\t{paramFileDir}\nnumberOfParticles\t{numberOfParticles}\nminPt\t\t\t{minPt}\nmaxPt\t\t\t{maxPt}\npythiaErrorTolerance\t{pythiaErrorTolerance}")
71+
print(f"externalDecayer\t\t{externalDecayer}\ndecayLongLived\t\t{decayLongLived}\ndynamicalPtRange\t{dynamicalPtRange}\nuseYWeights\t\t{useYWeights}\nparamV2FileDir\t{paramV2FileDir}\ntoFixEP\t\t\t{toFixEP}\nyGenRange\t\t{yGenRange}")
72+
print(f"useLMeeDecaytable\t{useLMeeDecaytable}\nweightingMode\t\t{weightingMode}")
73+
ini_file = abspath(join(args.output,IniName))
74+
print("==> Writing simulation configuration to "+ini_file)
75+
os.makedirs(os.path.dirname(ini_file), exist_ok=True)
76+
with open(f"{ini_file}",'w') as f:
77+
f.write(f"[GeneratorExternal]\nfileName = {generatorName}\nfuncName={generatorFunc}(")
78+
f.write(f"{collisionSystem},{centrality},{decayMode},{selectedMothers},\"{paramFile}\",\"{paramFileDir}\",{numberOfParticles},{minPt},{maxPt},{pythiaErrorTolerance},{externalDecayer},{decayLongLived},{dynamicalPtRange},{useYWeights},\"{paramV2FileDir}\",{toFixEP},{yGenRange},\"{useLMeeDecaytable}\",{weightingMode}")
79+
f.write(")")
80+
return ini_file
81+
82+
def run_only_simulation(args):
83+
sim_log_name = "simlog"
84+
name="o2sim"
85+
86+
output_dir = abspath(args.output)
87+
output_name = abspath(join(args.output,name))
88+
ini_file = abspath(args.sim_ini_file)
89+
log_file = abspath(join(args.output,sim_log_name))
90+
91+
current_dir = os.getcwd()
92+
if not exists(output_dir):
93+
os.makedirs(output_dir)
94+
os.chdir(output_dir)
95+
96+
97+
print("\n==> Running cocktail simulation")
98+
command_to_run = ['o2-sim','-n',args.nEvents,'-g','external','-o',output_name,'--configFile',ini_file,'--noGeant']
99+
print("running with: ",end='')
100+
print(*command_to_run)
101+
print("redirect output to "+log_file)
102+
print("\nrunning...")
103+
f = open(log_file, "w")
104+
simproc = subprocess.Popen(['o2-sim','-n',args.nEvents,'-g','external','-o',output_name,'--configFile',ini_file,'--noGeant'], stdout=f, stderr=subprocess.STDOUT)
105+
simproc.communicate()
106+
f.close()
107+
print("...done\n")
108+
109+
os.chdir(current_dir)
110+
111+
if args.clean:
112+
clean(args.output,name,True)
113+
114+
if not simproc.returncode==0:
115+
print("ERROR: o2sim finished with error. See "+abspath(join(args.output,name+"_serverlog"))+" and "+log_file+"for details\n")
116+
return 1
117+
else:
118+
print("Cocktail simulation finished successful. Result in "+output_name+"_Kine.root\n")
119+
return 0
120+
121+
122+
def run_only_analysis_task(args):
123+
sim_log_name = "readerlog"
124+
ana_log_name = "analog"
125+
name="kineReader"
126+
127+
print("\n==> Running cocktail analysis task")
128+
129+
output_dir = abspath(args.output)
130+
output_name = join(output_dir,name)
131+
current_dir = os.getcwd()
132+
133+
kin_file = abspath(args.input)
134+
json_file = abspath(args.ana_config_file)
135+
sim_log_file = join(output_dir,sim_log_name)
136+
ana_log_file = join(output_dir,ana_log_name)
137+
138+
if not exists(output_dir):
139+
os.makedirs(output_dir)
140+
os.chdir(output_dir)
141+
142+
f = root.TFile(kin_file)
143+
tree = f.Get("o2sim")
144+
nEvents = tree.GetEntries()
145+
print(f"Found {nEvents} events in {kin_file}")
146+
#MCTrack
147+
#@size
148+
149+
sim_command_to_run = ['o2-sim','-g','extkinO2','-n',str(nEvents),'-o',output_name,'--extKinFile',kin_file,'--noGeant','--forwardKine','--noDiscOutput']
150+
print("running reader with: ",end='')
151+
print(*sim_command_to_run)
152+
print("redirect reader output to "+sim_log_file)
153+
154+
fs = open(sim_log_file, "w")
155+
simproc = subprocess.Popen(sim_command_to_run, stdout=fs, stderr=subprocess.STDOUT)
156+
157+
proxy_command_to_run = ['o2-sim-mctracks-proxy','--nevents',str(nEvents),'--o2sim-pid',str(simproc.pid)]
158+
ana_command_to_run = ['o2-analysis-em-lmee-lf-cocktail', '--configuration','json://'+json_file,'-b']
159+
print("running analysis with: ",end='')
160+
print(*proxy_command_to_run,end='')
161+
print(" | ",end='')
162+
print(*ana_command_to_run)
163+
print("redirect analysis output to "+ana_log_file)
164+
165+
fa = open(ana_log_file,"w")
166+
proxyproc = subprocess.Popen(proxy_command_to_run, stdout=subprocess.PIPE)
167+
anaproc = subprocess.Popen(ana_command_to_run, stdin=proxyproc.stdout, stdout=fa, stderr=subprocess.STDOUT)
168+
169+
print("\nrunning...\n")
170+
simproc.communicate()
171+
if not simproc.returncode==0:
172+
print("ERROR: Reader finished with error. See "+abspath(join(args.output,name+"_serverlog"))+" and "+sim_log_file+" for details\n")
173+
proxyproc.kill();
174+
anaproc.kill();
175+
proxyproc.communicate()
176+
anaproc.communicate()
177+
fs.close()
178+
fa.close()
179+
print("...done\n")
180+
181+
182+
if not anaproc.returncode==0:
183+
print("ERROR: Analysis task finished with error. See "+abspath(join(args.output,"analog"))+" for details\n")
184+
else:
185+
print("Analysis task finished successful. Histograms in "+output_dir+"/AnalysisResults.root\n")
186+
187+
os.chdir(current_dir)
188+
189+
clean(args.output,name,False)
190+
191+
if (not simproc.returncode) and (not anaproc.returncode):
192+
return 0
193+
else:
194+
return 1
195+
196+
def run_full(args):
197+
sim_log_name = "simlog"
198+
ana_log_name = "analog"
199+
name="o2sim"
200+
201+
print("\n==> Running cocktail simulation + analysis task")
202+
203+
output_dir = abspath(args.output)
204+
output_name = join(output_dir,name)
205+
current_dir = os.getcwd()
206+
207+
ini_file = abspath(args.sim_ini_file)
208+
json_file = abspath(args.ana_config_file)
209+
sim_log_file = join(output_dir,sim_log_name)
210+
ana_log_file = join(output_dir,ana_log_name)
211+
212+
if not exists(output_dir):
213+
os.makedirs(output_dir)
214+
os.chdir(output_dir)
215+
216+
sim_command_to_run = ['o2-sim','-g','external','-n',args.nEvents,'-o',output_name,'--configFile',ini_file,'--noGeant','--forwardKine']
217+
if not args.save_kine:
218+
sim_command_to_run.append('--noDiscOutput')
219+
print("running simulation with: ",end='')
220+
print(*sim_command_to_run)
221+
print("redirect sim output to "+sim_log_file)
222+
223+
fs = open(sim_log_file, "w")
224+
simproc = subprocess.Popen(sim_command_to_run, stdout=fs, stderr=subprocess.STDOUT)
225+
226+
proxy_command_to_run = ['o2-sim-mctracks-proxy','--nevents',args.nEvents,'--o2sim-pid',str(simproc.pid)]
227+
ana_command_to_run = ['o2-analysis-em-lmee-lf-cocktail','--configuration','json://'+json_file,'-b']
228+
print("running analysis with: ",end='')
229+
print(*proxy_command_to_run,end='')
230+
print(" | ",end='')
231+
print(*ana_command_to_run)
232+
print("redirect analysis output to "+ana_log_file)
233+
234+
fa = open(ana_log_file,"w")
235+
proxyproc = subprocess.Popen(proxy_command_to_run, stdout=subprocess.PIPE)
236+
anaproc = subprocess.Popen(ana_command_to_run, stdin=proxyproc.stdout, stdout=fa, stderr=subprocess.STDOUT)
237+
238+
print("\nrunning...\n")
239+
simproc.communicate()
240+
if not simproc.returncode==0:
241+
print("ERROR: o2sim finished with error. See "+abspath(join(args.output,name+"_serverlog"))+" and "+sim_log_file+" for details\n")
242+
proxyproc.kill();
243+
anaproc.kill();
244+
else:
245+
print("Cocktail simulation finished successful.",end='')
246+
if args.save_kine:
247+
print(" Output written to "+output_name+"_Kine.root.",end='')
248+
print(" Waiting for analysis task to finish...\n")
249+
proxyproc.communicate()
250+
anaproc.communicate()
251+
fs.close()
252+
fa.close()
253+
print("...done\n")
254+
255+
256+
if not anaproc.returncode==0:
257+
print("ERROR: Analysis task finished with error. See "+abspath(join(args.output,"analog"))+" for details\n")
258+
else:
259+
print("Analysis task finished successful. Histograms in "+output_dir+"/AnalysisResults.root\n")
260+
261+
os.chdir(current_dir)
262+
263+
if args.clean:
264+
clean(args.output,name,True)
265+
266+
if (not simproc.returncode) and (not anaproc.returncode):
267+
return 0
268+
else:
269+
return 1
270+
271+
def main():
272+
parser = argparse.ArgumentParser()
273+
common_sim_parser = argparse.ArgumentParser(add_help=False)
274+
sim_input = common_sim_parser.add_mutually_exclusive_group(required=True)
275+
common_sim_parser.add_argument("--nEvents","-n",help="Number of events to be generated",required=True)
276+
sim_input.add_argument("--sim-ini-file",dest="sim_ini_file",help="INI file for the generator")
277+
sim_input.add_argument("--sim-config-file",dest="sim_config_file",help="JSON config file for the generator (will be converted to INI file)")
278+
common_sim_parser.add_argument("--output","-o",default=os.getcwd(),help="Output directory")
279+
common_sim_parser.add_argument("--clean", dest="clean", action="store_true",help="Delete unwanted files after finishing the job")
280+
common_ana_parser = argparse.ArgumentParser(add_help=False)
281+
common_ana_parser.add_argument("--ana-config-file",dest="ana_config_file",help="Config file for the analysis task",required=True)
282+
sub_parsers = parser.add_subparsers(dest="command",required=True)
283+
sim_parser = sub_parsers.add_parser("sim-only",parents=[common_sim_parser])
284+
ana_parser = sub_parsers.add_parser("ana-only",parents=[common_ana_parser])
285+
ana_parser.add_argument("--input","-i",help="Analysis input file",required=True)
286+
ana_parser.add_argument("--output","-o",default=os.getcwd(),help="Output directory")
287+
full_parser = sub_parsers.add_parser("full",parents=[common_sim_parser,common_ana_parser])
288+
full_parser.add_argument("--save-kine",dest="save_kine",action="store_true",help="Write the generator output to o2sim_Kine.root")
289+
args = parser.parse_args()
290+
291+
print("\n######################")
292+
print("## LMee LF Cocktail ##")
293+
print("######################")
294+
295+
print("\n==> Running in mode \'"+args.command+"\'\n")
296+
297+
if ( ((args.command=="full") or (args.command=="sim-only")) and args.sim_config_file):
298+
args.sim_ini_file=read_sim_config(args)
299+
if args.sim_ini_file == 1:
300+
return 1
301+
302+
if (args.command=="full"):
303+
return run_full(args)
304+
if (args.command=="sim-only"):
305+
return run_only_simulation(args)
306+
if (args.command=="ana-only"):
307+
return run_only_analysis_task(args)
308+
309+
main()

0 commit comments

Comments
 (0)