ATLAS Offline Software
PhysicsAnalysis/D3PDMaker/D3PDMakerReader/python/Helpers.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
2 
3 #
4 # This module collects some functions used by the helper scripts of
5 # the package.
6 #
7 # @author Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>
8 
9 
17 def separateSources( filenames ):
18 
19  # Loop over the file names, and create the header and source lists:
20  header_files = []
21  source_files = []
22  for file in filenames:
23  # Skip the lingering linkdef and dictionary files:
24  if file.lower().find( "linkdef" ) != -1 or file.lower().find( "dict" ) != -1:
25  continue
26  # Find the header files:
27  if file.endswith( ".h" ) or file.endswith( ".icc" ):
28  header_files += [ file ]
29  pass
30  # Find the source files:
31  if file.endswith( ".cxx" ) or file.endswith( ".cpp" ) or file.endswith( ".C" ):
32  source_files += [ file ]
33  pass
34  pass
35 
36  # Return the result:
37  return ( header_files, source_files )
38 
39 
48 def dictionaryHeaders( filenames ):
49 
50  # Loop over the file names, and collect the "dictionary headers":
51  header_files = []
52  for file in filenames:
53  # Skip the lingering linkdef and dictionary files:
54  if file.lower().find( "linkdef" ) != -1 or file.lower().find( "dict" ) != -1:
55  continue
56  # Skip the D3PDReader template classes:
57  if ( file.find( "VarHandle.h" ) != -1 or
58  file.find( "VarHandle.icc" ) != -1 or
59  file.find( "VarProxy.h" ) != -1 or
60  file.find( "VarProxy.icc" ) != -1 ):
61  continue
62  # Find the header files:
63  if file.endswith( ".h" ):
64  header_files += [ file ]
65  pass
66  pass
67 
68  # Return the final list:
69  return header_files
70 
71 
80 def dictionaryClasses( filenames ):
81 
82  # Create a logger object first of all:
83  from AthenaCommon.Logging import logging
84  logger = logging.getLogger( "dictionaryClasses" )
85 
86  # Extract the class names from the header files:
87  classnames = [ "D3PDReader::VarHandleBase",
88  "D3PDReader::VarProxyBase",
89  "D3PDReader::VariableStats",
90  "D3PDReader::D3PDReadStats",
91  "map<TString,D3PDReader::VariableStats>",
92  "pair<TString,D3PDReader::VariableStats>",
93  "map<TString,D3PDReader::VarHandleBase*>",
94  "pair<TString,D3PDReader::VarHandleBase*>",
95  "D3PDReader::UserD3PDObjectElement",
96  "D3PDReader::UserD3PDObject" ]
97  for header in filenames:
98  # Open the header file:
99  hfile = open( header, "rU" )
100  if not hfile:
101  logger.error( "Couldn't open header file: %s", hfile )
102  return 255
103  for line in hfile:
104  import re
105  m1 = re.match( r".*ClassDef\‍( (\w+), 0 \‍)", line )
106  m2 = re.match( ".*(VarHandle< .* >).*", line )
107  m3 = re.match( ".*(VarProxy< .* >).*", line )
108  if m1:
109  if not ( "D3PDReader::" + m1.group( 1 ) ) in classnames:
110  logger.verbose( "Found class: " + m1.group( 1 ) )
111  classnames += [ "D3PDReader::" + m1.group( 1 ) ]
112  pass
113  continue
114  if m2:
115  if m2.group( 1 ) == "VarHandle< T >": continue
116  if not ( "D3PDReader::" + m2.group( 1 ) ) in classnames:
117  logger.verbose( "Found class: " + m2.group( 1 ) )
118  classnames += [ "D3PDReader::" + m2.group( 1 ) ]
119  pass
120  continue
121  if m3:
122  if m3.group( 1 ) == "VarProxy< T >": continue
123  if not ( "D3PDReader::" + m3.group( 1 ) ) in classnames:
124  logger.verbose( "Found class: " + m3.group( 1 ) )
125  classnames += [ "D3PDReader::" + m3.group( 1 ) ]
126  pass
127  continue
128  pass
129  pass
130 
131  # Now "clean up" these class names a little, so that ROOT would
132  # like them better:
133  import re
134  finalnames = []
135  for cname in classnames:
136  # First, let's remove all mentions of the std namespace:
137  cname = re.sub( r"std::", "", cname )
138  # Now remove all the whitespaces:
139  cname = re.sub( r"\s", "", cname )
140  # Remove the allocator class names:
141  cname = re.sub( r",allocator<\w*>", "", cname )
142  cname = re.sub( r",allocator<\w*<\w*>>", "", cname )
143  cname = re.sub( r",allocator<\w*<\w*<\w*>>>", "", cname )
144  # Make sure whitespaces are re-inserted into the unsigned primitive
145  # names:
146  cname = re.sub( r"unsigned", "unsigned ", cname )
147  # Also take care of adding back the needed whitespace before the
148  # "long" modifier. But don't add a whitespace after the last long in
149  # the name. For instance, "longlong" should become "long long" and not
150  # "long long ".
151  cname = re.sub( r"long(?!>)", "long ", cname )
152  # Finally, make sure that there is a space between the > operators:
153  while cname != re.sub( r">>", "> >", cname ):
154  cname = re.sub( r">>", "> >", cname )
155  pass
156  finalnames += [ cname ]
157  pass
158 
159  return finalnames
160 
161 
172 def writeLinkDefFile( filename, classnames, headers = [] ):
173 
174  # Create a logger object first of all:
175  from AthenaCommon.Logging import logging
176  logger = logging.getLogger( "writeLinkDefFile" )
177 
178  # Open the linkdef file:
179  linkdef = open( filename, "w" )
180  if not linkdef:
181  logger.error( "Couldn't open %s for writing!", filename )
182  return 255
183  else:
184  logger.info( "Writing linkdef file to: %s", filename )
185  pass
186 
187  # Write the file's header:
188  linkdef.write( "// Dear emacs, this is -*- c++ -*-\n" )
189  linkdef.write( "// $Id: Helpers.py 600807 2014-06-08 15:26:51Z krasznaa $\n" )
190  linkdef.write( "#ifndef D3PDREADER_LINKDEF_H\n" )
191  linkdef.write( "#define D3PDREADER_LINKDEF_H\n\n" )
192 
193  # Write the required includes:
194  for header in headers:
195  linkdef.write( "#include \"%s\"\n" % header )
196  pass
197 
198  # Write the rest of the constant part:
199  linkdef.write( "\n#ifdef __CINT__\n\n" )
200  linkdef.write( "#pragma link off all globals;\n" )
201  linkdef.write( "#pragma link off all classes;\n" )
202  linkdef.write( "#pragma link off all functions;\n\n" )
203  linkdef.write( "#pragma link C++ nestedclass;\n\n" )
204 
205  # Write which files to generate a dictionary for:
206  for classname in classnames:
207  linkdef.write( "#pragma link C++ class %s+;\n" % classname )
208  pass
209 
210  # Write which template functions to generate a dictionary for:
211  linkdef.write( "\n" )
212  linkdef.write( "// You can disable the remaining lines if you don't\n" )
213  linkdef.write( "// plan to use the library in CINT or PyROOT.\n" )
214  functions = [ "D3PDReader::UserD3PDObject::DeclareVariable<bool>",
215  "D3PDReader::UserD3PDObject::DeclareVariable<short>",
216  "D3PDReader::UserD3PDObject::DeclareVariable<unsigned short>",
217  "D3PDReader::UserD3PDObject::DeclareVariable<int>",
218  "D3PDReader::UserD3PDObject::DeclareVariable<unsigned int>",
219  "D3PDReader::UserD3PDObject::DeclareVariable<long long>",
220  "D3PDReader::UserD3PDObject::DeclareVariable<unsigned long long>",
221  "D3PDReader::UserD3PDObject::DeclareVariable<float>",
222  "D3PDReader::UserD3PDObject::DeclareVariable<double>",
223 # "D3PDReader::UserD3PDObject::DeclareVariable<vector<short>* >",
224 # "D3PDReader::UserD3PDObject::DeclareVariable<vector<unsigned short>* >",
225 # "D3PDReader::UserD3PDObject::DeclareVariable<vector<int>* >",
226 # "D3PDReader::UserD3PDObject::DeclareVariable<vector<unsigned int>* >",
227 # "D3PDReader::UserD3PDObject::DeclareVariable<vector<long long>* >",
228 # "D3PDReader::UserD3PDObject::DeclareVariable<vector<unsigned long long>* >",
229 # "D3PDReader::UserD3PDObject::DeclareVariable<vector<float>* >",
230 # "D3PDReader::UserD3PDObject::DeclareVariable<vector<double>* >",
231  "D3PDReader::UserD3PDObject::Variable<bool>",
232  "D3PDReader::UserD3PDObject::Variable<short>",
233  "D3PDReader::UserD3PDObject::Variable<unsigned short>",
234  "D3PDReader::UserD3PDObject::Variable<int>",
235  "D3PDReader::UserD3PDObject::Variable<unsigned int>",
236  "D3PDReader::UserD3PDObject::Variable<long long>",
237  "D3PDReader::UserD3PDObject::Variable<unsigned long long>",
238  "D3PDReader::UserD3PDObject::Variable<float>",
239  "D3PDReader::UserD3PDObject::Variable<double>",
240 # "D3PDReader::UserD3PDObject::Variable<vector<short>* >",
241 # "D3PDReader::UserD3PDObject::Variable<vector<unsigned short>* >",
242 # "D3PDReader::UserD3PDObject::Variable<vector<int>* >",
243 # "D3PDReader::UserD3PDObject::Variable<vector<unsigned int>* >",
244 # "D3PDReader::UserD3PDObject::Variable<vector<long long>* >",
245 # "D3PDReader::UserD3PDObject::Variable<vector<unsigned long long>* >",
246 # "D3PDReader::UserD3PDObject::Variable<vector<float>* >",
247 # "D3PDReader::UserD3PDObject::Variable<vector<double>* >",
248  "D3PDReader::UserD3PDObjectElement::Variable<short>",
249  "D3PDReader::UserD3PDObjectElement::Variable<unsigned short>",
250  "D3PDReader::UserD3PDObjectElement::Variable<int>",
251  "D3PDReader::UserD3PDObjectElement::Variable<unsigned int>",
252  "D3PDReader::UserD3PDObjectElement::Variable<long long>",
253  "D3PDReader::UserD3PDObjectElement::Variable<unsigned long long>",
254  "D3PDReader::UserD3PDObjectElement::Variable<float>",
255  "D3PDReader::UserD3PDObjectElement::Variable<double>" ]
256  for function in functions:
257  linkdef.write( "#pragma link C++ function %s;\n" % function )
258  pass
259 
260  # Close the file:
261  linkdef.write( "\n" )
262  linkdef.write( "#endif // __CINT__\n" )
263  linkdef.write( "#endif // D3PDREADER_LINKDEF_H\n" )
264  linkdef.close()
265 
266  # Signal that the function was successful:
267  return 0
268 
269 
279 def makeRootCorePackageSkeleton( directory, name ):
280 
281  # Create a logger object first of all:
282  from AthenaCommon.Logging import logging
283  logger = logging.getLogger( "makeRootCorePackageSkeleton" )
284 
285  # Check whether the output directory exists:
286  import os.path
287  if not os.path.exists( directory ):
288  logger.error( "The output directory (%s) doesn't exist!", directory )
289  return 255
290 
291  # Check that the package's directory doesn't exist yet:
292  if os.path.exists( directory + "/" + name ):
293  logger.error( "The directory for the package (%s/%s) already exists!", directory, name )
294  return 255
295 
296  # Create the directory structure:
297  import os
298  os.mkdir( directory + "/" + name, 0o755 )
299  os.mkdir( directory + "/" + name + "/" + name, 0o755 )
300  os.mkdir( directory + "/" + name + "/Root", 0o755 )
301  os.mkdir( directory + "/" + name + "/cmt", 0o755 )
302 
303  # Create the RootCore Makefile:
304  makefile = open( directory + "/" + name + "/cmt/Makefile.RootCore", "w" )
305  makefile.write( "# $Id: Helpers.py 600807 2014-06-08 15:26:51Z krasznaa $\n\n" )
306  makefile.write( "PACKAGE = %s\n" % name )
307  makefile.write( "PACKAGE_PRELOAD = Tree\n" )
308  makefile.write( "# Add the option -DACTIVATE_BRANCHES if your analysis framework\n" )
309  makefile.write( "# disables all branches by default.\n" )
310  makefile.write( "# Remove the COLLECT_D3PD_READING_STATISTICS option to gain a bit\n" )
311  makefile.write( "# of performance...\n" )
312  makefile.write( "PACKAGE_CXXFLAGS = -DCOLLECT_D3PD_READING_STATISTICS\n" )
313  makefile.write( "PACKAGE_LDFLAGS =\n" )
314  makefile.write( "PACKAGE_DEP =\n" )
315  makefile.write( "PACKAGE_PEDANTIC = 1\n" )
316  makefile.write( "PACKAGE_NOOPT = dict\n\n" )
317  makefile.write( "include $(ROOTCOREDIR)/Makefile-common\n" )
318  makefile.close()
319 
320  # Create the RootCore requirements file:
321  requirements = open( directory + "/" + name + "/cmt/requirements", "w" )
322  requirements.write( "package %s\n\n" % name )
323  requirements.write( "use AtlasPolicy AtlasPolicy-*\n" )
324  requirements.write( "use AtlasROOT AtlasROOT-* External\n\n" )
325  requirements.write( "library %s ../Root/*.cxx\n" % name )
326  requirements.write( "apply_pattern installed_library\n\n" )
327  requirements.write( "apply_pattern have_root_headers root_headers=\"*.h " \
328  "../Root/LinkDef.h\" headers_lib=%s\n" % name )
329  requirements.close()
330 
331  # Signal that the function was successful:
332  return 0
333 
334 
345 def makeSFramePackageSkeleton( directory, name ):
346 
347  # Create a logger object first of all:
348  from AthenaCommon.Logging import logging
349  logger = logging.getLogger( "makeSFramePackageSkeleton" )
350 
351  # Check whether the output directory exists:
352  import os.path
353  if not os.path.exists( directory ):
354  logger.error( "The output directory (%s) doesn't exist!", directory )
355  return 255
356 
357  # Check that the package's directory doesn't exist yet:
358  if os.path.exists( directory + "/" + name ):
359  logger.error( "The directory for the package (%s/%s) already exists!", directory, name )
360  return 255
361 
362  # Create the directory structure:
363  import os
364  os.mkdir( directory + "/" + name, 0o755 )
365  os.mkdir( directory + "/" + name + "/include", 0o755 )
366  os.mkdir( directory + "/" + name + "/src", 0o755 )
367  os.mkdir( directory + "/" + name + "/proof", 0o755 )
368 
369  # Create the SFrame Makefile:
370  makefile = open( directory + "/" + name + "/Makefile", "w" )
371  makefile.write( "# $Id: Helpers.py 600807 2014-06-08 15:26:51Z krasznaa $\n\n" )
372  makefile.write( "# Package information\n" )
373  makefile.write( "LIBRARY = %s\n" % name )
374  makefile.write( "OBJDIR = obj\n" )
375  makefile.write( "DEPDIR = $(OBJDIR)/dep\n" )
376  makefile.write( "SRCDIR = src\n" )
377  makefile.write( "INCDIR = include\n\n" )
378  makefile.write( "# Enable collecting D3PD reading statistics\n" )
379  makefile.write( "INCLUDES += -DCOLLECT_D3PD_READING_STATISTICS\n\n" )
380  makefile.write( "# Include the generic compilation rules\n" )
381  makefile.write( "include $(SFRAME_DIR)/Makefile.common\n" )
382  makefile.close()
383 
384  # Create the PROOF related files:
385  setup = open( directory + "/" + name + "/proof/SETUP.C", "w" )
386  setup.write( "// $Id: Helpers.py 600807 2014-06-08 15:26:51Z krasznaa $\n\n" )
387  setup.write( "int SETUP() {\n\n" )
388  setup.write( " if( gSystem->Load( \"libTree\" ) == -1 ) return -1;\n" )
389  setup.write( " if( gSystem->Load( \"lib%s\" ) == -1 ) return -1;\n\n" % name )
390  setup.write( " return 0;\n" )
391  setup.write( "}\n" )
392  setup.close()
393  # Notice that BUILD.sh has to be executable:
394  build = open( directory + "/" + name + "/proof/BUILD.sh", "w" )
395  build.write( "# $Id: Helpers.py 600807 2014-06-08 15:26:51Z krasznaa $\n\n" )
396  build.write( "if [ \"$1\" = \"clean\" ]; then\n" )
397  build.write( " make distclean\n" )
398  build.write( " exit 0\n" )
399  build.write( "fi\n\n" )
400  build.write( "make default\n" )
401  build.close()
402  os.chmod( directory + "/" + name + "/proof/BUILD.sh", 0o755 )
403 
404  # Signal that the function was successful:
405  return 0
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
python.Helpers.makeRootCorePackageSkeleton
def makeRootCorePackageSkeleton(directory, name)
Create the directory structure for a RootCore package.
Definition: PhysicsAnalysis/D3PDMaker/D3PDMakerReader/python/Helpers.py:279
python.Helpers.separateSources
def separateSources(filenames)
Separate the source and header files based on their names.
Definition: PhysicsAnalysis/D3PDMaker/D3PDMakerReader/python/Helpers.py:17
python.Helpers.dictionaryClasses
def dictionaryClasses(filenames)
Function collecting the class names to create a dictionary for.
Definition: PhysicsAnalysis/D3PDMaker/D3PDMakerReader/python/Helpers.py:80
python.Helpers.writeLinkDefFile
def writeLinkDefFile(filename, classnames, headers=[])
Function writing a LinkDef file.
Definition: PhysicsAnalysis/D3PDMaker/D3PDMakerReader/python/Helpers.py:172
Trk::open
@ open
Definition: BinningType.h:40
python.Helpers.makeSFramePackageSkeleton
def makeSFramePackageSkeleton(directory, name)
Create an SFrame package skeleton.
Definition: PhysicsAnalysis/D3PDMaker/D3PDMakerReader/python/Helpers.py:345
python.Helpers.dictionaryHeaders
def dictionaryHeaders(filenames)
Find the headers needed for dictionary generation.
Definition: PhysicsAnalysis/D3PDMaker/D3PDMakerReader/python/Helpers.py:48