ATLAS Offline Software
Loading...
Searching...
No Matches
chainComp Namespace Reference

Functions

 get_parser ()
 find_reference (inputFile)
 find_repository (ref_path)
 load_yaml (path)
 print_event_diff (inp_data, ref_data, key)
 print_step_diff (inp_data, ref_data, key)
 print_diff (inp_dict, ref_dict, matching_only=False)
 create_patch (inp_path, ref_path)
 main ()

Detailed Description

Script to compare trigger chain counts in YAML format produced by
chainDump.py --yaml and providing information and instructions for
updating counts reference in the athena repository.

Function Documentation

◆ create_patch()

chainComp.create_patch ( inp_path,
ref_path )

Definition at line 168 of file chainComp.py.

168def create_patch(inp_path, ref_path):
169 def find_ref_package():
170 for path in [ref_path, find_reference(inp_path), find_reference(ref_path)]:
171 for pkg in packages:
172 if '/data/'+pkg in ref_path:
173 return pkg, os.path.split(path)[1]
174 return None, None
175 package_name, ref_file_name = find_ref_package()
176 if not package_name:
177 logging.warning('Failed to find reference package name, cannot create git patch file')
178 return
179
180 ref_rel_path = '/Trigger/TrigValidation/' + package_name + '/share/' + ref_file_name
181
182 diff_cmd = 'diff -U 1 -b'
183 diff_cmd += ' --label a' + ref_rel_path + ' ' + ref_path
184 diff_cmd += ' --label b' + ref_rel_path + ' ' + inp_path
185
186 diff_txt = subprocess.getoutput(diff_cmd)
187 patch_name = os.path.split(ref_path)[1]
188 if patch_name.endswith('.ref') or patch_name.endswith('.new'):
189 patch_name = patch_name[0:-4]
190 patch_name += '.patch'
191 with open(patch_name, 'w') as patch_file:
192 patch_file.write('diff --git a{p:s} b{p:s}\n'.format(p=ref_rel_path))
193 patch_file.write(diff_txt + '\n')
194 logging.info('Patch file created. To apply, run in the athena source directory:')
195 logging.info('git apply %s/%s', os.getcwd(), patch_name)
196 logging.info('Then check with git diff and, if everything is correct, add and commit')
197 if running_in_CI():
198 logging.info('or see the patch below:\n')
199 subprocess.call('cat ' + patch_name, shell=True)
200 print('\n') # noqa: ATL901
201
202
void print(char *figname, TCanvas *c1)

◆ find_reference()

chainComp.find_reference ( inputFile)

Definition at line 50 of file chainComp.py.

50def find_reference(inputFile):
51 ref_path = None
52 if inputFile.endswith('.new'):
53 inp_name = os.path.split(inputFile)[-1]
54 ref_name = inp_name[0:-4] + '.ref'
55 logging.debug('Searching for file %s in DATAPATH', ref_name)
56 for pkg_name in packages:
57 ref_path = unixtools.find_datafile(pkg_name+'/'+ref_name)
58 if ref_path:
59 break
60 if ref_path:
61 logging.debug('Found %s', ref_path)
62 else:
63 logging.debug('Not found')
64 return ref_path
65
66

◆ find_repository()

chainComp.find_repository ( ref_path)
Try to find the athena git repository based on paths in env.
Needs to work both in local WorkDir build and in full/incremental CI build.

Definition at line 67 of file chainComp.py.

67def find_repository(ref_path):
68 '''
69 Try to find the athena git repository based on paths in env.
70 Needs to work both in local WorkDir build and in full/incremental CI build.
71 '''
72 logging.debug('Searching for the source repository path')
73 search_str = '/Trigger/TrigValidation'
74 def try_path(p):
75 logging.debug('Trying %s', p)
76 if os.path.islink(p) and os.path.isfile(p) and search_str in os.path.realpath(p):
77 candidate = os.path.realpath(p).split(search_str)[0]
78 logging.debug('Candidate %s', candidate)
79 if os.path.isdir(candidate + '/.git'):
80 return candidate
81 return None
82
83 result = try_path(ref_path)
84 if result:
85 return result
86
87 env_vars = ['DATAPATH', 'JOBOPTSEARCHPATH', 'CALIBPATH', 'XMLPATH']
88 path_lists = [os.getenv(var).split(os.pathsep) for var in env_vars]
89 max_len = max([len(pl) for pl in path_lists])
90 max_len = min(max_len, 2) # Limit to first two paths to avoid very deep and slow search
91 for i in range(max_len):
92 for pl in path_lists:
93 if i >= len(pl):
94 continue
95 paths = glob.glob(pl[i]+'/**', recursive=True)
96 for p in paths:
97 result = try_path(p)
98 if result:
99 return result
100 return None
101
102
#define min(a, b)
Definition cfImp.cxx:40
#define max(a, b)
Definition cfImp.cxx:41
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177

◆ get_parser()

chainComp.get_parser ( )

Definition at line 24 of file chainComp.py.

24def get_parser():
25 parser = argparse.ArgumentParser(usage='%(prog)s [options] inputFile',
26 description=__doc__)
27 parser.add_argument('inputFile',
28 metavar='PATH',
29 help='Name of input counts file')
30 parser.add_argument('-r', '--referenceFile',
31 metavar='PATH',
32 help='Name of reference counts file. If empty, try to guess from inputFile')
33 parser.add_argument('-s', '--sourceRepository',
34 metavar='PATH',
35 help='Path to the git checkout of the athena repository.'
36 'If empty, try to guess from the environment')
37 parser.add_argument('-p', '--patch',
38 action='store_true',
39 help='Create a git patch file with the count differences')
40 parser.add_argument('-m', '--matchingOnly',
41 action='store_true',
42 help='Ignore added and removed chains, and only compare counts for chains ' + \
43 'present in both reference and input file')
44 parser.add_argument('-v', '--verbose',
45 action='store_true',
46 help='Increase output verbosity')
47 return parser
48
49

◆ load_yaml()

chainComp.load_yaml ( path)

Definition at line 103 of file chainComp.py.

103def load_yaml(path):
104 result = None
105 if not os.path.isfile(path):
106 logging.error('Not a file: %s', path)
107 return result
108 with open(path) as f:
109 result = yaml.safe_load(f)
110 return result
111
112

◆ main()

chainComp.main ( )

Definition at line 203 of file chainComp.py.

203def main():
204 args = get_parser().parse_args()
205 logging.basicConfig(stream=sys.stdout,
206 format='chainComp %(levelname)-8s %(message)s',
207 level=logging.DEBUG if args.verbose else logging.INFO)
208
209 inp_path = args.inputFile
210 ref_path = args.referenceFile or find_reference(inp_path)
211 if not ref_path:
212 logging.error('No reference file specified and couldn\'t guess from '
213 'input name. Please use the -r argument (see --help).')
214 return 1
215
216 logging.info('Test file: %s', inp_path)
217 logging.info('Reference file: %s', ref_path)
218
219 # Currently not used, but ready for implementing checks against upstream
220 # src_path = args.sourceRepository or find_repository(ref_path)
221 # logging.info('Repository path: %s', src_path)
222
223 inp_dict = load_yaml(inp_path)
224 ref_dict = load_yaml(ref_path)
225 if (not inp_dict) or (not ref_dict):
226 return 1
227
228 retcode = print_diff(inp_dict, ref_dict, args.matchingOnly)
229 if retcode:
230 logging.error('Trigger counts differ from the reference. If the above differences are intended, update the reference')
231 if args.patch:
232 create_patch(inp_path, ref_path)
233 else:
234 logging.info('Trigger counts match the reference')
235
236 return retcode
237
238
int main()
Definition hello.cxx:18

◆ print_diff()

chainComp.print_diff ( inp_dict,
ref_dict,
matching_only = False )

Definition at line 130 of file chainComp.py.

130def print_diff(inp_dict, ref_dict, matching_only=False):
131 retcode = 0
132 chains_not_in_ref = [c[0] for c in inp_dict.items() if c[0] not in ref_dict]
133 chains_not_in_inp = [c[0] for c in ref_dict.items() if c[0] not in inp_dict]
134 chains_count_diff = [c[0] for c in inp_dict.items() if c[0] in ref_dict and c[1] != ref_dict[c[0]]]
135
136 # New chains (missing in reference)
137 n_new_chains = len(chains_not_in_ref)
138 if n_new_chains > 0 and not matching_only:
139 retcode = 1
140 logging.info('Found %d new chain%s added:', n_new_chains, 's' if n_new_chains > 1 else '')
141 for chain_name in chains_not_in_ref:
142 logging.info(' %s', chain_name)
143
144 # Removed chains (missing in test file)
145 n_removed_chains = len(chains_not_in_inp)
146 if n_removed_chains > 0 and not matching_only:
147 retcode = 1
148 logging.info('Found %d chain%s removed:', n_removed_chains, 's' if n_removed_chains > 1 else '')
149 for chain_name in chains_not_in_inp:
150 logging.info(' %s', chain_name)
151
152 # Count differences
153 n_diff_chains = len(chains_count_diff)
154 if n_diff_chains > 0:
155 retcode = 1
156 logging.info('Found %d chain%s with count differences:', n_diff_chains, 's' if n_diff_chains > 1 else '')
157 for chain_name in chains_count_diff:
158 logging.info(' %s:', chain_name)
159 inp_data = inp_dict[chain_name]
160 ref_data = ref_dict[chain_name]
161 print_event_diff(inp_data, ref_data, 'eventCount')
162 print_step_diff(inp_data, ref_data, 'stepCounts')
163 print_step_diff(inp_data, ref_data, 'stepFeatures')
164
165 return retcode
166
167

◆ print_event_diff()

chainComp.print_event_diff ( inp_data,
ref_data,
key )

Definition at line 113 of file chainComp.py.

113def print_event_diff(inp_data, ref_data, key):
114 if inp_data[key] != ref_data[key]:
115 logging.info(' %s: %d -> %d', key, ref_data[key], inp_data[key])
116
117

◆ print_step_diff()

chainComp.print_step_diff ( inp_data,
ref_data,
key )

Definition at line 118 of file chainComp.py.

118def print_step_diff(inp_data, ref_data, key):
119 inp_steps = inp_data.get(key, dict())
120 ref_steps = ref_data.get(key, dict())
121 if inp_steps != ref_steps:
122 logging.info(' %s:', key)
123 for step in range(max(len(inp_steps), len(ref_steps))):
124 inp_count = inp_steps.get(step, 0)
125 ref_count = ref_steps.get(step, 0)
126 if inp_count != ref_count:
127 logging.info(' %d: %d -> %d', step, ref_count, inp_count)
128
129