21 import Alignment.MillePedeAlignmentAlgorithm.mpslib.Mpslibclass
as mpslib
22 import Alignment.MillePedeAlignmentAlgorithm.mpslib.tools
as mps_tools
23 import Alignment.MillePedeAlignmentAlgorithm.mpsvalidate.iniparser
as mpsv_iniparser
24 import Alignment.MillePedeAlignmentAlgorithm.mpsvalidate.trackerTree
as mpsv_trackerTree
25 from Alignment.MillePedeAlignmentAlgorithm.alignmentsetup.helper
import checked_out_MPS
26 from functools
import reduce
31 Wrapper around subprocess calls which treats output depending on verbosity 35 - `command`: list of command items 36 - `verbose`: flag to turn on verbosity 39 call_method = subprocess.check_call
if verbose
else subprocess.check_output
41 call_method(command, stderr=subprocess.STDOUT)
42 except subprocess.CalledProcessError
as e:
43 print "" if verbose
else e.output
44 print "Failed to execute command:",
" ".
join(command)
49 """Extracts different weight configurations from `config`. 52 - `config`: ConfigParser object containing the alignment configuration 55 weight_dict = collections.OrderedDict()
59 for section
in config.sections():
60 if 'general' in section:
62 elif section ==
"weights":
63 for option
in config.options(section):
64 common_weights[option] = [x.strip()
for x
in 65 config.get(section, option).
split(
",")]
66 elif section.startswith(
"dataset:"):
68 if config.has_option(section,
'weight'):
69 weight_dict[name] = [x.strip()
for x
in 70 config.get(section,
"weight").
split(
",")]
72 weight_dict[name] = [
'1.0']
74 weights_list = [[(name, weight)
for weight
in weight_dict[name]]
75 for name
in weight_dict]
77 common_weights_list = [[(name, weight)
for weight
in common_weights[name]]
78 for name
in common_weights]
79 common_weights_dicts = []
80 for item
in itertools.product(*common_weights_list):
82 for name,weight
in item:
84 common_weights_dicts.append(d)
87 for weight_conf
in itertools.product(*weights_list):
88 if len(common_weights) > 0:
89 for common_weight
in common_weights_dicts:
90 configs.append([(dataset[0],
91 reduce(
lambda x,y: x.replace(y, common_weight[y]),
92 common_weight, dataset[1]))
93 for dataset
in weight_conf])
95 configs.append(weight_conf)
102 Create sqlite file with single-IOV tags and use it to override the GT. If 103 the GT is already customized by the user, the customization has higher 104 priority. Returns a snippet to be appended to the configuration file 107 - `cms_process`: cms.Process object 108 - `run_number`: run from which to extract the alignment payloads 111 run_number =
int(run_number)
112 if not run_number > 0:
113 print "'FirstRunForStartGeometry' must be positive, but is", run_number
116 input_db_name = os.path.abspath(
"alignment_input.db")
117 tags = mps_tools.create_single_iov_db(
119 run_number, input_db_name)
122 for record,tag
in tags.iteritems():
124 result += (
"\nimport " 125 "Alignment.MillePedeAlignmentAlgorithm.alignmentsetup." 126 "SetCondition as tagwriter\n")
127 result += (
"\ntagwriter.setCondition(process,\n" 128 " connect = \""+tag[
"connect"]+
"\",\n" 129 " record = \""+record+
"\",\n" 130 " tag = \""+tag[
"tag"]+
"\")\n")
137 Check consistency of input alignment payloads and IOV definition. 138 Returns a dictionary with the information needed to override possibly 139 problematic input taken from the global tag. 142 - `cms_process`: cms.Process object containing the CMSSW configuration 143 - `first_run`: first run for start geometry 146 print "Checking consistency of IOV definition..." 147 iovs = mps_tools.make_unique_runranges(cms_process.AlignmentProducer)
150 "TrackerAlignmentRcd":
None,
151 "TrackerSurfaceDeformationRcd":
None,
152 "TrackerAlignmentErrorExtendedRcd":
None,
155 for condition
in cms_process.GlobalTag.toGet.value():
156 if condition.record.value()
in inputs:
157 inputs[condition.record.value()] = {
158 "tag": condition.tag.value(),
160 if not condition.hasParameter(
"connect")
161 else condition.connect.value())
164 inputs_from_gt = [record
for record
in inputs
if inputs[record]
is None]
165 inputs.update(mps_tools.get_tags(cms_process.GlobalTag.globaltag.value(),
169 if first_run != iovs[0]:
170 if iovs[0] == 1
and len(iovs) == 1:
171 print "Single IOV output detected in configuration and",
172 print "'FirstRunForStartGeometry' is not 1." 173 print "Creating single IOV output from input conditions in run",
174 print str(first_run)+
"." 175 for inp
in inputs: inputs[inp][
"problematic"] =
True 177 print "Value of 'FirstRunForStartGeometry' has to match first",
178 print "defined output IOV:",
179 print first_run,
"!=", iovs[0]
183 for inp
in inputs.itervalues():
184 inp[
"iovs"] = mps_tools.get_iovs(inp[
"connect"], inp[
"tag"])
187 problematic_gt_inputs = {}
188 input_indices = {key: len(value[
"iovs"]) -1
189 for key,value
in inputs.iteritems()}
190 for iov
in reversed(iovs):
192 if inputs[inp].
pop(
"problematic",
False):
193 problematic_gt_inputs[inp] = inputs[inp]
194 if inp
in problematic_gt_inputs:
continue 195 if input_indices[inp] < 0:
196 print "First output IOV boundary at run", iov,
197 print "is before the first input IOV boundary at",
198 print inputs[inp][
"iovs"][0],
"for '"+inp+
"'." 199 print "Please check your run range selection." 201 input_iov = inputs[inp][
"iovs"][input_indices[inp]]
203 if inp
in inputs_from_gt:
204 problematic_gt_inputs[inp] = inputs[inp]
205 print "Found problematic input taken from global tag." 206 print "Input IOV boundary at run",input_iov,
207 print "for '"+inp+
"' is within output IOV starting with",
208 print "run",
str(iov)+
"." 209 print "Deriving an alignment with coarse IOV granularity",
210 print "starting from finer granularity leads to wrong",
212 print "A single IOV input using the IOV of",
213 print "'FirstRunForStartGeometry' ("+
str(first_run)+
") is",
214 print "automatically created and used." 216 print "Found input IOV boundary at run",input_iov,
217 print "for '"+inp+
"' which is within output IOV starting with",
218 print "run",
str(iov)+
"." 219 print "Deriving an alignment with coarse IOV granularity",
220 print "starting from finer granularity leads to wrong results." 221 print "Please check your run range selection." 223 elif iov == input_iov:
224 input_indices[inp] -= 1
227 input_indices = {key: len(value[
"iovs"]) -1
228 for key,value
in inputs.iteritems()
229 if (key !=
"TrackerAlignmentRcd")
230 and (inp
not in problematic_gt_inputs)}
231 for iov
in reversed(inputs[
"TrackerAlignmentRcd"][
"iovs"]):
232 for inp
in input_indices:
233 input_iov = inputs[inp][
"iovs"][input_indices[inp]]
235 print "Found input IOV boundary at run",input_iov,
236 print "for '"+inp+
"' which is within 'TrackerAlignmentRcd'",
237 print "IOV starting with run",
str(iov)+
"." 238 print "Deriving an alignment with inconsistent IOV boundaries",
239 print "leads to wrong results." 240 print "Please check your input IOVs." 242 elif iov == input_iov:
243 input_indices[inp] -= 1
245 print "IOV consistency check successful." 248 return problematic_gt_inputs
252 """Create MPS mass storage directory where, e.g., mille binaries are stored. 255 - `mps_dir_name`: campaign name 256 - `general_options`: general options dictionary 260 mss_dir = general_options.get(
"massStorageDir",
261 "/eos/cms/store/caf/user/"+os.environ[
"USER"])
262 mss_dir = os.path.join(mss_dir,
"MPproduction", mps_dir_name)
264 cmd = [
"mkdir",
"-p", mss_dir]
267 if not general_options.get(
"testMode",
False):
269 with open(os.devnull,
"w")
as dump:
270 subprocess.check_call(cmd, stdout = dump, stderr = dump)
271 except subprocess.CalledProcessError:
272 print "Failed to create mass storage directory:", mss_dir
279 """Method to create hidden 'TrackerTree.root'. 282 - `global_tag`: global tag from which the tracker geometry is taken 283 - `first_run`: run to specify IOV within `global_tag` 286 config = mpsv_iniparser.ConfigData()
287 config.jobDataPath =
"." 288 config.globalTag = global_tag
289 config.firstRun = first_run
290 return mpsv_trackerTree.check(config)
295 helpEpilog =
'''Builds the config-templates from a universal config-template for each 296 dataset specified in .ini-file that is passed to this script. 297 Then calls mps_setup.pl for all datasets.''' 299 description=
'Setup the alignment as configured in the alignment_config file.',
302 parser.add_argument(
'-v',
'--verbose', action=
'store_true',
303 help=
'display detailed output of mps_setup')
305 parser.add_argument(
'-w',
'--weight', action=
'store_true',
306 help=
'create an additional mergejob with (possibly new) weights from .ini-config')
308 parser.add_argument(
'alignmentConfig', action=
'store',
309 help=
'name of the .ini config file that specifies the datasets to be used')
311 args = parser.parse_args()
312 aligmentConfig = args.alignmentConfig
315 config = ConfigParser.ConfigParser()
316 config.optionxform = str
317 config.read(aligmentConfig)
325 mpsTemplates = os.path.join(
"src",
"Alignment",
"MillePedeAlignmentAlgorithm",
"templates")
327 mpsTemplates = os.path.join(os.environ[
"CMSSW_BASE"], mpsTemplates)
329 mpsTemplates = os.path.join(os.environ[
"CMSSW_RELEASE_BASE"], mpsTemplates)
330 milleScript = os.path.join(mpsTemplates,
"mps_runMille_template.sh")
331 pedeScript = os.path.join(mpsTemplates,
"mps_runPede_rfcp_template.sh")
334 currentDir = os.getcwd()
336 match = re.search(re.compile(
'mpproduction\/mp(.+?)$', re.M|re.I),currentDir)
338 mpsdirname =
'mp'+match.group(1)
340 print "Current location does not seem to be a MillePede campaign directory:",
351 for var
in [
"classInf",
"pedeMem",
"jobname",
"FirstRunForStartGeometry"]:
353 generalOptions[var] = config.get(
'general',var)
354 except ConfigParser.NoOptionError:
355 print "No", var,
"found in [general] section. Please check ini-file." 359 generalOptions[
'datasetdir'] =
'' 360 if config.has_option(
'general',
'datasetdir'):
361 generalOptions[
'datasetdir'] = config.get(
'general',
'datasetdir')
363 os.environ[
"datasetdir"] = generalOptions[
'datasetdir']
365 print "No datasetdir given in [general] section.",
366 print "Be sure to give a full path in inputFileList." 369 for var
in (
"globaltag",
"configTemplate",
"json",
"massStorageDir",
"testMode"):
371 generalOptions[var] = config.get(
'general',var)
372 except ConfigParser.NoOptionError:
373 if var ==
"testMode":
continue 374 print "No '" + var +
"' given in [general] section." 380 pedesettings = ([x.strip()
for x
in config.get(
"general",
"pedesettings").
split(
",")]
381 if config.has_option(
"general",
"pedesettings")
else [
None])
391 if not os.path.isdir(
"jobData"):
392 print "No jobData-folder found. Properly set up the alignment before using the -w option." 394 if not os.path.exists(
"mps.db"):
395 print "No mps.db found. Properly set up the alignment before using the -w option." 400 configTemplate = config.get(
'general',
'configTemplate')
401 except ConfigParser.NoOptionError:
402 print 'No default configTemplate given in [general] section.' 403 print 'When using -w, a default configTemplate is needed to build a merge-config.' 408 globalTag = config.get(
'general',
'globaltag')
409 except ConfigParser.NoOptionError:
410 print "No default 'globaltag' given in [general] section." 411 print "When using -w, a default configTemplate is needed to build a merge-config." 415 first_run = config.get(
"general",
"FirstRunForStartGeometry")
416 except ConfigParser.NoOptionError:
417 print "Missing mandatory option 'FirstRunForStartGeometry' in [general] section." 420 for section
in config.sections():
421 if section.startswith(
"dataset:"):
423 collection = config.get(section,
"collection")
425 except ConfigParser.NoOptionError:
426 print "Missing mandatory option 'collection' in section ["+section+
"]." 430 with open(configTemplate,
"r") as f: 433 print "The config-template '"+configTemplate+
"' cannot be found." 436 tmpFile = re.sub(
'setupGlobaltag\s*\=\s*[\"\'](.*?)[\"\']',
437 'setupGlobaltag = \"'+globalTag+
'\"',
439 tmpFile = re.sub(
'setupCollection\s*\=\s*[\"\'](.*?)[\"\']',
440 'setupCollection = \"'+collection+
'\"',
442 tmpFile = re.sub(re.compile(
"setupRunStartGeometry\s*\=\s*.*$", re.M),
443 "setupRunStartGeometry = "+first_run,
446 thisCfgTemplate =
"tmp.py" 447 with open(thisCfgTemplate,
"w")
as f: f.write(tmpFile)
449 cms_process = mps_tools.get_process_object(thisCfgTemplate)
452 with open(thisCfgTemplate,
"a")
as f: f.write(overrideGT)
454 for setting
in pedesettings:
458 print "Creating pede job." 460 print "Creating pede jobs using settings from '{0}'.".
format(setting)
461 for weight_conf
in weight_confs:
466 for name,weight
in weight_conf:
473 lib = mpslib.jobdatabase()
477 jobm_path = os.path.join(
"jobData", lib.JOBDIR[-1])
482 os.path.join(jobm_path,
"alignment_merge.py")]
488 "-w", thisCfgTemplate,
489 os.path.join(jobm_path,
"alignment_merge.py"),
493 if setting
is not None: command.extend([
"-a", setting])
494 print " ".
join(command)
499 with open(os.path.join(jobm_path,
".weights.pkl"),
"wb")
as f:
500 cPickle.dump(weight_conf, f, 2)
506 if overrideGT.strip() !=
"":
508 msg = (
"Overriding global tag with single-IOV tags extracted from '{}' " 509 "for run number '{}'.".
format(generalOptions[
"globaltag"],
522 for section
in config.sections():
523 if 'general' in section:
525 elif section.startswith(
"dataset:"):
530 datasetOptions[
'name'] = section[8:]
533 for var
in [
'inputFileList',
'collection']:
535 datasetOptions[var] = config.get(section,var)
536 except ConfigParser.NoOptionError:
537 print 'No', var,
'found in', section+
'. Please check ini-file.' 541 for var
in [
'configTemplate',
'globaltag']:
542 if config.has_option(section,var):
543 datasetOptions[var] = config.get(section,var)
546 datasetOptions[var] = generalOptions[var]
548 print "No",var,
"found in ["+section+
"]",
549 print "and no default in [general] section." 553 datasetOptions[
'cosmicsZeroTesla'] =
False 554 if config.has_option(section,
'cosmicsZeroTesla'):
555 datasetOptions[
'cosmicsZeroTesla'] = config.getboolean(section,
'cosmicsZeroTesla')
557 datasetOptions[
'cosmicsDecoMode'] =
False 558 if config.has_option(section,
'cosmicsDecoMode'):
559 datasetOptions[
'cosmicsDecoMode'] = config.getboolean(section,
'cosmicsDecoMode')
561 datasetOptions[
'primaryWidth'] = -1.0
562 if config.has_option(section,
'primaryWidth'):
563 datasetOptions[
'primaryWidth'] = config.getfloat(section,
'primaryWidth')
565 datasetOptions[
'json'] =
'' 566 if config.has_option(section,
'json'):
567 datasetOptions[
'json'] = config.get(section,
'json')
570 datasetOptions[
'json'] = generalOptions[
'json']
572 print "No json given in either [general] or ["+section+
"] sections.",
573 print "Proceeding without json-file." 577 datasetOptions[
'inputFileList'] = os.path.expandvars(datasetOptions[
'inputFileList'])
580 datasetOptions[
'configTemplate'] = os.path.expandvars(datasetOptions[
'configTemplate'])
584 datasetOptions[
'njobs'] = 0
586 with open(datasetOptions[
'inputFileList'],
'r') as filelist: 587 for line
in filelist:
588 if 'CastorPool' in line:
591 if not line.strip()==
'':
592 datasetOptions[
'njobs'] += 1
594 print 'Inputfilelist', datasetOptions[
'inputFileList'],
'does not exist.' 596 if datasetOptions[
'njobs'] == 0:
597 print 'Number of jobs is 0. There may be a problem with the inputfilelist:' 598 print datasetOptions[
'inputFileList']
602 if config.has_option(section,
'njobs'):
603 if config.getint(section,
'njobs')<=datasetOptions[
'njobs']:
604 datasetOptions[
'njobs'] = config.getint(section,
'njobs')
606 print 'njobs is bigger than the default',datasetOptions[
'njobs'],
'. Using default.' 608 print 'No number of jobs specified. Using number of files in inputfilelist as the number of jobs.' 613 with open(datasetOptions[
'configTemplate'],
'r') as INFILE: 614 tmpFile = INFILE.read() 616 print 'The config-template called',datasetOptions[
'configTemplate'],
'cannot be found.' 619 tmpFile = re.sub(
'setupGlobaltag\s*\=\s*[\"\'](.*?)[\"\']',
620 'setupGlobaltag = \"'+datasetOptions[
'globaltag']+
'\"',
622 tmpFile = re.sub(re.compile(
"setupRunStartGeometry\s*\=\s*.*$", re.M),
623 "setupRunStartGeometry = "+
624 generalOptions[
"FirstRunForStartGeometry"], tmpFile)
625 tmpFile = re.sub(
'setupCollection\s*\=\s*[\"\'](.*?)[\"\']',
626 'setupCollection = \"'+datasetOptions[
'collection']+
'\"',
628 if datasetOptions[
'cosmicsZeroTesla']:
629 tmpFile = re.sub(re.compile(
'setupCosmicsZeroTesla\s*\=\s*.*$', re.M),
630 'setupCosmicsZeroTesla = True',
632 if datasetOptions[
'cosmicsDecoMode']:
633 tmpFile = re.sub(re.compile(
'setupCosmicsDecoMode\s*\=\s*.*$', re.M),
634 'setupCosmicsDecoMode = True',
636 if datasetOptions[
'primaryWidth'] > 0.0:
637 tmpFile = re.sub(re.compile(
'setupPrimaryWidth\s*\=\s*.*$', re.M),
638 'setupPrimaryWidth = '+
str(datasetOptions[
'primaryWidth']),
640 if datasetOptions[
'json'] !=
'':
641 tmpFile = re.sub(re.compile(
'setupJson\s*\=\s*.*$', re.M),
642 'setupJson = \"'+datasetOptions[
'json']+
'\"',
645 thisCfgTemplate =
'tmp.py' 646 with open(thisCfgTemplate,
'w')
as OUTFILE:
647 OUTFILE.write(tmpFile)
655 configTemplate = tmpFile
656 cms_process = mps_tools.get_process_object(thisCfgTemplate)
658 generalOptions[
"FirstRunForStartGeometry"])
660 with open(thisCfgTemplate,
"a")
as f: f.write(overrideGT)
664 command = [
"mps_setup.pl",
667 "-M", generalOptions[
"pedeMem"],
668 "-N", datasetOptions[
"name"],
671 datasetOptions[
"inputFileList"],
672 str(datasetOptions[
"njobs"]),
673 generalOptions[
"classInf"],
674 generalOptions[
"jobname"],
676 "cmscafuser:"+mssDir]
677 command =
filter(
lambda x: len(x.strip()) > 0, command)
680 print 'Submitting dataset:', datasetOptions[
'name']
681 print 'Baseconfig: ', datasetOptions[
'configTemplate']
682 print 'Collection: ', datasetOptions[
'collection']
683 if datasetOptions[
"collection"]
in (
"ALCARECOTkAlCosmicsCTF0T",
684 "ALCARECOTkAlCosmicsInCollisions"):
685 print 'cosmicsDecoMode: ', datasetOptions[
'cosmicsDecoMode']
686 print 'cosmicsZeroTesla: ', datasetOptions[
'cosmicsZeroTesla']
687 print 'Globaltag: ', datasetOptions[
'globaltag']
688 print 'Number of jobs: ', datasetOptions[
'njobs']
689 print 'Inputfilelist: ', datasetOptions[
'inputFileList']
690 if datasetOptions[
'json'] !=
'':
691 print 'Jsonfile: ', datasetOptions[
'json']
692 print 'Pass to mps_setup: ',
" ".
join(command)
701 print "No dataset section defined in '{0}'".
format(aligmentConfig)
702 print "At least one section '[dataset:<name>]' is required." 705 firstPedeConfig =
True 706 for setting
in pedesettings:
710 print "Creating pede job." 712 print "Creating pede jobs using settings from '{0}'.".
format(setting)
713 for weight_conf
in weight_confs:
718 for name,weight
in weight_conf:
721 if not firstPedeConfig:
726 lib = mpslib.jobdatabase()
730 jobm_path = os.path.join(
"jobData", lib.JOBDIR[-1])
733 command = [
"rm",
"-f", os.path.join(jobm_path,
"alignment_merge.py")]
736 thisCfgTemplate =
"tmp.py" 737 with open(thisCfgTemplate,
"w")
as f:
738 f.write(configTemplate+overrideGT)
743 "-w", thisCfgTemplate,
744 os.path.join(jobm_path,
"alignment_merge.py"),
748 if setting
is not None: command.extend([
"-a", setting])
749 print " ".
join(command)
752 generalOptions[
"FirstRunForStartGeometry"])
754 os.symlink(tracker_tree_path,
755 os.path.abspath(os.path.join(jobm_path,
756 ".TrackerTree.root")))
757 firstPedeConfig =
False 760 with open(os.path.join(jobm_path,
".weights.pkl"),
"wb")
as f:
761 cPickle.dump(weight_conf, f, 2)
766 if overrideGT.strip() !=
"":
768 msg = (
"Overriding global tag with single-IOV tags extracted from '{}' for " 769 "run number '{}'.".
format(generalOptions[
"globaltag"],
770 generalOptions[
"FirstRunForStartGeometry"]))
def check_iov_definition(cms_process, first_run)
static void pop(std::vector< T > &vec, unsigned int index)
def create_input_db(cms_process, run_number)
def create_tracker_tree(global_tag, first_run)
static std::string join(char **cmd)
def handle_process_call(command, verbose=False)
def get_weight_configs(config)
def create_mass_storage_directory(mps_dir_name, general_options)