3 from __future__
import print_function
4 from future.utils
import lmap
13 import Alignment.OfflineValidation.TkAlAllInOneTool.findAndChange
as fnc
15 import Alignment.OfflineValidation.TkAlAllInOneTool.GCP
as GCP
16 import Alignment.OfflineValidation.TkAlAllInOneTool.DMR
as DMR
17 import Alignment.OfflineValidation.TkAlAllInOneTool.Zmumu
as Zmumu
18 import Alignment.OfflineValidation.TkAlAllInOneTool.PV
as PV
19 import Alignment.OfflineValidation.TkAlAllInOneTool.SplitV
as SplitV
20 import Alignment.OfflineValidation.TkAlAllInOneTool.JetHT
as JetHT
25 """ Parse user input """ 27 parser = argparse.ArgumentParser(description =
"AllInOneTool for validation of the tracker alignment", formatter_class=argparse.RawTextHelpFormatter)
28 parser.add_argument(
"config", metavar=
'config', type=str, action=
"store", help=
"Global AllInOneTool config (json/yaml format)")
29 parser.add_argument(
"-d",
"--dry", action =
"store_true", help =
"Set up everything, but don't run anything")
30 parser.add_argument(
"-v",
"--verbose", action =
"store_true", help =
"Enable standard output stream")
31 parser.add_argument(
"-e",
"--example", action =
"store_true", help =
"Print example of config in JSON format")
32 parser.add_argument(
"-f",
"--force", action =
"store_true", help =
"Force creation of enviroment, possible overwritten old configuration")
33 parser.add_argument(
"-j",
"--job-flavour", action =
"store", default =
"workday", choices = [
"espresso",
"microcentury",
"longlunch",
"workday",
"tomorrow",
"testmatch",
"nextweek"], help =
"Job flavours for HTCondor at CERN, default is 'workday'")
35 return parser.parse_args()
40 """Check if GRID proxy has been initialized.""" 43 with open(os.devnull,
"w")
as dump:
44 subprocess.check_call([
"voms-proxy-info",
"--exists"],
45 stdout = dump, stderr = dump)
46 except subprocess.CalledProcessError:
53 """Forward proxy to location visible from the batch system. 55 - `rundir`: directory for storing the forwarded proxy 57 - Full path to the forwarded proxy 61 print(
"Please create proxy via 'voms-proxy-init -voms cms'.")
65 proxyName =
"{}/.user_proxy".
format(rundir)
66 localProxy = subprocess.check_output([
"voms-proxy-info",
"--path"]).
strip()
67 shutil.copyfile(localProxy, proxyName)
76 """Update a template configuration file with custom configuration 78 - configurationFile: File name for the configuration file that will be updated 79 - updateInstructions: A dictionary defining the updated configuration with keys "overwrite", "remove", "add" and "addBefore" each containing a list with the instructions on what should be replaced, removed or added. 83 with open(configurationFile,
"r") as inputFile: fileContent = inputFile.readlines() 86 if "overwrite" in updateInstructions:
88 for instruction
in updateInstructions[
"overwrite"]:
90 decodeInstruction = instruction.split(
"|")
91 if(len(decodeInstruction) > 1):
92 lineToReplace = decodeInstruction[0]
93 newInstruction = instruction[instruction.index(
"|")+1:]
95 lineToReplace = instruction.split()[0]
96 newInstruction = instruction
98 lineOverwritten =
False 99 for iLine
in range(0,len(fileContent)):
100 if fileContent[iLine].startswith(lineToReplace):
101 fileContent[iLine] = newInstruction
102 if not fileContent[iLine].endswith(
"\n"):
103 fileContent[iLine] = fileContent[iLine] +
"\n" 104 lineOverwritten =
True 108 if not lineOverwritten:
109 fileContent.append(newInstruction)
110 if not fileContent[-1].endswith(
"\n"):
111 fileContent[-1] = fileContent[-1] +
"\n" 114 if "remove" in updateInstructions:
115 for instruction
in updateInstructions[
"remove"]:
116 for iLine
in range(0,len(fileContent)):
117 if fileContent[iLine].startswith(instruction):
118 fileContent.pop(iLine)
122 if "add" in updateInstructions:
123 for instruction
in updateInstructions[
"add"]:
124 categories = instruction.split(
".")
125 if len(categories) > 2:
126 category = categories[1]
128 category =
"nonExistent" 129 previousCategory =
"" 133 for iLine
in range(0,len(fileContent)):
134 if fileContent[iLine] ==
"\n" and previousCategory == category:
135 fileContent.insert(iLine, instruction)
136 if not fileContent[iLine].endswith(
"\n"):
137 fileContent[iLine] = fileContent[iLine] +
"\n" 140 elif fileContent[iLine] ==
"\n":
141 previousCategory =
"" 143 newCategories = fileContent[iLine].
split(
".")
144 if len(newCategories) > 2:
145 previousCategory = newCategories[1]
147 previousCategory =
"" 151 fileContent.append(instruction)
152 if not fileContent[-1].endswith(
"\n"):
153 fileContent[-1] = fileContent[-1] +
"\n" 156 if "addBefore" in updateInstructions:
157 for instruction
in updateInstructions[
"addBefore"]:
158 lineBefore = instruction.split(
"|")[0]
159 newInstruction = instruction[instruction.index(
"|")+1:]
161 for iLine
in range(0,len(fileContent)):
162 if fileContent[iLine].startswith(lineBefore):
163 fileContent.insert(iLine,newInstruction)
164 if not fileContent[iLine].endswith(
"\n"):
165 fileContent[iLine] = fileContent[iLine] +
"\n" 172 fileContent.append(newInstruction)
173 if not fileContent[-1].endswith(
"\n"):
174 fileContent[-1] = fileContent[-1] +
"\n" 177 with open(configurationFile,
"w")
as outputFile:
178 outputFile.writelines(fileContent)
187 print(
"Grid proxy is required in most use cases of the tool.")
188 print(
"Please create a proxy via 'voms-proxy-init -voms cms'.")
196 with open(
"{}/src/Alignment/OfflineValidation/bin/example.yaml".
format(os.environ[
"CMSSW_BASE"]),
"r") as exampleFile: config = yaml.load(exampleFile, Loader=yaml.Loader) 197 pprint.pprint(config, width=30) 201 with open(args.config, "r") as configFile: if args.verbose:
202 print(
"Read AllInOne config: '{}'".
format(args.config))
204 if args.config.split(
".")[-1] ==
"json":
205 config = json.load(configFile)
207 elif args.config.split(
".")[-1] ==
"yaml":
208 config = yaml.load(configFile, Loader=yaml.Loader)
211 raise Exception(
"Unknown config extension '{}'. Please use json/yaml format!".
format(args.config.split(
".")[-1]))
214 for path
in fnc.find_and_change(list(), config):
215 if args.verbose
and (
"." in str(path)
or "/" in str(path)):
219 if os.path.isdir(config[
"name"])
and not args.force:
220 raise Exception(
"Validation directory '{}' already exists! Please choose another name for your directory.".
format(config[
"name"]))
222 validationDir = os.path.abspath(config[
"name"])
223 exeDir =
"{}/executables".
format(validationDir)
224 cmsconfigDir =
"{}/cmsConfigs".
format(validationDir)
226 subprocess.call([
"mkdir",
"-p", validationDir] + (([
"-v"]
if args.verbose
else [])))
227 subprocess.call([
"mkdir",
"-p", exeDir] + ([
"-v"]
if args.verbose
else []))
228 subprocess.call([
"mkdir",
"-p", cmsconfigDir] + ([
"-v"]
if args.verbose
else []))
231 subprocess.call([
"cp",
"-f", args.config, validationDir] + ([
"-v"]
if args.verbose
else []))
234 crabTemplateFile = fnc.digest_path(
"$CMSSW_BASE/src/Alignment/OfflineValidation/python/TkAlAllInOneTool/templates/crabTemplate.py")
235 condorTemplateFile = fnc.digest_path(
"$CMSSW_BASE/src/Alignment/OfflineValidation/python/TkAlAllInOneTool/templates/condorTemplate.submit")
236 executableTempleteFile = fnc.digest_path(
"$CMSSW_BASE/src/Alignment/OfflineValidation/python/TkAlAllInOneTool/templates/executableTemplate.sh")
243 for validation
in config[
"validations"]:
244 if validation ==
"GCP":
245 jobs.extend(
GCP.GCP(config, validationDir))
247 elif validation ==
"DMR":
248 jobs.extend(
DMR.DMR(config, validationDir))
250 elif validation ==
"Zmumu":
253 elif validation ==
"PV":
254 jobs.extend(
PV.PV(config, validationDir))
256 elif validation ==
"SplitV":
259 elif validation ==
"JetHT":
266 subprocess.call([
"mkdir",
"-p",
"{}/DAG/".
format(validationDir)] + ([
"-v"]
if args.verbose
else []))
268 with open(
"{}/DAG/dagFile".
format(validationDir),
"w")
as dag:
271 subprocess.call([
"mkdir",
"-p", job[
"dir"]] + ([
"-v"]
if args.verbose
else []))
272 subprocess.call([
"mkdir",
"-p", job[
"config"][
"output"]] + ([
"-v"]
if args.verbose
else []))
273 subprocess.call([
"mkdir",
"-p",
"{}/condor".
format(job[
"dir"])] + ([
"-v"]
if args.verbose
else []))
274 subprocess.call([
"ln",
"-fs", job[
"config"][
"output"],
"{}/output".
format(job[
"dir"])] + ([
"-v"]
if args.verbose
else []))
277 crabConfigurationFile =
"{}/crabConfiguration.py".
format(job[
"dir"])
278 subprocess.call([
"cp", crabTemplateFile, crabConfigurationFile] + ([
"-v"]
if args.verbose
else []))
279 condorSubmitFile =
"{}/condor.sub".
format(job[
"dir"])
280 subprocess.call([
"cp", condorTemplateFile, condorSubmitFile] + ([
"-v"]
if args.verbose
else []))
281 executableFile =
"{}/run.sh".
format(job[
"dir"])
282 subprocess.call([
"cp", executableTempleteFile, executableFile] + ([
"-v"]
if args.verbose
else []))
286 print(
"Forwarding grid proxy to directory {}".
format(job[
"dir"]))
290 subprocess.call(
"cp -f $(which {}) {}".
format(job[
"exe"], exeDir) + (
" -v" if args.verbose
else ""), shell =
True)
291 subprocess.call([
"ln",
"-fs",
"{}/{}".
format(exeDir, job[
"exe"]), job[
"dir"]] + ([
"-v"]
if args.verbose
else []))
292 if "cms-config" in job:
293 cmsConfig = job[
"cms-config"].
split(
"/")[-1]
295 subprocess.call([
"cp",
"-f", job[
"cms-config"],
"{}/{}".
format(cmsconfigDir, cmsConfig)] + ([
"-v"]
if args.verbose
else []))
296 subprocess.call([
"ln",
"-fs",
"{}/{}".
format(cmsconfigDir, cmsConfig),
"{}/validation_cfg.py".
format(job[
"dir"])] + ([
"-v"]
if args.verbose
else []))
299 with open(
"{}/validation.json".
format(job[
"dir"]),
"w")
as jsonFile:
301 print(
"Write local json config: '{}'".
format(
"{}/validation.json".
format(job[
"dir"])))
303 json.dump(job[
"config"], jsonFile, indent=4)
306 executableCustomization = {
"overwrite": [],
"addBefore": []}
308 executableCustomization[
"overwrite"].
append(
"export X509|export X509_USER_PROXY={}".
format(myProxy))
309 executableCustomization[
"overwrite"].
append(
"cd workDir|cd {}".
format(job[
"dir"]))
312 if "exeArguments" in job:
313 executableCustomization[
"overwrite"].
append(
"./cmsRun|./{} {}".
format(job[
"exe"], job[
"exeArguments"]))
315 executableCustomization[
"overwrite"].
append(
"./cmsRun|./{} {}validation.json".
format(job[
"exe"],
"validation_cfg.py config=" if "cms-config" in job
else ""))
318 if "nCondorJobs" in job:
319 executableCustomization[
"addBefore"].
append(
"./{}|JOBNUMBER=${{1:--1}}".
format(job[
"exe"]))
325 subprocess.call([
"chmod",
"a+rx", executableFile] + ([
"-v"]
if args.verbose
else []))
328 condorSubmitCustomization = {
"overwrite": [],
"addBefore": []}
331 condorSubmitCustomization[
"overwrite"].
append(
'+JobFlavour = "{}"'.
format(args.job_flavour
if not 'flavour' in job
else job[
'flavour']))
334 if "nCondorJobs" in job:
335 condorSubmitCustomization[
"addBefore"].
append(
"output|arguments = $(ProcID)")
336 condorSubmitCustomization[
"overwrite"].
append(
"output = condor/condor$(ProcID).out")
337 condorSubmitCustomization[
"overwrite"].
append(
"error = condor/condor$(ProcID).err")
338 condorSubmitCustomization[
"overwrite"].
append(
"log = condor/condor$(ProcID).log")
339 condorSubmitCustomization[
"overwrite"].
append(
"queue {}".
format(job[
"nCondorJobs"]))
345 dag.write(
"JOB {} condor.sub DIR {}\n".
format(job[
"name"], job[
"dir"]))
347 if job[
"dependencies"]:
349 dag.write(
"PARENT {} CHILD {}".
format(
" ".
join(job[
"dependencies"]), job[
"name"]))
354 if "crabCustomConfiguration" in job[
"config"]:
359 print(
"DAGman config has been written: '{}'".
format(
"{}/DAG/dagFile".
format(validationDir)))
363 print(
"Enviroment is set up. If you want to submit everything, call 'condor_submit_dag {}/DAG/dagFile'".
format(validationDir))
366 subprocess.call([
"condor_submit_dag",
"{}/DAG/dagFile".
format(validationDir)])
369 if __name__ ==
"__main__":
372 def SplitV(config, validationDir)
def Zmumu(config, validationDir)
def updateConfigurationFile(configurationFile, updateInstructions)
def forward_proxy(rundir)
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
def DMR(config, validationDir)
def split(sequence, size)
static std::string join(char **cmd)
def PV(config, validationDir)
def GCP(config, validationDir)
def JetHT(config, validationDir)