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).
decode()
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 cmssw_version =
'_'.
join(release_format.split(
'_')[:4])
47 cmssw_version = cmssw_version[:-1] +
'x' 48 root_file_dir_in_gui =
'ROOT/RelValData/%s/' % cmssw_version
49 if 'R000000001__RelVal' in base_output_filename:
50 root_file_dir_in_gui =
'ROOT/RelVal/%s/' % cmssw_version
52 base_file_path_in_gui = root_file_dir_in_gui + base_output_filename
53 pr_file_path_in_gui = root_file_dir_in_gui + pr_output_filename
55 COMPARISON_RESULTS.append({
'workflow': workflow,
'base_dataset': base_dataset,
'pr_dataset': pr_dataset,
'run_nr': run_nr,\
56 'changed_elements':
int(output_numbers[0]),
'removed_elements':
int(output_numbers[1]),
'added_elements':
int(output_numbers[2]),
57 'base_file_path_in_gui': base_file_path_in_gui,
'pr_file_path_in_gui': pr_file_path_in_gui})
58 except Exception
as ex:
59 print(
'Exception comparing two root files: %s' % ex)
62 base_files = glob.glob(os.path.join(base_dir,
'*.*_*/DQM_*.root'))
63 pr_files = glob.glob(os.path.join(pr_dir,
'*.*_*/DQM_*.root'))
67 base_files = [ os.path.relpath(x, base_dir)
for x
in base_files ]
68 pr_files = [ os.path.relpath(x, pr_dir)
for x
in pr_files ]
71 return [value
for value
in base_files
if value
in pr_files]
74 base_files = glob.glob(os.path.join(output_dir,
'base/*.root'))
75 pr_files = glob.glob(os.path.join(output_dir,
'pr/*.root'))
77 files = base_files + pr_files
79 print(
'Files to be uploaded:')
82 for _
in range(
min(num_procs, len(files))):
83 thread = Thread(target=upload, args=(files,))
90 command = [
'visDQMUpload.py',
'https://cmsweb.cern.ch/dqm/dev', file]
91 print(
'Uploading output:')
94 subprocess.call(command)
96 except Exception
as ex:
99 print(
'Exception uploading a file: %s' % ex)
102 template_file_path = os.path.join(os.getenv(
'CMSSW_BASE'),
'src',
'DQMServices',
'FileIO',
'scripts',
'dqm-histo-comparison-summary-template.html')
103 if not os.path.isfile(template_file_path):
104 template_file_path = os.path.join(os.getenv(
'CMSSW_RELEASE_BASE'),
'src',
'DQMServices',
'FileIO',
'scripts',
'dqm-histo-comparison-summary-template.html')
105 template_file = open(template_file_path,
'r') 106 result = template_file.read() 108 result = result.replace('$PR_LIST$', pr_list)
113 for comp
in COMPARISON_RESULTS:
114 total_changes += comp[
'removed_elements'] + comp[
'added_elements'] + comp[
'changed_elements']
115 baseline_count = comp[
'changed_elements'] + comp[
'removed_elements']
116 pr_count = comp[
'changed_elements'] + comp[
'added_elements']
117 overlay_count = baseline_count
120 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'])
121 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'])
122 overlay_url =
'https://cmsweb.cern.ch/dqm/dev/start?runnr=%s;dataset%%3D%s;referenceshow%%3Dall;referencenorm=False;referenceobj1%%3Dother::%s::;sampletype%%3Doffline_relval;workspace%%3DEverything;' \
123 % (comp[
'run_nr'], comp[
'pr_dataset'], comp[
'base_dataset'])
124 base_raw_url =
'https://cmsweb.cern.ch/dqm/dev/jsroot/index.htm?file=https://cmsweb.cern.ch/dqm/dev/data/browse/%s' % comp[
'base_file_path_in_gui']
125 pr_raw_url =
'https://cmsweb.cern.ch/dqm/dev/jsroot/index.htm?file=https://cmsweb.cern.ch/dqm/dev/data/browse/%s' % comp[
'pr_file_path_in_gui']
127 table_items +=
' <tr>\n' 128 table_items +=
' <td><a href="%s" target="_blank">%s baseline GUI</a><span> (%s)</span></td>\n' % (base_url, comp[
'workflow'], baseline_count)
129 table_items +=
' <td><a href="%s" target="_blank">%s pr GUI</a><span> (%s)</span></td>\n' % (pr_url, comp[
'workflow'], pr_count)
130 table_items +=
' <td><a href="%s" target="_blank">%s overlay GUI</a><span> (%s)</span></td>\n' % (overlay_url, comp[
'workflow'], overlay_count)
131 table_items +=
' <td><a href="%s" target="_blank">%s baseline rootjs</a><span> (%s)</span></td>\n' % (base_raw_url, comp[
'workflow'], baseline_count)
132 table_items +=
' <td><a href="%s" target="_blank">%s pr rootjs</a><span> (%s)</span></td>\n' % (pr_raw_url, comp[
'workflow'], pr_count)
133 table_items +=
' <td><span class="removed">-%s</span><span class="added">+%s</span><span class="changed">%s</span></td>\n' \
134 % (comp[
'removed_elements'], comp[
'added_elements'], comp[
'changed_elements'])
135 table_items +=
' </tr>\n' 137 result = result.replace(
'$TOTAL_CHANGES$',
str(total_changes))
138 result = result.replace(
'$NUMBER_OF_WORKFLOWS$',
str(len(COMPARISON_RESULTS)))
139 result = result.replace(
'$PER_WORKFLOW_LIST$', table_items)
140 template_file.close()
143 result_file_path = os.path.join(summary_dir,
'dqm-histo-comparison-summary.html')
144 if os.path.dirname(result_file_path):
145 if not os.path.exists(os.path.dirname(result_file_path)):
146 os.makedirs(os.path.dirname(result_file_path))
147 summary_file = open(result_file_path,
'w')
148 summary_file.write(result)
151 if __name__ ==
'__main__':
152 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. " 153 "All workflow directories are searched for correctly named DQM root files. " 154 "Comparison is done bin by bin and output is written to a root files containing only the changes.")
155 parser.add_argument(
'-b',
'--base-dir', help=
'Baseline IB directory', default=
'basedata/')
156 parser.add_argument(
'-p',
'--pr-dir', help=
'PR directory', default=
'prdata/')
157 parser.add_argument(
'-o',
'--output-dir', help=
'Comparison root files output directory', default=
'dqmHistoComparisonOutput')
158 parser.add_argument(
'-j',
'--nprocs', help=
'Number of processes', default=1, type=int)
159 parser.add_argument(
'-n',
'--pr-number', help=
'This is obsolete and should NOT be used.', required=
False)
160 parser.add_argument(
'-t',
'--test-number', help=
'Unique test number to distinguish different comparisons of the same PR.', default=
'1')
161 parser.add_argument(
'-r',
'--release-format', help=
'Release format in this format: CMSSW_10_5_X_2019-02-17-0000')
162 parser.add_argument(
'-s',
'--summary-dir', help=
'Directory where summary with all links will be saved', default=
'')
163 parser.add_argument(
'-l',
'--pr-list', help=
'A list of PRs participating in the comparison', default=
'')
164 args = parser.parse_args()
167 pr_number =
'Unknown' 169 pr_number = args.pr_list.split(
' ')[0].
split(
'/')[1].
replace(
'#',
'_')
173 release_format = args.release_format
174 if not release_format:
176 release_format = os.environ[
'CMSSW_VERSION']
178 print(
'You are not in a CMSSW release. Please provide a valid release-format (-r option)')
181 collect_and_compare_files(args.base_dir, args.pr_dir, args.output_dir, args.nprocs, pr_number, args.test_number, 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)
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)
void print(TMatrixD &m, const char *label=nullptr, bool mathematicaFormat=false)
def compare(base_dir, pr_dir, output_dir, files, pr_number, test_number, release_format)
def split(sequence, size)
static std::string join(char **cmd)
bool decode(bool &, std::string_view)