3 from __future__
import print_function
5 ROOT.PyConfig.IgnoreCommandLineOptions =
True 11 from blacklist
import get_blacklist
13 def create_dif(base_file_path, pr_file_path, pr_number, test_number, cmssw_version, output_dir_path):
14 base_file = ROOT.TFile(base_file_path,
'read')
15 ROOT.gROOT.GetListOfFiles().Remove(base_file)
17 pr_file = ROOT.TFile(pr_file_path,
'read')
18 ROOT.gROOT.GetListOfFiles().Remove(pr_file)
20 if base_file.IsOpen():
21 print(
'Baseline file successfully opened', file=sys.stderr)
23 print(
'Unable to open base file', file=sys.stderr)
27 print(
'PR file successfully opened', file=sys.stderr)
29 print(
'Unable to open PR file', file=sys.stderr)
42 only_pr_paths =
list(set(pr_flat_dict).difference(set(base_flat_dict)))
45 only_base_paths =
list(set(base_flat_dict).difference(set(pr_flat_dict)))
48 paths_to_save_in_base = []
51 paths_to_save_in_pr = []
54 compare(shared_paths, pr_flat_dict, base_flat_dict, paths_to_save_in_pr, paths_to_save_in_base)
57 for path
in only_base_paths:
58 item = base_flat_dict[path]
63 paths_to_save_in_base.append(path)
66 for path
in only_pr_paths:
67 item = pr_flat_dict[path]
72 paths_to_save_in_pr.append(path)
74 base_output_filename =
get_output_filename(pr_file_path, pr_number, test_number, cmssw_version,
False)
75 pr_output_filename =
get_output_filename(pr_file_path, pr_number, test_number, cmssw_version,
True)
78 save_paths(base_flat_dict, paths_to_save_in_base, os.path.join(output_dir_path,
'base', base_output_filename))
81 save_paths(pr_flat_dict, paths_to_save_in_pr, os.path.join(output_dir_path,
'pr', pr_output_filename))
87 nr_of_changed_elements = len(set(paths_to_save_in_base).
intersection(set(paths_to_save_in_pr)))
88 nr_of_removed_elements = len(paths_to_save_in_base) - nr_of_changed_elements
89 nr_of_added_elements = len(paths_to_save_in_pr) - nr_of_changed_elements
91 print(
'Base output file. PR output file. Changed elements, removed elements, added elements:')
92 print(base_output_filename)
93 print(pr_output_filename)
94 print(
'%s %s %s' % (nr_of_changed_elements, nr_of_removed_elements, nr_of_added_elements))
96 def compare(shared_paths, pr_flat_dict, base_flat_dict, paths_to_save_in_pr, paths_to_save_in_base):
98 for path
in shared_paths:
99 pr_item = pr_flat_dict[path]
100 base_item = base_flat_dict[path]
102 if pr_item ==
None or base_item ==
None:
107 if pr_item.InheritsFrom(
'TProfile2D')
and base_item.InheritsFrom(
'TProfile2D'):
111 elif pr_item.InheritsFrom(
'TProfile')
and base_item.InheritsFrom(
'TProfile'):
115 elif pr_item.InheritsFrom(
'TH1')
and base_item.InheritsFrom(
'TH1'):
117 pr_array = root_numpy.hist2array(hist=pr_item, include_overflow=
True, copy=
False)
118 base_array = root_numpy.hist2array(hist=base_item, include_overflow=
True, copy=
False)
120 if pr_array.shape != base_array.shape
or not np.allclose(pr_array, base_array, equal_nan=
True):
124 if pr_item != base_item:
128 paths_to_save_in_pr.append(path)
129 paths_to_save_in_base.append(path)
133 if pr_item.GetSize() != base_item.GetSize():
136 for i
in range(pr_item.GetSize()):
137 pr_bin_content = pr_item.GetBinContent(i)
138 base_bin_content = base_item.GetBinContent(i)
140 pr_bin_entries = pr_item.GetBinEntries(i)
141 base_bin_entries = base_item.GetBinEntries(i)
143 pr_bin_error = pr_item.GetBinError(i)
144 base_bin_error = base_item.GetBinError(i)
146 if not np.isclose(pr_bin_content, base_bin_content, equal_nan=
True):
149 if not np.isclose(pr_bin_entries, base_bin_entries, equal_nan=
True):
152 if not np.isclose(pr_bin_error, base_bin_error, equal_nan=
True):
159 for key
in file.GetListOfKeys():
169 if hasattr(node,
'GetListOfKeys'):
170 for key
in node.GetListOfKeys():
174 path = tuple(new_dir_list)
178 if node.InheritsFrom(
'TObjString'):
180 name = node.GetName().
split(
'>')[0][1:]
183 return node.GetName()
186 return '_string_monitor_element' 190 dirs_list = dirs_list[:]
199 print(
'No differences were observed - output will not be written', file=sys.stderr)
203 result_dir = os.path.dirname(result_file_path)
204 if not os.path.exists(result_dir):
205 os.makedirs(result_dir)
207 result_file = ROOT.TFile(result_file_path,
'recreate')
208 ROOT.gROOT.GetListOfFiles().Remove(result_file)
210 if not result_file.IsOpen():
211 print(
'Unable to open %s output file' % result_file_path, file=sys.stderr)
218 print(
'Output written to %s file' % result_file_path, file=sys.stderr)
222 histogram = flat_dict[path]
224 current = output_file
227 for directory
in path[:-1]:
235 dir = parent_dir.Get(name)
237 dir = parent_dir.mkdir(name)
246 input_file_name = os.path.basename(input_file_path)
248 run = input_file_name.split(
'_')[2]
249 workflow = os.path.basename(os.path.dirname(input_file_path)).
split(
'_')[0].
replace(
'.',
'_')
254 if run ==
'R000000001':
255 relval_prefix =
'RelVal_' 261 return 'DQM_V0001_%s__%swf%s_%s__%s-PR%s-%s__DQMIO.root' % (run, relval_prefix, workflow, baseOrPr, cmssw_version, pr_number, test_number)
264 return os.path.basename(file_path).
split(
'_')[2].lstrip(
'R').lstrip('0')
266 if __name__ ==
'__main__':
267 parser = argparse.ArgumentParser(description=
"This tool compares DQM monitor elements found in base-file with the ones found in pr-file." 268 "Comparison is done bin by bin and output is written to a root file containing only the changes.")
269 parser.add_argument(
'-b',
'--base-file', help=
'Baseline IB DQM root file', required=
True)
270 parser.add_argument(
'-p',
'--pr-file', help=
'PR DQM root file', required=
True)
271 parser.add_argument(
'-n',
'--pr-number', help=
'PR number under test', default=
'00001')
272 parser.add_argument(
'-t',
'--test-number', help=
'Unique test number to distinguish different comparisons of the same PR.', default=
'1')
273 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'])
274 parser.add_argument(
'-o',
'--output-dir', help=
'Comparison root files output directory', default=
'dqmHistoComparisonOutput')
275 args = parser.parse_args()
277 cmssw_version =
'_'.
join(args.release_format.split(
'_')[:4])
279 create_dif(args.base_file, args.pr_file, args.pr_number, args.test_number, cmssw_version, args.output_dir)
def get_output_filename(input_file_path, pr_number, test_number, cmssw_version, isPr)
def save_to_file(flat_dict, path, output_file)
def get_blacklist(RUN_NR)
def replace(string, replacements)
def flatten_file(file, run_nr)
S & print(S &os, JobReport::InputFile const &f)
def traverse_till_end(node, dirs_list, result, run_nr)
double intersection(double r12)
def create_dif(base_file_path, pr_file_path, pr_number, test_number, cmssw_version, output_dir_path)
def is_blacklisted(dirs_list, run_nr)
def create_dir(parent_dir, name)
static std::string join(char **cmd)
def compare_TProfile(pr_item, base_item)
def save_paths(flat_dict, paths, result_file_path)
def compare(shared_paths, pr_flat_dict, base_flat_dict, paths_to_save_in_pr, paths_to_save_in_base)
def get_run_nr(file_path)
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger list("!*","!HLTx*"if it matches 2 triggers or more) will accept the event if all the matching triggers are FAIL.It will reject the event if any of the triggers are PASS or EXCEPTION(this matches the behavior of"!*"before the partial wildcard feature was incorporated).Triggers which are in the READY state are completely ignored.(READY should never be returned since the trigger paths have been run