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.PV
as PV
18 import Alignment.OfflineValidation.TkAlAllInOneTool.SplitV
as SplitV
19 import Alignment.OfflineValidation.TkAlAllInOneTool.JetHT
as JetHT
24 """ Parse user input """ 26 parser = argparse.ArgumentParser(description =
"AllInOneTool for validation of the tracker alignment", formatter_class=argparse.RawTextHelpFormatter)
27 parser.add_argument(
"config", metavar=
'config', type=str, action=
"store", help=
"Global AllInOneTool config (json/yaml format)")
28 parser.add_argument(
"-d",
"--dry", action =
"store_true", help =
"Set up everything, but don't run anything")
29 parser.add_argument(
"-v",
"--verbose", action =
"store_true", help =
"Enable standard output stream")
30 parser.add_argument(
"-e",
"--example", action =
"store_true", help =
"Print example of config in JSON format")
31 parser.add_argument(
"-f",
"--force", action =
"store_true", help =
"Force creation of enviroment, possible overwritten old configuration")
32 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'")
34 return parser.parse_args()
39 """Check if GRID proxy has been initialized.""" 42 with open(os.devnull,
"w")
as dump:
43 subprocess.check_call([
"voms-proxy-info",
"--exists"],
44 stdout = dump, stderr = dump)
45 except subprocess.CalledProcessError:
52 """Forward proxy to location visible from the batch system. 54 - `rundir`: directory for storing the forwarded proxy 56 - Full path to the forwarded proxy 60 print(
"Please create proxy via 'voms-proxy-init -voms cms'.")
64 proxyName =
"{}/.user_proxy".
format(rundir)
65 localProxy = subprocess.check_output([
"voms-proxy-info",
"--path"]).
strip()
66 shutil.copyfile(localProxy, proxyName)
75 """Update a template configuration file with custom configuration 77 - configurationFile: File name for the configuration file that will be updated 78 - 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. 82 with open(configurationFile,
"r") as inputFile: fileContent = inputFile.readlines() 85 if "overwrite" in updateInstructions:
87 for instruction
in updateInstructions[
"overwrite"]:
89 decodeInstruction = instruction.split(
"|")
90 if(len(decodeInstruction) > 1):
91 lineToReplace = decodeInstruction[0]
92 newInstruction = instruction[instruction.index(
"|")+1:]
94 lineToReplace = instruction.split()[0]
95 newInstruction = instruction
97 lineOverwritten =
False 98 for iLine
in range(0,len(fileContent)):
99 if fileContent[iLine].startswith(lineToReplace):
100 fileContent[iLine] = newInstruction
101 if not fileContent[iLine].endswith(
"\n"):
102 fileContent[iLine] = fileContent[iLine] +
"\n" 103 lineOverwritten =
True 107 if not lineOverwritten:
108 fileContent.append(newInstruction)
109 if not fileContent[-1].endswith(
"\n"):
110 fileContent[-1] = fileContent[-1] +
"\n" 113 if "remove" in updateInstructions:
114 for instruction
in updateInstructions[
"remove"]:
115 for iLine
in range(0,len(fileContent)):
116 if fileContent[iLine].startswith(instruction):
117 fileContent.pop(iLine)
121 if "add" in updateInstructions:
122 for instruction
in updateInstructions[
"add"]:
123 categories = instruction.split(
".")
124 if len(categories) > 2:
125 category = categories[1]
127 category =
"nonExistent" 128 previousCategory =
"" 132 for iLine
in range(0,len(fileContent)):
133 if fileContent[iLine] ==
"\n" and previousCategory == category:
134 fileContent.insert(iLine, instruction)
135 if not fileContent[iLine].endswith(
"\n"):
136 fileContent[iLine] = fileContent[iLine] +
"\n" 139 elif fileContent[iLine] ==
"\n":
140 previousCategory =
"" 142 newCategories = fileContent[iLine].
split(
".")
143 if len(newCategories) > 2:
144 previousCategory = newCategories[1]
146 previousCategory =
"" 150 fileContent.append(instruction)
151 if not fileContent[-1].endswith(
"\n"):
152 fileContent[-1] = fileContent[-1] +
"\n" 155 if "addBefore" in updateInstructions:
156 for instruction
in updateInstructions[
"addBefore"]:
157 lineBefore = instruction.split(
"|")[0]
158 newInstruction = instruction[instruction.index(
"|")+1:]
160 for iLine
in range(0,len(fileContent)):
161 if fileContent[iLine].startswith(lineBefore):
162 fileContent.insert(iLine,newInstruction)
163 if not fileContent[iLine].endswith(
"\n"):
164 fileContent[iLine] = fileContent[iLine] +
"\n" 171 fileContent.append(newInstruction)
172 if not fileContent[-1].endswith(
"\n"):
173 fileContent[-1] = fileContent[-1] +
"\n" 176 with open(configurationFile,
"w")
as outputFile:
177 outputFile.writelines(fileContent)
186 print(
"Grid proxy is required in most use cases of the tool.")
187 print(
"Please create a proxy via 'voms-proxy-init -voms cms'.")
195 with open(
"{}/src/Alignment/OfflineValidation/bin/example.yaml".
format(os.environ[
"CMSSW_BASE"]),
"r") as exampleFile: config = yaml.load(exampleFile, Loader=yaml.Loader) 196 pprint.pprint(config, width=30) 200 with open(args.config, "r") as configFile: if args.verbose:
201 print(
"Read AllInOne config: '{}'".
format(args.config))
203 if args.config.split(
".")[-1] ==
"json":
204 config = json.load(configFile)
206 elif args.config.split(
".")[-1] ==
"yaml":
207 config = yaml.load(configFile, Loader=yaml.Loader)
210 raise Exception(
"Unknown config extension '{}'. Please use json/yaml format!".
format(args.config.split(
".")[-1]))
213 for path
in fnc.find_and_change(list(), config):
214 if args.verbose
and (
"." in str(path)
or "/" in str(path)):
218 if os.path.isdir(config[
"name"])
and not args.force:
219 raise Exception(
"Validation directory '{}' already exists! Please choose another name for your directory.".
format(config[
"name"]))
221 validationDir = os.path.abspath(config[
"name"])
222 exeDir =
"{}/executables".
format(validationDir)
223 cmsconfigDir =
"{}/cmsConfigs".
format(validationDir)
225 subprocess.call([
"mkdir",
"-p", validationDir] + (([
"-v"]
if args.verbose
else [])))
226 subprocess.call([
"mkdir",
"-p", exeDir] + ([
"-v"]
if args.verbose
else []))
227 subprocess.call([
"mkdir",
"-p", cmsconfigDir] + ([
"-v"]
if args.verbose
else []))
230 subprocess.call([
"cp",
"-f", args.config, validationDir] + ([
"-v"]
if args.verbose
else []))
233 crabTemplateFile = fnc.digest_path(
"$CMSSW_BASE/src/Alignment/OfflineValidation/python/TkAlAllInOneTool/templates/crabTemplate.py")
234 condorTemplateFile = fnc.digest_path(
"$CMSSW_BASE/src/Alignment/OfflineValidation/python/TkAlAllInOneTool/templates/condorTemplate.submit")
235 executableTempleteFile = fnc.digest_path(
"$CMSSW_BASE/src/Alignment/OfflineValidation/python/TkAlAllInOneTool/templates/executableTemplate.sh")
242 for validation
in config[
"validations"]:
243 if validation ==
"GCP":
244 jobs.extend(
GCP.GCP(config, validationDir))
246 elif validation ==
"DMR":
247 jobs.extend(
DMR.DMR(config, validationDir))
249 elif validation ==
"PV":
250 jobs.extend(
PV.PV(config, validationDir))
252 elif validation ==
"SplitV":
255 elif validation ==
"JetHT":
262 subprocess.call([
"mkdir",
"-p",
"{}/DAG/".
format(validationDir)] + ([
"-v"]
if args.verbose
else []))
264 with open(
"{}/DAG/dagFile".
format(validationDir),
"w")
as dag:
267 subprocess.call([
"mkdir",
"-p", job[
"dir"]] + ([
"-v"]
if args.verbose
else []))
268 subprocess.call([
"mkdir",
"-p", job[
"config"][
"output"]] + ([
"-v"]
if args.verbose
else []))
269 subprocess.call([
"mkdir",
"-p",
"{}/condor".
format(job[
"dir"])] + ([
"-v"]
if args.verbose
else []))
270 subprocess.call([
"ln",
"-fs", job[
"config"][
"output"],
"{}/output".
format(job[
"dir"])] + ([
"-v"]
if args.verbose
else []))
273 crabConfigurationFile =
"{}/crabConfiguration.py".
format(job[
"dir"])
274 subprocess.call([
"cp", crabTemplateFile, crabConfigurationFile] + ([
"-v"]
if args.verbose
else []))
275 condorSubmitFile =
"{}/condor.sub".
format(job[
"dir"])
276 subprocess.call([
"cp", condorTemplateFile, condorSubmitFile] + ([
"-v"]
if args.verbose
else []))
277 executableFile =
"{}/run.sh".
format(job[
"dir"])
278 subprocess.call([
"cp", executableTempleteFile, executableFile] + ([
"-v"]
if args.verbose
else []))
282 print(
"Forwarding grid proxy to directory {}".
format(job[
"dir"]))
286 subprocess.call(
"cp -f $(which {}) {}".
format(job[
"exe"], exeDir) + (
" -v" if args.verbose
else ""), shell =
True)
287 subprocess.call([
"ln",
"-fs",
"{}/{}".
format(exeDir, job[
"exe"]), job[
"dir"]] + ([
"-v"]
if args.verbose
else []))
288 if "cms-config" in job:
289 cmsConfig = job[
"cms-config"].
split(
"/")[-1]
291 subprocess.call([
"cp",
"-f", job[
"cms-config"],
"{}/{}".
format(cmsconfigDir, cmsConfig)] + ([
"-v"]
if args.verbose
else []))
292 subprocess.call([
"ln",
"-fs",
"{}/{}".
format(cmsconfigDir, cmsConfig),
"{}/validation_cfg.py".
format(job[
"dir"])] + ([
"-v"]
if args.verbose
else []))
295 with open(
"{}/validation.json".
format(job[
"dir"]),
"w")
as jsonFile:
297 print(
"Write local json config: '{}'".
format(
"{}/validation.json".
format(job[
"dir"])))
299 json.dump(job[
"config"], jsonFile, indent=4)
302 executableCustomization = {
"overwrite": [],
"addBefore": []}
304 executableCustomization[
"overwrite"].
append(
"export X509|export X509_USER_PROXY={}".
format(myProxy))
305 executableCustomization[
"overwrite"].
append(
"cd workDir|cd {}".
format(job[
"dir"]))
308 if "exeArguments" in job:
309 executableCustomization[
"overwrite"].
append(
"./cmsRun|./{} {}".
format(job[
"exe"], job[
"exeArguments"]))
311 executableCustomization[
"overwrite"].
append(
"./cmsRun|./{} {}validation.json".
format(job[
"exe"],
"validation_cfg.py config=" if "cms-config" in job
else ""))
314 if "nCondorJobs" in job:
315 executableCustomization[
"addBefore"].
append(
"./{}|JOBNUMBER=${{1:--1}}".
format(job[
"exe"]))
321 subprocess.call([
"chmod",
"a+rx", executableFile] + ([
"-v"]
if args.verbose
else []))
324 condorSubmitCustomization = {
"overwrite": [],
"addBefore": []}
327 condorSubmitCustomization[
"overwrite"].
append(
'+JobFlavour = "{}"'.
format(args.job_flavour
if not 'flavour' in job
else job[
'flavour']))
330 if "nCondorJobs" in job:
331 condorSubmitCustomization[
"addBefore"].
append(
"output|arguments = $(ProcID)")
332 condorSubmitCustomization[
"overwrite"].
append(
"output = condor/condor$(ProcID).out")
333 condorSubmitCustomization[
"overwrite"].
append(
"error = condor/condor$(ProcID).err")
334 condorSubmitCustomization[
"overwrite"].
append(
"log = condor/condor$(ProcID).log")
335 condorSubmitCustomization[
"overwrite"].
append(
"queue {}".
format(job[
"nCondorJobs"]))
341 dag.write(
"JOB {} condor.sub DIR {}\n".
format(job[
"name"], job[
"dir"]))
343 if job[
"dependencies"]:
345 dag.write(
"PARENT {} CHILD {}".
format(
" ".
join(job[
"dependencies"]), job[
"name"]))
350 if "crabCustomConfiguration" in job[
"config"]:
355 print(
"DAGman config has been written: '{}'".
format(
"{}/DAG/dagFile".
format(validationDir)))
359 print(
"Enviroment is set up. If you want to submit everything, call 'condor_submit_dag {}/DAG/dagFile'".
format(validationDir))
362 subprocess.call([
"condor_submit_dag",
"{}/DAG/dagFile".
format(validationDir)])
365 if __name__ ==
"__main__":
368 def SplitV(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)