3 from __future__
import print_function
5 ROOT.PyConfig.IgnoreCommandLineOptions =
True
10 from DQMServices.FileIO.blacklist
import get_blacklist
12 def create_dif(base_file_path, pr_file_path, pr_number, test_number, cmssw_version, output_dir_path):
13 base_file = ROOT.TFile(base_file_path,
'read')
14 ROOT.gROOT.GetListOfFiles().Remove(base_file)
16 pr_file = ROOT.TFile(pr_file_path,
'read')
17 ROOT.gROOT.GetListOfFiles().Remove(pr_file)
19 if base_file.IsOpen():
20 print(
'Baseline file successfully opened', file=sys.stderr)
22 print(
'Unable to open base file', file=sys.stderr)
26 print(
'PR file successfully opened', file=sys.stderr)
28 print(
'Unable to open PR file', file=sys.stderr)
38 shared_paths = list(set(pr_flat_dict).
intersection(set(base_flat_dict)))
41 only_pr_paths = list(set(pr_flat_dict).difference(set(base_flat_dict)))
44 only_base_paths = list(set(base_flat_dict).difference(set(pr_flat_dict)))
47 paths_to_save_in_base = []
50 paths_to_save_in_pr = []
53 compare(shared_paths, pr_flat_dict, base_flat_dict, paths_to_save_in_pr, paths_to_save_in_base)
56 for path
in only_base_paths:
57 item = base_flat_dict[path]
62 paths_to_save_in_base.append(path)
65 for path
in only_pr_paths:
66 item = pr_flat_dict[path]
71 paths_to_save_in_pr.append(path)
73 base_output_filename =
get_output_filename(pr_file_path, pr_number, test_number, cmssw_version,
False)
74 pr_output_filename =
get_output_filename(pr_file_path, pr_number, test_number, cmssw_version,
True)
77 save_paths(base_flat_dict, paths_to_save_in_base, os.path.join(output_dir_path,
'base', base_output_filename))
80 save_paths(pr_flat_dict, paths_to_save_in_pr, os.path.join(output_dir_path,
'pr', pr_output_filename))
86 nr_of_changed_elements = len(set(paths_to_save_in_base).
intersection(set(paths_to_save_in_pr)))
87 nr_of_removed_elements = len(paths_to_save_in_base) - nr_of_changed_elements
88 nr_of_added_elements = len(paths_to_save_in_pr) - nr_of_changed_elements
90 print(
'Base output file. PR output file. Changed elements, removed elements, added elements:')
91 print(base_output_filename)
92 print(pr_output_filename)
93 print(
'%s %s %s' % (nr_of_changed_elements, nr_of_removed_elements, nr_of_added_elements))
95 def compare(shared_paths, pr_flat_dict, base_flat_dict, paths_to_save_in_pr, paths_to_save_in_base):
97 for path
in shared_paths:
98 pr_item = pr_flat_dict[path]
99 base_item = base_flat_dict[path]
101 if pr_item ==
None or base_item ==
None:
106 if pr_item.InheritsFrom(
'TProfile2D')
and base_item.InheritsFrom(
'TProfile2D'):
110 elif pr_item.InheritsFrom(
'TProfile')
and base_item.InheritsFrom(
'TProfile'):
114 elif pr_item.InheritsFrom(
'TH1')
and base_item.InheritsFrom(
'TH1'):
116 pr_array = np.array(pr_item)
117 base_array = np.array(base_item)
119 if pr_array.shape != base_array.shape
or not np.allclose(pr_array, base_array, equal_nan=
True):
123 if pr_item != base_item:
127 paths_to_save_in_pr.append(path)
128 paths_to_save_in_base.append(path)
132 if pr_item.GetSize() != base_item.GetSize():
135 for i
in range(pr_item.GetSize()):
136 pr_bin_content = pr_item.GetBinContent(i)
137 base_bin_content = base_item.GetBinContent(i)
139 pr_bin_entries = pr_item.GetBinEntries(i)
140 base_bin_entries = base_item.GetBinEntries(i)
142 pr_bin_error = pr_item.GetBinError(i)
143 base_bin_error = base_item.GetBinError(i)
145 if not np.isclose(pr_bin_content, base_bin_content, equal_nan=
True):
148 if not np.isclose(pr_bin_entries, base_bin_entries, equal_nan=
True):
151 if not np.isclose(pr_bin_error, base_bin_error, equal_nan=
True):
158 for key
in file.GetListOfKeys():
168 if hasattr(node,
'GetListOfKeys'):
169 for key
in node.GetListOfKeys():
173 path = tuple(new_dir_list)
177 if node.InheritsFrom(
'TObjString'):
179 name = node.GetName().
split(
'>')[0][1:]
182 return node.GetName()
185 return '_string_monitor_element'
189 dirs_list = dirs_list[:]
198 print(
'No differences were observed - output will not be written', file=sys.stderr)
202 result_dir = os.path.dirname(result_file_path)
203 if not os.path.exists(result_dir):
204 os.makedirs(result_dir)
206 result_file = ROOT.TFile(result_file_path,
'recreate')
207 ROOT.gROOT.GetListOfFiles().Remove(result_file)
209 if not result_file.IsOpen():
210 print(
'Unable to open %s output file' % result_file_path, file=sys.stderr)
217 print(
'Output written to %s file' % result_file_path, file=sys.stderr)
221 histogram = flat_dict[path]
223 current = output_file
226 for directory
in path[:-1]:
234 dir = parent_dir.Get(name)
236 dir = parent_dir.mkdir(name)
245 input_file_name = os.path.basename(input_file_path)
247 run = input_file_name.split(
'_')[2]
248 workflow = os.path.basename(os.path.dirname(input_file_path)).
split(
'_')[0].
replace(
'.',
'_')
253 if run ==
'R000000001':
254 relval_prefix =
'RelVal_'
260 return 'DQM_V0001_%s__%swf%s_%s__%s-PR%s-%s__DQMIO.root' % (run, relval_prefix, workflow, baseOrPr, cmssw_version, pr_number, test_number)
263 return os.path.basename(file_path).
split(
'_')[2].lstrip(
'R').lstrip(
'0')
265 if __name__ ==
'__main__':
266 parser = argparse.ArgumentParser(description=
"This tool compares DQM monitor elements found in base-file with the ones found in pr-file."
267 "Comparison is done bin by bin and output is written to a root file containing only the changes.")
268 parser.add_argument(
'-b',
'--base-file', help=
'Baseline IB DQM root file', required=
True)
269 parser.add_argument(
'-p',
'--pr-file', help=
'PR DQM root file', required=
True)
270 parser.add_argument(
'-n',
'--pr-number', help=
'PR number under test', default=
'00001')
271 parser.add_argument(
'-t',
'--test-number', help=
'Unique test number to distinguish different comparisons of the same PR.', default=
'1')
272 parser.add_argument(
'-r',
'--release-format', help=
'Release format in this format: CMSSW_10_5_X_2019-02-17-0000', default=os.environ[
'CMSSW_VERSION'])
273 parser.add_argument(
'-o',
'--output-dir', help=
'Comparison root files output directory', default=
'dqmHistoComparisonOutput')
274 args = parser.parse_args()
276 cmssw_version =
'_'.
join(args.release_format.split(
'_')[:4])
278 create_dif(args.base_file, args.pr_file, args.pr_number, args.test_number, cmssw_version, args.output_dir)