ATLAS Offline Software
XMLtoHeader.py
Go to the documentation of this file.
1 #!/usr/bin/python
2 
3 from __future__ import print_function
4 
5 # Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
6 import os.path
7 import sys
8 import getopt
9 import xml.etree.ElementTree as ET
10 from datetime import date
11 
12 #--------------------------------------
13 #get command line arguments
14 #--------------------------------------
15 argv = sys.argv
16 
17 inputXMLname = '../schema/L1CTSpecifications.xml'
18 outputNames = 'L1Common'
19 
20 opts, remainder = getopt.getopt( argv[1:], 'i:o:', ['inputXML=','outputNames='])
21 #print ("OPTIONS: ", opts)
22 #print ("REMAINDER: ", remainder)
23 
24 for opt,arg in opts:
25  if opt in ['-i','--inputXML']:
26  inputXMLname = arg
27  elif opt in ['-o','--outputNames']:
28  outputNames = arg
29  else:
30  print("option %s not known.." % opt)
31 
32 
33 
34 #-----------------------------------
35 # some definitions
36 #-----------------------------------
37 
38 typeDictCpp = {'u32' :'uint32_t','u16':'uint16_t','s32' :'int32_t','s16':'int16_t','string':'string', 'bool':'bool','float':'float','double':'double'}
39 typeDictJava = {'u32' :'long','u16':'long','s32' :'int','s16':'int','string':'String', 'bool':'Boolean','float':'Single','double':'Double'}
40 
41 versionDict = {}
42 
43 if 'dataformat' in os.path.basename(outputNames):
44  versionDict = {'v0':'Before moving the L1A position to the eformat-version field', 'v1': 'After moving the L1A position to the eformat-version field to free bits for the HLT counter', 'v2':'First version of CTP data with programmable extra words (up to 50), and time difference in BC to previous L1A', 'v3':'Including also the turn counter in the payload','v4':'Version with increased number of inputs/items for run-2 (->beginning 2015)'}#,'vZ': 'dummy for testing'}
45 
46 if 'L1Common' in os.path.basename(outputNames):
47  #versionDict = {'v0':'Before long shutdown I (before 2015)', 'v1': 'Version after long shutdown I','v2':'dummy','v3':'dummy','v4':'dummy'}
48  versionDict = {'v0':'Before long shutdown I (before 2015)', 'v1': 'Version after long shutdown I'}
49 
50 
51 #print versionDict.keys()
52 message_missingElement = 'Concerning child #{number}: Sorry, no {element} specified. This is a necessary element. Please make sure to specify it in the config file.'
53 
54 
55 
56 #----------------------
57 #Read the XML tree
58 #----------------------
59 tree = ET.parse(inputXMLname)
60 root = tree.getroot()
61 
62 #---------------------------------------------
63 #Get all versions that exist for an element
64 #---------------------------------------------
65 
66 nameVersionsDict={}
67 childIndex = 0
68 for child in root:
69  childIndex +=1
70  if child.find('name') is None:
71  #print (message_missingElement.format(number=childIndex, element='name'))
72  exit(1)
73  elif child.find('name').text[1:-1] in nameVersionsDict:
74  nameVersionsDict[child.find('name').text[1:-1]].append(child.attrib['ns'])
75  else:
76  versionList = [child.attrib['ns']]
77  nameVersionsDict[child.find('name').text[1:-1]] = versionList
78 
79 #print (nameVersionsDict)
80 staticList = [] #parameters that didn't change so far
81 for name in nameVersionsDict:
82  if len(nameVersionsDict[name])==1:
83  staticList.append(name)
84  for vers in nameVersionsDict[name]:
85  count = nameVersionsDict[name].count(vers)
86  if count>1:
87  #print ('ERROR: Element "',name,'" occurs several times with same version (' , vers, '). Please fix config file.')
88  exit(1)
89 
90 
91 #------------------------------------------------------------------
92 #Get number of changed parameters compared to v0 for each version
93 #------------------------------------------------------------------
94 numChangeVersionDict = {}
95 numChangeVersionDict['v0'] = 0
96 changedParameterNames = []
97 for v in list(versionDict)[1:]:
98  childIndex = 0
99  for child in root:
100  childIndex +=1
101  if child.attrib['ns'] is None:
102  #print (message_missingElement.format(number=childIndex, element='ns'))
103  exit(1)
104  else:
105  if child.attrib['ns']==v:
106  if child.find('name').text[1:-1] not in changedParameterNames:
107  changedParameterNames.append(child.find('name').text[1:-1])
108 
109  numChangeVersionDict[v] = len(changedParameterNames)
110 
111 
112 
113 
114 def CreateFiles(time):
115 #=====================================
116 # actually create the output files
117 #=====================================
118 
119  #--------- the definition of CTP version class--------------------------------
120  cppBaseStartstring = "/*\n*This file was automatically created by XMLtoHeader.py\n* Created on: {creationTime}\n* Created with config: {xmlFile}\n*\n* Author: Ruth Poettgen\n* Contact: ruth.poettgen@cern.ch\n**Brief: Defines class for different CTP versions.\n*/\n\n\n#include <inttypes.h>\n#include <assert.h>\n#include <iostream>\n#include <stdlib.h>\n#include <map>\n#include <iomanip>\n#include <sstream>\n\n"
121  start = cppBaseStartstring.format(creationTime = time, xmlFile = inputXMLname)
122 
123  baseNameRoot = os.path.basename(outputNames)
124  baseName = baseNameRoot + 'Version'
125  fileName = outputNames + 'Version'
126  baseHeader = open(fileName+'.h','w')
127  baseHeader.write(start)
128 
129 
130  baseHeader.write('#ifndef '+baseName.upper() + '_H\n')
131  baseHeader.write('#define '+baseName.upper() + '_H\n')
132  baseHeader.write('\nclass '+baseName + '{\n\n')
133 
134  protectedString = "\nprotected:\n"
135  protectedString += " //---------------------------------------------------------------------------------------------------\n"
136  protectedString += " // For explanation of the variables and there values in different versions see config XML file.\n"
137  protectedString += " //---------------------------------------------------------------------------------------------------\n"
138 
139  functionString = ''
140 
141  publicString = "\npublic: \n"
142  publicString += '\n ' + baseName + '(unsigned int version) {\n'
143 
144  dumpString = '\n std::string dump() const {\n';
145  dumpString += '\n std::ostringstream s;\n';
146  dumpString += '\n std::ostringstream tmp;\n\n';
147  dumpString += ' s << \"For a description of the parameters for different CTP version, see schema/L1CoreSpecifications.xml in L1CommonCore.\" << std::endl;\n\n';
148  dumpString += ' s << \"|-------------------------------------------------------------|\" << std::endl;\n';
149  dumpString += ' s << \"| Name | Value |\" << std::endl;\n';
150  dumpString += ' s << \"|-------------------------------------------------------------|\" << std::endl;\n';
151 
152  #dumpString += ' s << \"|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\" << std::endl;\n';
153  #dumpString += ' s << \"| Name | Value | Comment |\" << std::endl;\n';
154  #dumpString += ' s << \"|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\" << std::endl;\n';
155 
156  changedValuesDict = {}
157  numberOfChanges = 0
158  #--------------------------------------------
159  #get start strings for the other files
160  #--------------------------------------------
161 
162  pyStartstring = "#!/usr/bin/env python\n\n#This file was automatically created by XMLtoHeader.py\n# Created on: {creationTime}\n# Created with config: {xmlFile}\n# \n# Author: Ruth Poettgen\n# Contact: ruth.poettgen@cern.ch\n\n\n\nimport sys\n\nclass {classname}(object):\n def __init__(self):\n"
163 
164  #javaStartstring = "/*\n*This file was automatically created by XMLtoHeader.py\n* Created on: {creationTime}\n* Created with config: {xmlFile}\n*\n* Author: Ruth Poettgen\n* Contact: ruth.poettgen@cern.ch\n**Brief: Defines some CTP parameters. {version}.\n*/\n\n\npackage {pack};\n\npublic class {classname} "
165 
166 
167  #-------------------------------------------------------
168  # write one file/one constructor part for each version
169  #-------------------------------------------------------
170  for v in versionDict:
171 
172  if (v!='v0'):
173  changedValuesDict[v] = []
174 
175  pyStartstring = pyStartstring.format(creationTime = time,version = versionDict[v], xmlFile = inputXMLname, classname=baseNameRoot)
176  headerName = outputNames + "_" + v + ".py"
177  pyHeader = open(headerName,'w')
178  pyHeader.write(pyStartstring)
179 
180  #javaStartstring = javaStartstring.format(creationTime = time, xmlFile = inputXMLname,version = versionDict[v],pack='L1Common.'+ outputNames,classname=outputNames+'_'+v)
181  #headerName = outputNames + "_" + v + ".java"
182  #javaHeader = open(headerName,'w')
183  #javaHeader.write(javaStartstring + '{\n\n')
184 
185 
186  childIndex=0
187  nameList=[]
188 
189  for child in root:
190  hasChanged = False
191  childIndex=childIndex+1
192  #print ('looking at child #', childIndex)
193 
194  if child.attrib['ns'] not in versionDict:
195  #print 'Version ID ', child.attrib['ns'], ' not recognised. Should be one of ', versionDict.keys()
196  exit(1)
197 
198  #check if all the attributes necessary are set
199  if child.find('name') is None:
200  #print (message_missingElement.format(number=childIndex, element='name'))
201  exit(1)
202  if child.find('type') is None:
203  #print (message_missingElement.format(number=childIndex, element='type'))
204  exit(1)
205  if child.find('value') is None:
206  #print (message_missingElement.format(number=childIndex, element='value'))
207  exit(1)
208 
209 
210  #check wether parameter has already been written, don't write again
211  if child.find('name').text[1:-1] in nameList:
212  #print (child.find('name').text[1:-1], ' already written. Skipping.')
213  continue
214  #else:
215  #print ('Found new parameter: ', child.find('name').text[1:-1])
216 
217 
218  #-------------------------------------------------------------
219  #get latest version of parameter for the required CTP version
220  #-------------------------------------------------------------
221 
222  if list(versionDict).index( child.attrib['ns'] )>list(versionDict).index(v):
223  #print 'Version (' , child.attrib['ns'] , ') is beyond what we are looking for right now (' , v, ') . Skipping.'
224  continue
225 
226  tmp_v=v
227  while tmp_v not in nameVersionsDict[child.find('name').text[1:-1]]:
228  #print tmp_v, 'is not contained in ', nameVersionsDict[child.find('name').text[1:-1]]
229  index = list(versionDict).index(tmp_v)
230  tmp_v = list(versionDict)[index-1]
231  #print '--> Going to write ' , tmp_v , ' instead'
232 
233  if tmp_v!='v0':
234  hasChanged=True
235 
236  if child.attrib['ns']!=tmp_v:
237  #print ('Version (' , child.attrib['ns'] , ') is not what we are looking for right now. Skipping.')
238  continue
239 
240 
241  #-------------------------------------------------------------
242  # write the files
243  #-------------------------------------------------------------
244 
245  typeText = child.find('type').text
246  nameText = child.find('name').text[1:-1]
247  valueText = child.find('value').text
248 
249 
250  pyHeader.write(' self.'+nameText.ljust(30)+'= ')
251 
252  if 'mult' in typeText: #arrays need special treatment
253 
254  #javaHeader.write(' '+'public static ' + typeDictJava[ typeText[0:-5] ] +'[] ')
255  #javaHeader.write(nameText.ljust(30)+'= ')
256  #javaHeader.write(' { ' + valueText +' };')
257 
258  pyHeader.write( ('[ ' + valueText + ' ]').ljust(50) )
259 
260 
261  listOfElements = valueText.split(',')
262  numberOfElements = len(listOfElements)
263 
264  if v=='v0':
265 
266  protectedString += ' '
267  protectedString += typeDictCpp[typeText[0:-5]] + ' '
268  protectedString += (nameText+ '['+ str(numberOfElements) + ']').ljust(20)+ '='
269  protectedString += '{ ' + valueText + '};'
270 
271 
272  functionString += '\n const '+typeDictCpp[typeText[0:-5]] + '* get'
273  functionString += nameText + '() const { return ' + nameText + '; }'
274 
275 
276  dumpString += '\n s << \"|\" << std::left << std::setw(40) << \" ' + nameText + '\" << \" | \";\n'
277  dumpString += ' tmp.clear(); tmp.str(\"\");\n tmp<< \"[\";\n'
278  dumpString += ' for (int i=0; i <' + str(numberOfElements) + '; i++) {\n'
279  dumpString += ' if (i) tmp<<\",\";\n'
280  dumpString += ' tmp << this->' + nameText + '[i];\n }\n tmp<<\"]\";\n'
281  dumpString += ' s << std::right << std::setw(17) << tmp.str() << \" | \" << std::endl;\n\n'
282  #dumpString += ' s << std::right << std::setw(35) << tmp.str() << \" | \";\n'
283  #if child.find('comment') is None:
284  # dumpString += ' s << std::left << std::setw(120) << ' + '\"--\"' + ' << \" | \" << std::endl;\n\n'
285  #else:
286  # dumpString += ' s << std::left << std::setw(120) << ' + child.find('comment').text + ' << \" | \" << std::endl;\n\n'
287 
288 
289 
290  if hasChanged:
291  changedValuesDict[v].append([nameText,valueText])
292 
293  else:
294  #javaHeader.write(' public static ' + typeDictJava[typeText] +' ')
295  #javaHeader.write(nameText.ljust(30)+'= ')
296  #javaHeader.write(valueText +';')
297 
298  if (valueText)[0] not in ['0','1','2','3','4','5','6','7','8','9']:
299  val = valueText
300  pyHeader.write( ('self.' + val.replace('+',' + self.')).ljust(10))
301  else:
302  pyHeader.write(valueText.ljust(10))
303 
304 
305  if v=='v0':
306  functionString += '\n '+typeDictCpp[typeText] + ' get'
307  functionString += nameText + '() const { return ' + nameText + '; }'
308 
309  protectedString += ' ' + typeDictCpp[typeText] + ' '
310  protectedString += nameText
311  protectedString += ' = ' + valueText + ';'
312 
313  dumpString += ' s << \"|\" << std::left << std::setw(40) << \" ' + nameText + '\" << \" | \";\n'
314  dumpString += ' s << std::right << std::setw(17) << this->' + nameText + ' << \" | \" << std::endl;\n\n'
315  #dumpString += ' s << std::right << std::setw(35) << this->' + nameText + ' << \" | \";\n'
316  #if child.find('comment') is None:
317  #dumpString += ' s << std::left << std::setw(120) << ' + '\"--\"' + ' << \" | \" << std::endl;\n\n'
318  #else:
319  #dumpString += ' s << std::left << std::setw(120) << ' + child.find('comment').text + ' << \" | \" << std::endl;\n\n'
320 
321 
322  if hasChanged:
323  changedValuesDict[v].append([nameText,valueText])
324 
325 
326 
327  #--- comment -------------------------
328  if child.find('comment') is None:
329  pyHeader.write('\n')
330  #javaHeader.write('\n')
331  else:
332  pyHeader.write( ' # ' + child.find('comment').text[1:-1] + '\n')
333  if v =='v0':
334  protectedString += '\n'
335 
336  nameList.append(nameText)
337 
338 
339 
340 
341  #------------------------------
342  # finalise the file writing
343  #------------------------------
344 
345  pyHeader.write('\n\n' + baseNameRoot + '_' + v + ' = ' + baseNameRoot + '()'+'\n\n' + 'del ' + baseNameRoot)
346  #javaHeader.write('\n}')
347 
348  dumpString += ' s << \"|-------------------------------------------------------------|\" << std::endl;\n\n';
349  #dumpString += ' s << \"|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\" << std::endl;\n\n';
350  dumpString += ' return s.str();\n\n }'
351 
352  nVersions = len(versionDict)
353 
354  #access function
355  selection= ' if (version>=' + str(nVersions)+') {\n';
356  selection+= ' std::cerr << \"ERROR: invalid CTP version requested (\" << version << \"). Should be in [0,'+ str(nVersions-1)+ '].Setting it to the latest version ('+str(nVersions-1)+'). \" << std::endl;\n'
357  selection += ' version='+str(nVersions-1)+';\n'
358  selection+= ' }\n\n'
359 
360 
361  versionInt = 1
362  for v in changedValuesDict:
363  selection += ' if (version==' + str(versionInt) + ' ) {\n'
364  for pair in changedValuesDict[v]:
365  if ',' in pair[1]:
366  listOfValues = pair[1].split(',')
367  numValues = len(listOfElements)
368  selection+='\n'
369  valIndex = 0
370  for val in listOfValues:
371  selection+= ' ' + pair[0] + '[' + str(valIndex) + '] = ' + val + ';\n'
372  valIndex+=1
373  else:
374  selection+=' ' + pair[0] + ' = ' + pair[1] + ';\n'
375 
376  selection += ' }\n\n'
377  versionInt+=1
378  numberOfChanges = len(changedValuesDict)
379 
380 
381  baseHeader.write(protectedString+'\n\n')
382  baseHeader.write(publicString +'\n\n')
383  baseHeader.write(selection)
384  baseHeader.write(' };\n\n')
385  baseHeader.write(functionString+'\n\n')
386  baseHeader.write(dumpString+'\n\n')
387  baseHeader.write('\n};\n\n')
388  baseHeader.write('#endif //' + baseName.upper() + '_H')
389 
390 
391 now = date.today().strftime("%d/%m/%y")
392 
393 if __name__ == "__main__":
394  CreateFiles(now)
395 
396 
index
Definition: index.py:1
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
XMLtoHeader.count
count
Definition: XMLtoHeader.py:85
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
calibdata.exit
exit
Definition: calibdata.py:236
XMLtoHeader.CreateFiles
def CreateFiles(time)
Definition: XMLtoHeader.py:114
Trk::open
@ open
Definition: BinningType.h:40
str
Definition: BTagTrackIpAccessor.cxx:11
dbg::print
void print(std::FILE *stream, std::format_string< Args... > fmt, Args &&... args)
Definition: SGImplSvc.cxx:70
Trk::split
@ split
Definition: LayerMaterialProperties.h:38