CMS 3D CMS Logo

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