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 "/store/caf/user/"+os.environ[
"USER"])
262 mss_dir = os.path.join(mss_dir,
"MPproduction", mps_dir_name)
264 cmd = [
"/afs/cern.ch/project/eos/installation/cms/bin/eos.select",
265 "mkdir",
"-p", mss_dir]
268 if not general_options.get(
"testMode",
False):
270 with open(os.devnull,
"w")
as dump:
271 subprocess.check_call(cmd, stdout = dump, stderr = dump)
272 except subprocess.CalledProcessError:
273 print "Failed to create mass storage directory:", mss_dir
280 """Method to create hidden 'TrackerTree.root'. 283 - `global_tag`: global tag from which the tracker geometry is taken 284 - `first_run`: run to specify IOV within `global_tag` 287 config = mpsv_iniparser.ConfigData()
288 config.jobDataPath =
"." 289 config.globalTag = global_tag
290 config.firstRun = first_run
291 return mpsv_trackerTree.check(config)
296 helpEpilog =
'''Builds the config-templates from a universal config-template for each 297 dataset specified in .ini-file that is passed to this script. 298 Then calls mps_setup.pl for all datasets.''' 300 description=
'Setup the alignment as configured in the alignment_config file.',
303 parser.add_argument(
'-v',
'--verbose', action=
'store_true',
304 help=
'display detailed output of mps_setup')
306 parser.add_argument(
'-w',
'--weight', action=
'store_true',
307 help=
'create an additional mergejob with (possibly new) weights from .ini-config')
309 parser.add_argument(
'alignmentConfig', action=
'store',
310 help=
'name of the .ini config file that specifies the datasets to be used')
312 args = parser.parse_args()
313 aligmentConfig = args.alignmentConfig
316 config = ConfigParser.ConfigParser()
317 config.optionxform = str
318 config.read(aligmentConfig)
326 mpsTemplates = os.path.join(
"src",
"Alignment",
"MillePedeAlignmentAlgorithm",
"templates")
328 mpsTemplates = os.path.join(os.environ[
"CMSSW_BASE"], mpsTemplates)
330 mpsTemplates = os.path.join(os.environ[
"CMSSW_RELEASE_BASE"], mpsTemplates)
331 milleScript = os.path.join(mpsTemplates,
"mps_runMille_template.sh")
332 pedeScript = os.path.join(mpsTemplates,
"mps_runPede_rfcp_template.sh")
335 currentDir = os.getcwd()
337 match = re.search(re.compile(
'mpproduction\/mp(.+?)$', re.M|re.I),currentDir)
339 mpsdirname =
'mp'+match.group(1)
341 print "Current location does not seem to be a MillePede campaign directory:",
352 for var
in [
"classInf",
"pedeMem",
"jobname",
"FirstRunForStartGeometry"]:
354 generalOptions[var] = config.get(
'general',var)
355 except ConfigParser.NoOptionError:
356 print "No", var,
"found in [general] section. Please check ini-file." 360 generalOptions[
'datasetdir'] =
'' 361 if config.has_option(
'general',
'datasetdir'):
362 generalOptions[
'datasetdir'] = config.get(
'general',
'datasetdir')
364 os.environ[
"datasetdir"] = generalOptions[
'datasetdir']
366 print "No datasetdir given in [general] section.",
367 print "Be sure to give a full path in inputFileList." 370 for var
in (
"globaltag",
"configTemplate",
"json",
"massStorageDir",
"testMode"):
372 generalOptions[var] = config.get(
'general',var)
373 except ConfigParser.NoOptionError:
374 if var ==
"testMode":
continue 375 print "No '" + var +
"' given in [general] section." 381 pedesettings = ([x.strip()
for x
in config.get(
"general",
"pedesettings").
split(
",")]
382 if config.has_option(
"general",
"pedesettings")
else [
None])
392 if not os.path.isdir(
"jobData"):
393 print "No jobData-folder found. Properly set up the alignment before using the -w option." 395 if not os.path.exists(
"mps.db"):
396 print "No mps.db found. Properly set up the alignment before using the -w option." 401 configTemplate = config.get(
'general',
'configTemplate')
402 except ConfigParser.NoOptionError:
403 print 'No default configTemplate given in [general] section.' 404 print 'When using -w, a default configTemplate is needed to build a merge-config.' 409 globalTag = config.get(
'general',
'globaltag')
410 except ConfigParser.NoOptionError:
411 print "No default 'globaltag' given in [general] section." 412 print "When using -w, a default configTemplate is needed to build a merge-config." 416 first_run = config.get(
"general",
"FirstRunForStartGeometry")
417 except ConfigParser.NoOptionError:
418 print "Missing mandatory option 'FirstRunForStartGeometry' in [general] section." 421 for section
in config.sections():
422 if section.startswith(
"dataset:"):
424 collection = config.get(section,
"collection")
426 except ConfigParser.NoOptionError:
427 print "Missing mandatory option 'collection' in section ["+section+
"]." 431 with open(configTemplate,
"r") as f: 434 print "The config-template '"+configTemplate+
"' cannot be found." 437 tmpFile = re.sub(
'setupGlobaltag\s*\=\s*[\"\'](.*?)[\"\']',
438 'setupGlobaltag = \"'+globalTag+
'\"',
440 tmpFile = re.sub(
'setupCollection\s*\=\s*[\"\'](.*?)[\"\']',
441 'setupCollection = \"'+collection+
'\"',
443 tmpFile = re.sub(re.compile(
"setupRunStartGeometry\s*\=\s*.*$", re.M),
444 "setupRunStartGeometry = "+first_run,
447 thisCfgTemplate =
"tmp.py" 448 with open(thisCfgTemplate,
"w")
as f: f.write(tmpFile)
450 cms_process = mps_tools.get_process_object(thisCfgTemplate)
453 with open(thisCfgTemplate,
"a")
as f: f.write(overrideGT)
455 for setting
in pedesettings:
459 print "Creating pede job." 461 print "Creating pede jobs using settings from '{0}'.".
format(setting)
462 for weight_conf
in weight_confs:
467 for name,weight
in weight_conf:
474 lib = mpslib.jobdatabase()
478 jobm_path = os.path.join(
"jobData", lib.JOBDIR[-1])
483 os.path.join(jobm_path,
"alignment_merge.py")]
489 "-w", thisCfgTemplate,
490 os.path.join(jobm_path,
"alignment_merge.py"),
494 if setting
is not None: command.extend([
"-a", setting])
495 print " ".
join(command)
500 with open(os.path.join(jobm_path,
".weights.pkl"),
"wb")
as f:
501 cPickle.dump(weight_conf, f, 2)
507 if overrideGT.strip() !=
"":
509 msg = (
"Overriding global tag with single-IOV tags extracted from '{}' " 510 "for run number '{}'.".
format(generalOptions[
"globaltag"],
523 for section
in config.sections():
524 if 'general' in section:
526 elif section.startswith(
"dataset:"):
531 datasetOptions[
'name'] = section[8:]
534 for var
in [
'inputFileList',
'collection']:
536 datasetOptions[var] = config.get(section,var)
537 except ConfigParser.NoOptionError:
538 print 'No', var,
'found in', section+
'. Please check ini-file.' 542 for var
in [
'configTemplate',
'globaltag']:
543 if config.has_option(section,var):
544 datasetOptions[var] = config.get(section,var)
547 datasetOptions[var] = generalOptions[var]
549 print "No",var,
"found in ["+section+
"]",
550 print "and no default in [general] section." 554 datasetOptions[
'cosmicsZeroTesla'] =
False 555 if config.has_option(section,
'cosmicsZeroTesla'):
556 datasetOptions[
'cosmicsZeroTesla'] = config.getboolean(section,
'cosmicsZeroTesla')
558 datasetOptions[
'cosmicsDecoMode'] =
False 559 if config.has_option(section,
'cosmicsDecoMode'):
560 datasetOptions[
'cosmicsDecoMode'] = config.getboolean(section,
'cosmicsDecoMode')
562 datasetOptions[
'primaryWidth'] = -1.0
563 if config.has_option(section,
'primaryWidth'):
564 datasetOptions[
'primaryWidth'] = config.getfloat(section,
'primaryWidth')
566 datasetOptions[
'json'] =
'' 567 if config.has_option(section,
'json'):
568 datasetOptions[
'json'] = config.get(section,
'json')
571 datasetOptions[
'json'] = generalOptions[
'json']
573 print "No json given in either [general] or ["+section+
"] sections.",
574 print "Proceeding without json-file." 578 datasetOptions[
'inputFileList'] = os.path.expandvars(datasetOptions[
'inputFileList'])
581 datasetOptions[
'configTemplate'] = os.path.expandvars(datasetOptions[
'configTemplate'])
585 datasetOptions[
'njobs'] = 0
587 with open(datasetOptions[
'inputFileList'],
'r') as filelist: 588 for line
in filelist:
589 if 'CastorPool' in line:
592 if not line.strip()==
'':
593 datasetOptions[
'njobs'] += 1
595 print 'Inputfilelist', datasetOptions[
'inputFileList'],
'does not exist.' 597 if datasetOptions[
'njobs'] == 0:
598 print 'Number of jobs is 0. There may be a problem with the inputfilelist:' 599 print datasetOptions[
'inputFileList']
603 if config.has_option(section,
'njobs'):
604 if config.getint(section,
'njobs')<=datasetOptions[
'njobs']:
605 datasetOptions[
'njobs'] = config.getint(section,
'njobs')
607 print 'njobs is bigger than the default',datasetOptions[
'njobs'],
'. Using default.' 609 print 'No number of jobs specified. Using number of files in inputfilelist as the number of jobs.' 614 with open(datasetOptions[
'configTemplate'],
'r') as INFILE: 615 tmpFile = INFILE.read() 617 print 'The config-template called',datasetOptions[
'configTemplate'],
'cannot be found.' 620 tmpFile = re.sub(
'setupGlobaltag\s*\=\s*[\"\'](.*?)[\"\']',
621 'setupGlobaltag = \"'+datasetOptions[
'globaltag']+
'\"',
623 tmpFile = re.sub(re.compile(
"setupRunStartGeometry\s*\=\s*.*$", re.M),
624 "setupRunStartGeometry = "+
625 generalOptions[
"FirstRunForStartGeometry"], tmpFile)
626 tmpFile = re.sub(
'setupCollection\s*\=\s*[\"\'](.*?)[\"\']',
627 'setupCollection = \"'+datasetOptions[
'collection']+
'\"',
629 if datasetOptions[
'cosmicsZeroTesla']:
630 tmpFile = re.sub(re.compile(
'setupCosmicsZeroTesla\s*\=\s*.*$', re.M),
631 'setupCosmicsZeroTesla = True',
633 if datasetOptions[
'cosmicsDecoMode']:
634 tmpFile = re.sub(re.compile(
'setupCosmicsDecoMode\s*\=\s*.*$', re.M),
635 'setupCosmicsDecoMode = True',
637 if datasetOptions[
'primaryWidth'] > 0.0:
638 tmpFile = re.sub(re.compile(
'setupPrimaryWidth\s*\=\s*.*$', re.M),
639 'setupPrimaryWidth = '+
str(datasetOptions[
'primaryWidth']),
641 if datasetOptions[
'json'] !=
'':
642 tmpFile = re.sub(re.compile(
'setupJson\s*\=\s*.*$', re.M),
643 'setupJson = \"'+datasetOptions[
'json']+
'\"',
646 thisCfgTemplate =
'tmp.py' 647 with open(thisCfgTemplate,
'w')
as OUTFILE:
648 OUTFILE.write(tmpFile)
656 configTemplate = tmpFile
657 cms_process = mps_tools.get_process_object(thisCfgTemplate)
659 generalOptions[
"FirstRunForStartGeometry"])
661 with open(thisCfgTemplate,
"a")
as f: f.write(overrideGT)
665 command = [
"mps_setup.pl",
668 "-M", generalOptions[
"pedeMem"],
669 "-N", datasetOptions[
"name"],
672 datasetOptions[
"inputFileList"],
673 str(datasetOptions[
"njobs"]),
674 generalOptions[
"classInf"],
675 generalOptions[
"jobname"],
677 "cmscafuser:"+mssDir]
678 command =
filter(
lambda x: len(x.strip()) > 0, command)
681 print 'Submitting dataset:', datasetOptions[
'name']
682 print 'Baseconfig: ', datasetOptions[
'configTemplate']
683 print 'Collection: ', datasetOptions[
'collection']
684 if datasetOptions[
"collection"]
in (
"ALCARECOTkAlCosmicsCTF0T",
685 "ALCARECOTkAlCosmicsInCollisions"):
686 print 'cosmicsDecoMode: ', datasetOptions[
'cosmicsDecoMode']
687 print 'cosmicsZeroTesla: ', datasetOptions[
'cosmicsZeroTesla']
688 print 'Globaltag: ', datasetOptions[
'globaltag']
689 print 'Number of jobs: ', datasetOptions[
'njobs']
690 print 'Inputfilelist: ', datasetOptions[
'inputFileList']
691 if datasetOptions[
'json'] !=
'':
692 print 'Jsonfile: ', datasetOptions[
'json']
693 print 'Pass to mps_setup: ',
" ".
join(command)
702 print "No dataset section defined in '{0}'".
format(aligmentConfig)
703 print "At least one section '[dataset:<name>]' is required." 706 firstPedeConfig =
True 707 for setting
in pedesettings:
711 print "Creating pede job." 713 print "Creating pede jobs using settings from '{0}'.".
format(setting)
714 for weight_conf
in weight_confs:
719 for name,weight
in weight_conf:
722 if not firstPedeConfig:
727 lib = mpslib.jobdatabase()
731 jobm_path = os.path.join(
"jobData", lib.JOBDIR[-1])
734 command = [
"rm",
"-f", os.path.join(jobm_path,
"alignment_merge.py")]
737 thisCfgTemplate =
"tmp.py" 738 with open(thisCfgTemplate,
"w")
as f:
739 f.write(configTemplate+overrideGT)
744 "-w", thisCfgTemplate,
745 os.path.join(jobm_path,
"alignment_merge.py"),
749 if setting
is not None: command.extend([
"-a", setting])
750 print " ".
join(command)
753 generalOptions[
"FirstRunForStartGeometry"])
755 os.symlink(tracker_tree_path,
756 os.path.abspath(os.path.join(jobm_path,
757 ".TrackerTree.root")))
758 firstPedeConfig =
False 761 with open(os.path.join(jobm_path,
".weights.pkl"),
"wb")
as f:
762 cPickle.dump(weight_conf, f, 2)
767 if overrideGT.strip() !=
"":
769 msg = (
"Overriding global tag with single-IOV tags extracted from '{}' for " 770 "run number '{}'.".
format(generalOptions[
"globaltag"],
771 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)