8 from threading
import Thread
10 COMPARISON_RESULTS = []
16 for _
in range(num_procs):
17 thread = Thread(target=compare, args=(base_dir, pr_dir, output_dir, files, pr_number, test_number, release_format))
19 threads.append(thread)
21 [thread.join()
for thread
in threads]
23 COMPARISON_RESULTS.sort(key=
lambda k:
float(k[
'workflow']))
25 def compare(base_dir, pr_dir, output_dir, files, pr_number, test_number, release_format):
28 file_name = files.pop()
29 command = [
'compareHistograms.py',
'-b', os.path.join(base_dir, file_name), \
30 '-p', os.path.join(pr_dir, file_name),
'-o', output_dir,
'-n', pr_number,
'-t', test_number,
'-r', release_format]
31 print(
'Running comparison:')
34 output = subprocess.check_output(command)
36 output_elements = output.split(
'\n')[1:]
37 base_output_filename = output_elements[0]
38 pr_output_filename = output_elements[1]
39 run_nr = base_output_filename.split(
'_')[2].lstrip(
'R').lstrip('0')
40 output_numbers = output_elements[2].
split(
' ')
42 workflow = os.path.basename(os.path.dirname(os.path.join(base_dir, file_name))).
split(
'_')[0]
43 base_dataset =
'/' +
'/'.
join(base_output_filename.rstrip(
'.root').
split(
'__')[1:])
44 pr_dataset =
'/' +
'/'.
join(pr_output_filename.rstrip(
'.root').
split(
'__')[1:])
46 COMPARISON_RESULTS.append({
'workflow': workflow,
'base_dataset': base_dataset,
'pr_dataset': pr_dataset,
'run_nr': run_nr,\
47 'changed_elements':
int(output_numbers[0]),
'removed_elements':
int(output_numbers[1]),
'added_elements':
int(output_numbers[2])})
48 except Exception
as ex:
49 print(
'Exception comparing two root files: %s' % ex)
52 base_files = glob.glob(os.path.join(base_dir,
'*.*_*/DQM_*.root'))
53 pr_files = glob.glob(os.path.join(pr_dir,
'*.*_*/DQM_*.root'))
57 base_files =
map(
lambda x: os.path.relpath(x, base_dir), base_files)
58 pr_files =
map(
lambda x: os.path.relpath(x, pr_dir), pr_files)
61 return [value
for value
in base_files
if value
in pr_files]
64 base_files = glob.glob(os.path.join(output_dir,
'base/*.root'))
65 pr_files = glob.glob(os.path.join(output_dir,
'pr/*.root'))
67 files = base_files + pr_files
69 print(
'Files to be uploaded:')
72 for _
in range(
min(num_procs, len(files))):
73 thread = Thread(target=upload, args=(files,))
80 command = [
'visDQMUpload.py',
'https://cmsweb.cern.ch/dqm/dev', file]
81 print(
'Uploading output:')
84 subprocess.call(command)
86 except Exception
as ex:
89 print(
'Exception uploading a file: %s' % ex)
92 template_file = open(os.path.join(os.path.dirname(__file__),
'dqm-histo-comparison-summary-template.html'),
'r') 93 result = template_file.read() 95 result = result.replace('$PR_LIST$', pr_list)
100 for comp
in COMPARISON_RESULTS:
101 total_changes += comp[
'removed_elements'] + comp[
'added_elements'] + comp[
'changed_elements']
102 baseline_count = comp[
'changed_elements'] + comp[
'removed_elements']
103 pr_count = comp[
'changed_elements'] + comp[
'added_elements']
104 overlay_count = baseline_count
107 base_url =
'https://cmsweb.cern.ch/dqm/dev/start?runnr=%s;dataset%%3D%s;sampletype%%3Doffline_relval;workspace%%3DEverything;' % (comp[
'run_nr'], comp[
'base_dataset'])
108 pr_url =
'https://cmsweb.cern.ch/dqm/dev/start?runnr=%s;dataset%%3D%s;sampletype%%3Doffline_relval;workspace%%3DEverything;' % (comp[
'run_nr'], comp[
'pr_dataset'])
109 overlay_url =
'https://cmsweb.cern.ch/dqm/dev/start?runnr=%s;dataset%%3D%s;referenceshow%%3Dall;referenceobj1%%3Dother::%s::;sampletype%%3Doffline_relval;workspace%%3DEverything;' \
110 % (comp[
'run_nr'], comp[
'pr_dataset'], comp[
'base_dataset'])
112 table_items +=
' <tr>\n' 113 table_items +=
' <td><a href="%s" target="_blank">%s baseline GUI</a><span> (%s)</span></td>\n' % (base_url, comp[
'workflow'], baseline_count)
114 table_items +=
' <td><a href="%s" target="_blank">%s pr GUI</a><span> (%s)</span></td>\n' % (pr_url, comp[
'workflow'], pr_count)
115 table_items +=
' <td><a href="%s" target="_blank">%s overlay GUI</a><span> (%s)</span></td>\n' % (overlay_url, comp[
'workflow'], overlay_count)
116 table_items +=
' <td><span class="removed">-%s</span><span class="added">+%s</span><span class="changed">%s</span></td>\n' \
117 % (comp[
'removed_elements'], comp[
'added_elements'], comp[
'changed_elements'])
118 table_items +=
' </tr>\n' 120 result = result.replace(
'$TOTAL_CHANGES$',
str(total_changes))
121 result = result.replace(
'$NUMBER_OF_WORKFLOWS$',
str(len(COMPARISON_RESULTS)))
122 result = result.replace(
'$PER_WORKFLOW_LIST$', table_items)
123 template_file.close()
126 result_file_path = os.path.join(summary_dir,
'dqm-histo-comparison-summary.html')
127 if os.path.dirname(result_file_path):
128 if not os.path.exists(os.path.dirname(result_file_path)):
129 os.makedirs(os.path.dirname(result_file_path))
130 summary_file = open(result_file_path,
'w')
131 summary_file.write(result)
134 if __name__ ==
'__main__':
135 parser = argparse.ArgumentParser(description=
"This tool compares DQM monitor elements within DQM files found in base-dir with the ones found in in pr-dir. " 136 "All workflow directories are searched for correctly named DQM root files. " 137 "Comparison is done bin by bin and output is written to a root files containing only the changes.")
138 parser.add_argument(
'-b',
'--base-dir', help=
'Baseline IB directory', default=
'basedata/')
139 parser.add_argument(
'-p',
'--pr-dir', help=
'PR directory', default=
'prdata/')
140 parser.add_argument(
'-o',
'--output-dir', help=
'Comparison root files output directory', default=
'dqmHistoComparisonOutput')
141 parser.add_argument(
'-j',
'--nprocs', help=
'Number of processes', default=1, type=int)
142 parser.add_argument(
'-n',
'--pr-number', help=
'This is obsolete and should NOT be used.', required=
False)
143 parser.add_argument(
'-t',
'--test-number', help=
'Unique test number to distinguish different comparisons of the same PR.', default=
'1')
144 parser.add_argument(
'-r',
'--release-format', help=
'Release format in this format: CMSSW_10_5_X_2019-02-17-0000', required=
True)
145 parser.add_argument(
'-s',
'--summary-dir', help=
'Directory where summary with all links will be saved', default=
'')
146 parser.add_argument(
'-l',
'--pr-list', help=
'A list of PRs participating in the comparison', default=
'')
147 args = parser.parse_args()
150 pr_number = args.pr_list.split(
' ')[0].
split(
'/')[1].
replace(
'#',
'_')
152 collect_and_compare_files(args.base_dir, args.pr_dir, args.output_dir, args.nprocs, pr_number, args.test_number, args.release_format)
def collect_and_compare_files(base_dir, pr_dir, output_dir, num_procs, pr_number, test_number, release_format)
def replace(string, replacements)
S & print(S &os, JobReport::InputFile const &f)
def upload_to_gui(output_dir, num_procs)
def get_file_pairs(base_dir, pr_dir)
def generate_summary_html(output_dir, pr_list, summary_dir)
def compare(base_dir, pr_dir, output_dir, files, pr_number, test_number, release_format)
static std::string join(char **cmd)