1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
#!/usr/bin/env python3
# Original author: Joerg Behr
# Translation from Perl to Python: Gregor Mittag
#
# This script reads the histogram file produced by Pede and it extracts the plot
# showing the average chi2/ndf per Mille binary number. After reading the MPS
# database, for which the file name has to be provided, an output file called
# chi2pedehis.txt is produced where the first column corresponds to the
# associated name, the second column corresponds to the Mille binary number, and
# the last column is equal to <chi2/ndf>. As further argument this scripts
# expects the file name of the Pede histogram file -- usually millepede.his. The
# last required argument represents the location of the Python config which was
# used by CMSSW.
#
# Use createChi2ndfplot.C to plot the output of this script.
import os
import sys
import re
import argparse
import Alignment.MillePedeAlignmentAlgorithm.mpslib.tools as mps_tools
import Alignment.MillePedeAlignmentAlgorithm.mpslib.Mpslibclass as mpslib
################################################################################
def main(argv = None):
"""Main routine of the script.
Arguments:
- `argv`: arguments passed to the main routine
"""
if argv == None:
argv = sys.argv[1:]
parser = argparse.ArgumentParser(description="Analysis pede histogram file")
parser.add_argument("-d", "--mps-db", dest="mps_db", required=True,
metavar="PATH", help="MPS database file ('mps.db')")
parser.add_argument("--his", dest="his_file", required=True,
metavar="PATH", help="pede histogram file")
parser.add_argument("-c", "--cfg", dest="cfg", metavar="PATH", required=True,
help="python configuration file of pede job")
parser.add_argument("-b", "--no-binary-check", dest="no_binary_check",
default=False, action="store_true",
help=("skip check for existing binaries "
"(possibly needed if used interactively)"))
args = parser.parse_args(argv)
for input_file in (args.mps_db, args.his_file, args.cfg):
if not os.path.exists(input_file):
print("Could not find input file:", input_file)
sys.exit(1)
ids, names = get_all_ids_names(args.mps_db)
used_binaries = get_used_binaries(args.cfg, args.no_binary_check)
his_data = get_his_data(args.his_file)
if len(his_data) != len(used_binaries):
print("The number of used binaries is", len(used_binaries), end=' ')
print("whereas in contrast, however, the <chi2/ndf> histogram in Pede has", end=' ')
print(len(his_data), "bins (Pede version >= rev92 might help if #bins < #binaries).", end=' ')
print("Exiting.")
sys.exit(1)
with open("chi2pedehis.txt", "w") as f:
for i, b in enumerate(used_binaries):
index = ids.index(b)
name = names[index]
f.write(" ".join([name, "{:03d}".format(b), his_data[i]])+"\n")
################################################################################
def get_all_ids_names(mps_db):
"""Returns two lists containing the mille job IDs and the associated names.
Arguments:
- `mps_db`: path to the MPS database file
"""
lib = mpslib.jobdatabase()
lib.read_db(mps_db)
ids = lib.JOBNUMBER[:lib.nJobs]
names = lib.JOBSP3[:lib.nJobs]
return ids, names
def get_used_binaries(cfg, no_binary_check):
"""Returns list of used binary IDs.
Arguments:
- `cfg`: python config used to run the pede job
- `no_binary_check`: if 'True' a check for file existence is skipped
"""
cms_process = mps_tools.get_process_object(cfg)
binaries = cms_process.AlignmentProducer.algoConfig.mergeBinaryFiles
if no_binary_check:
used_binaries = binaries
else:
# following check works only if 'args.cfg' was run from the same directory:
used_binaries = [b for b in binaries
if os.path.exists(os.path.join(os.path.dirname(cfg), b))]
used_binaries = [int(re.sub(r"milleBinary(\d+)\.dat", r"\1", b))
for b in used_binaries]
return used_binaries
def get_his_data(his_file):
"""Parse the pede histogram file.
Arguments:
- `his_file`: pede histogram file
"""
his_data = []
with open(his_file, "r") as his:
found_chi2_start = False;
for line in his:
if r"final <Chi^2/Ndf> from accepted local fits vs file number" in line:
found_chi2_start = True
if not found_chi2_start:
continue
else:
if r"end of xy-data" in line: break
if not re.search("\d", line): continue
if re.search(r"[a-z]", line): continue
splitted = line.split()
his_data.append(splitted[-1])
return his_data
################################################################################
if __name__ == "__main__":
main()
|