-
Anton Piccardo-Selg authoredAnton Piccardo-Selg authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
generate_mdevent_declarations.py 9.16 KiB
""" Simple script that generates references to all
needed MDEvent<X>/MDLeanEvent<X> instantiations. """
import sys
import os
import time
import datetime
import re
# List of every possible MDEvent or MDLeanEvent types.
mdevent_types = ["MDLeanEvent", "MDEvent"]
header = """/* Code below Auto-generated by '%s'
* on %s
*
* DO NOT EDIT!
*/
""" % (os.path.basename(__file__), datetime.datetime.now())
footer = """
/* CODE ABOWE WAS AUTO-GENERATED BY %s - DO NOT EDIT! */
""" % (os.path.basename(__file__))
#============================================================================================================
#============================================================================================================
#============================================================================================================
#============================================================================================================
def build_macro(padding,min_dimension=1, max_dimensions=4,const=""):
""" Return the macro code CALL_MDEVENT_FUNCTION
Parameter:
min_dimension :: to avoid compiler warnings, limit to dimensions higher than this
mad_dimension :: by default, maximal numner of dimesnions to be generated
const :: set to "const " to make a const equivalent
"""
# for the calling function macro
macro_top = """
/** Macro that makes it possible to call a templated method for
* a MDEventWorkspace using a IMDEventWorkspace_sptr as the input.
*
* @param funcname :: name of the function that will be called.
* @param workspace :: IMDEventWorkspace_sptr input workspace.
*/
#define %sCALL_MDEVENT_FUNCTION%s(funcname, workspace) \\
{ \\
"""
macro = """%s%sMDEventWorkspace<%s, %d>::sptr %s = boost::dynamic_pointer_cast<%sMDEventWorkspace<%s, %d> >(workspace); \\
if (%s) funcname<%s, %d>(%s); \\
"""
suffix = ""
prefix = ""
if (min_dimension > 1): suffix = "%d" % min_dimension
if const != "": prefix = "CONST_"
s = macro_top % (prefix, suffix);
for mdevent_type in mdevent_types:
for nd in xrange(1,max_dimensions+1):
if (nd >= min_dimension):
eventType = "%s<%d>" % (mdevent_type, nd)
varname = "MDEW_%s_%d" % (mdevent_type.upper(),nd)
if const != "":
varname = "CONST_" + varname
s += macro % (padding,const, eventType,nd, varname, const, eventType,nd, varname, eventType,nd, varname)
s += "} \n \n \n"
return s.split("\n")
#======================================================================================
def get_padding(line):
"""Return a string with the spaces padding the start of the given line."""
out = ""
for c in line:
if c == " ":
out += " "
else:
break
return out
#======================================================================================
def find_line_number(lines, pattern, startat=0):
"""Look line-by-line in lines[] for a line that starts with pattern. Return
the line number in source where the line was found, and the padding (in spaces) before it"""
padding = ""
searcher = re.compile(pattern);
for n in xrange(startat, len(lines)):
found = searcher.search(lines[n]);
if found :
# How much padding?
padding = get_padding(lines[n])
return (n, padding)
return (None, None)
#======================================================================================
def find_num_dim(lines):
"""Look up through header file and the string which identifies how many dimensions have to be instantiated
"""
searcher = re.compile(r'(?<=MAX_MD_DIMENSIONS_NUM)(\s*\=\s*)\d+');
for i in xrange(len(lines)) :
found = searcher.search(lines[i]);
if found :
rez = found.group()
return re.search('\d',rez).group()
raise IOError," can not find the string which defines the number of dimensions to process "
def parse_file(file_name,start_marker,end_marker) :
"""Read the file and separate it into three parts with the part between input markers to be generated and two others left unchanged.
@param -- file_name -- full file name to open
@param -- start_marker -- the marker which indicate first line of autogenerated file
@param -- end_marger -- the margker which indicate last line of autogenerated file
@return padding -- the number of spaces to insert in front of autogenerated lines
@return lines_before -- list of lines before autogenerated one (including start_marker)
@return lines_after -- list of lines after autogenerated one (including end_marker)
"""
# First, open the header and read all the lines
f = open(file_name, 'r')
s = f.read();
lines = s.split("\n")
(n1, padding) = find_line_number(lines, start_marker, startat=0)
(n2, padding_ignored) = find_line_number(lines,end_marker, startat=n1)
print "Lines for autogenerated code: ",n1,n2
if n1 is None or n2 is None:
raise Exception("Could not find the marker in the "+file_name+" file.")
lines_before = lines[:n1+1]
lines_after = lines[n2:]
f.close()
return (padding,lines_before,lines_after)
#============================================================================================================
#============================================================================================================
#============================================================================================================
def generate():
print "Generating MDEventFactory"
# Classes that have a .cpp file (and will get an Include line)
classes_cpp = ["MDBoxBase","MDBox", "MDEventWorkspace", "MDGridBox", "MDBin", "MDBoxIterator"]
# All of the classes to instantiate
classes = classes_cpp + mdevent_types
padding,lines,lines_after=parse_file("../inc/MantidDataObjects/MDEventFactory.h",
"//### BEGIN AUTO-GENERATED CODE",
"//### END AUTO-GENERATED CODE");
nDim = int(find_num_dim(lines));
print " numDimensions to be generated: ",nDim
# List of the dimensions to instantiate
dimensions = range(1,nDim+1);
header_lines = map(lambda x : padding+x,header.split("\n"));
footer_lines = map(lambda x : padding+x,footer.split("\n"));
lines +=header_lines;
# ========== Start the header file =============
# Make the macro then pad it into the list of lines
macro_lines = build_macro(padding,1,nDim)+build_macro(padding,3,nDim)+build_macro(padding,1,nDim,"const ");
# add padding to macro-generated lines
lines += macro_lines;
# Typedefs for MDEventWorkspace
lines.append("\n");
classes = ["MDBox", "MDBoxBase", "MDGridBox", "MDEventWorkspace", "MDBin"]
for c in classes:
lines.append("\n%s// ------------- Typedefs for %s ------------------\n" % (padding, c));
mdevent_type = "MDLeanEvent"
for nd in dimensions:
lines.append("%s/// Typedef for a %s with %d dimension%s " % (padding,c, nd, ['','s'][nd>1]) )
lines.append("%s typedef %s<%s<%d>, %d> %s%dLean;" % (padding,c, mdevent_type, nd, nd, c, nd) )
mdevent_type = "MDEvent"
for nd in dimensions:
lines.append("%s/// Typedef for a %s with %d dimension%s " % (padding,c, nd, ['','s'][nd>1]) )
lines.append("%stypedef %s<%s<%d>, %d> %s%d;" % (padding,c, mdevent_type, nd, nd, c, nd) )
lines.append("\n");
lines += footer_lines + lines_after
f = open("../inc/MantidDataObjects/MDEventFactory.h", 'w')
for line in lines:
f.write(line + "\n")
f.close()
# =========== Do the Source File ===========
padding,lines,lines_after=parse_file("./MDEventFactory.cpp",
"//### BEGIN AUTO-GENERATED CODE",
"//### END AUTO-GENERATED CODE");
header_lines = map(lambda x : padding+x,header.split("\n"));
footer_lines = map(lambda x : padding+x,footer.split("\n"));
lines += header_lines
## MDEvent and MDLeanEvent type (just one template arg)
for c in mdevent_types:
lines.append("%s// Instantiations for %s" % (padding,c))
for nd in dimensions:
lines.append("%s template class DLLExport %s<%d>;" % (padding,c, nd) )
# Classes with MDLeanEvent<x>,x
for c in classes_cpp:
lines.append("%s// Instantiations for %s" %(padding, c) )
for mdevent_type in mdevent_types:
for nd in dimensions:
lines.append("%s template class DLLExport %s<%s<%d>, %d>;" % (padding,c, mdevent_type, nd, nd) )
lines.append("\n ")
lines += footer_lines+lines_after
f = open("./MDEventFactory.cpp", 'w')
for line in lines:
f.write(line+"\n")
f.close()
# Post message about updating the id strings in the python layer to
# understand the new structure
print
print "The available IDs on the templated MDEventWorkspace classes may have changed."
print "Please update the casting IDs in PythonInterface/mantid/api/IMDEventWorkspace accordingly"
if __name__=="__main__":
generate()