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():
173 path = tuple(new_dir_list)
178 if node.InheritsFrom(
'TObjString'):
180 return node.GetName().
split(
'>')[0][1:]
182 return node.GetName()
186 print(
'No differences were observed - output will not be written', file=sys.stderr)
190 result_dir = os.path.dirname(result_file_path)
191 if not os.path.exists(result_dir):
192 os.makedirs(result_dir)
194 result_file = ROOT.TFile(result_file_path,
'recreate')
195 ROOT.gROOT.GetListOfFiles().Remove(result_file)
197 if not result_file.IsOpen():
198 print(
'Unable to open %s output file' % result_file_path, file=sys.stderr)
205 print(
'Output written to %s file' % result_file_path, file=sys.stderr)
209 histogram = flat_dict[path]
211 current = output_file
214 for directory
in path[:-1]:
222 dir = parent_dir.Get(name)
224 dir = parent_dir.mkdir(name)
233 input_file_name = os.path.basename(input_file_path)
235 run = input_file_name.split(
'_')[2]
236 workflow = os.path.basename(os.path.dirname(input_file_path)).
split(
'_')[0].
replace(
'.',
'_')
241 if run ==
'R000000001':
242 relval_prefix =
'RelVal_' 248 return 'DQM_V0001_%s__%swf%s_%s__%s-PR%s-%s__DQMIO.root' % (run, relval_prefix, workflow, baseOrPr, cmssw_version, pr_number, test_number)
251 return os.path.basename(file_path).
split(
'_')[2].lstrip(
'R').lstrip('0')
253 if __name__ ==
'__main__':
254 parser = argparse.ArgumentParser(description=
"This tool compares DQM monitor elements found in base-file with the ones found in pr-file." 255 "Comparison is done bin by bin and output is written to a root file containing only the changes.")
256 parser.add_argument(
'-b',
'--base-file', help=
'Baseline IB DQM root file', required=
True)
257 parser.add_argument(
'-p',
'--pr-file', help=
'PR DQM root file', required=
True)
258 parser.add_argument(
'-n',
'--pr-number', help=
'PR number under test', default=
'00001')
259 parser.add_argument(
'-t',
'--test-number', help=
'Unique test number to distinguish different comparisons of the same PR.', default=
'1')
260 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'])
261 parser.add_argument(
'-o',
'--output-dir', help=
'Comparison root files output directory', default=
'dqmHistoComparisonOutput')
262 args = parser.parse_args()
264 cmssw_version =
'_'.
join(args.release_format.split(
'_')[:4])
266 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 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