Skip to content
Snippets Groups Projects
  • Wuttke, Joachim's avatar
    c656f00e
    Most FormFactor classes now delegating parameter registration to INode. · c656f00e
    Wuttke, Joachim authored
    <code>
    
    import edtools, re, sys
    
    nodeList = '''\
    FormFactorAnisoPyramid ./Core/HardParticle/FormFactorAnisoPyramid
    FormFactorBox ./Core/HardParticle/FormFactorBox
    FormFactorCantellatedCube ./Core/HardParticle/FormFactorCantellatedCube
    FormFactorCone6 ./Core/HardParticle/FormFactorCone6
    FormFactorCone ./Core/HardParticle/FormFactorCone
    FormFactorCuboctahedron ./Core/HardParticle/FormFactorCuboctahedron
    FormFactorCylinder ./Core/HardParticle/FormFactorCylinder
    FormFactorDodecahedron ./Core/HardParticle/FormFactorDodecahedron
    FormFactorDot ./Core/HardParticle/FormFactorDot
    FormFactorEllipsoidalCylinder ./Core/HardParticle/FormFactorEllipsoidalCylinder
    FormFactorFullSphere ./Core/HardParticle/FormFactorFullSphere
    FormFactorFullSpheroid ./Core/HardParticle/FormFactorFullSpheroid
    FormFactorHollowSphere ./Core/HardParticle/FormFactorHollowSphere
    FormFactorGaussSphere ./Core/SoftParticle/FormFactorGauss
    FormFactorHemiEllipsoid ./Core/HardParticle/FormFactorHemiEllipsoid
    FormFactorIcosahedron ./Core/HardParticle/FormFactorIcosahedron
    FormFactorLongBoxGauss ./Core/HardParticle/FormFactorLongBoxGauss
    FormFactorLongBoxLorentz ./Core/HardParticle/FormFactorLongBoxLorentz
    FormFactorPrism3 ./Core/HardParticle/FormFactorPrism3
    FormFactorPrism6 ./Core/HardParticle/FormFactorPrism6
    FormFactorPyramid ./Core/HardParticle/FormFactorPyramid
    FormFactorSphereGaussianRadius ./Core/SoftParticle/FormFactorSphereGaussianRadius
    FormFactorSphereLogNormalRadius ./Core/SoftParticle/FormFactorSphereLogNormalRadius
    FormFactorTetrahedron ./Core/HardParticle/FormFactorTetrahedron
    FormFactorTriangle ./Core/HardParticle/FormFactorTriangle
    FormFactorTruncatedCube ./Core/HardParticle/FormFactorTruncatedCube
    FormFactorTruncatedSphere ./Core/HardParticle/FormFactorTruncatedSphere
    FormFactorTruncatedSpheroid ./Core/HardParticle/FormFactorTruncatedSpheroid
    '''
    
    def get_and_check_ctor_args(t, vars):
        avars = []
        if t!="":
            args = re.split(',\s+', t)
            for a in args:
                mm = re.search(r'double (\w+)( = \S+?)?', a)
                if not mm:
                    raise Exception("Unexpected argument '%s' in constructor" % a)
                avars.append(mm.group(1))
        ndiff = len(avars) - len(vars)
        if ndiff<0:
            raise Exception("Not enough constructor args")
        for i in range(len(vars)):
            if avars[ndiff+i] != vars[i]:
                raise Exception("Argument '%s' does not match variable '%s'" %
                                (avars[ndiff+i], vars[i]))
        return avars
    
    def refactor_class(node, fnbase):
        fnc = fnbase+".cpp"
        fnh = fnbase+".h"
    
        with open(fnh, 'r') as f:
            th = f.read()
    
        with open(fnc, 'r') as f:
            tc = f.read()
    
        # class declaration -> find base class
        m = re.search(r'\nclass (BA_CORE_API_ )?%s\s+(final\s+)?:\s+public\s+(\w+)' % node, th)
        if not m:
            raise Exception(node+": base class not found")
        baseClass = m.group(3)
    
        print("\n"+fnbase+": "+node+" < "+baseClass)
    
        # find constructor implementation
        ctors = []
        for m in re.finditer(r'^%s::%s(.*?^){(.*?)^}' % (node, node), tc, re.M | re.DOTALL):
            inits = m.group(1)
            if re.search(node, inits):
                continue # it's a delegating c'tor, ignorable for our purpose
            ctors.append(m.group(2))
        if len(ctors)==0:
            raise Exception("Constructor for "+node+" not found in "+fnc)
        if len(ctors)>1:
            raise Exception("Several constructors for "+node+" found in "+fnc)
        blocks = re.split(r';', ctors[0])
    
        names = []
        vars = []
        units = []
        minis = []
        maxis = []
        cname = '"NamelessClass"'
        for cmd in blocks:
            m = re.search(r'setName\((".*?")\)', cmd)
            if m:
                cname = m.group(1)
                continue
        for cmd in blocks:
            m = re.search(r'registerParameter(.*)', cmd)
            if not m:
                continue
            txt = m.group(1)
            m = re.match(r'\((".*?"), &m_(\w+)\)(\.setUnit\((".*?")\))?(\.set\w+\(.*?\))?$', txt)
            if not m:
                print(node, "-->nonstandard args-->", txt)
                continue
            names.append(m.group(1))
            vars.append(m.group(2))
            units.append(m.group(4) or '""')
            if not m.group(5):
                minis.append("-INF")
                maxis.append("+INF")
            else:
                limits = m.group(5)
                if re.match(r'\.set(Nonnegative|Postive)', limits):
                    minis.append("0")
                    maxis.append("+INF")
                else:
                    mm = re.match(r'.setLimited\((.*?),\s+(.*?)\)', limits)
                    minis.append(mm.group(1))
                    maxis.append(mm.group(2))
        print(node, "  ", cname, names, vars, units, minis, maxis)
    
        def ed_h(fn, t):
            ti = t
            # add P-based c'tor
            pattern = r'(\n    %s\(' % node
            pattern += r'((double\s+\w+)?'
            pattern += r'(,\s+double\s+\w+)*)'
            pattern += r'(,\s+bool position_at_center = false)?'
            pattern += r'(,\s+size_t n_samples)?'
            pattern += r'\);\n)'
            m = re.search(pattern, t, re.S)
            if not m:
                raise Exception("Constructor not matched")
            ctor = m.group(1)
            avars = get_and_check_ctor_args(m.group(2), vars)
    
            arg_pac = edtools.found_or_empty(r', bool position_at_center = false', ctor)
            arg_nsa = ""
            if re.search(r', size_t n_samples', ctor):
                arg_nsa = ', size_t n_samples = 0'
            outpat = r'\n    %s(const std::vector<double> P%s%s);\1' % (node, arg_pac, arg_nsa)
            t = re.sub(pattern, outpat, t, 0, re.S)
    
            # declare references;
            for var in vars:
                t = re.sub(r'(\n    )(double)( m_%s;)' % var, r'\1const \2&\3', t)
            return t
    
        edtools.ed_file(ed_h, fnh)
    
        def ed_c(fn, t):
            # add P-based c'tor
            pattern = r'\n%s::%s\(' % (node, node)
            pattern += r'((.*?)'
            pattern += r'((,\s+bool position_at_center)?'
            pattern += r'(,\s+size_t n_samples)?))'
            pattern += r'\)(.*?)\n({.*?\n})'
            m = re.search(pattern, t, re.S)
            if not m:
                print(pattern)
                raise Exception("c'tor not found in cpp file")
            allargs = m.group(1)
            avars = get_and_check_ctor_args(m.group(2), vars)
            optargs = m.group(3)
            have_pac = (m.group(4) is not None)
            have_nsa = m.group(5) is not None
            block = m.group(7)
    
            for i in range(len(vars)):
                block = re.sub(r'.*registerPar.*\n', '', block)
            block = re.sub(r'.*setName\(.*\n', '', block)
    
            # new c'tor with old implementation block
            outpat = r'\n%s::%s(const std::vector<double> P' % (node, node)
            if have_pac:
                outpat += r', bool position_at_center'
            if have_nsa:
                outpat += r', size_t n_samples'
            outpat += r')\n : %s({%s, %s, {' % (baseClass, cname, '"class_tooltip"')
            outpat += ', '.join([r'{%s, %s, %s, %s, %s, 0}' %
                                 (names[i], units[i], '"para_tooltip"',
                                  minis[i], maxis[i]) for i in range(len(names))])
            outpat += r'}}, P)\n'
            for i in range(len(vars)):
                outpat += r' , m_%s(m_P[%i])\n' % (vars[i], i)
            if have_pac:
                outpat += r' , m_position_at_center(position_at_center)\n'
            if have_nsa:
                outpat += r' , m_n_samples(n_samples)\n'
            outpat += edtools.text2re(block)
            # old c'tor refers to new c'tor
            outpat += r'\n\n%s::%s(' % (node, node)
            outpat += r'%s)\n : %s(std::vector<double>{%s}' % (allargs, node, ', '.join(avars))
            if have_pac:
                outpat += r', position_at_center'
            if have_nsa:
                outpat += r', n_samples'
            outpat += r')\n{}\n'
    
            t = re.sub(pattern, outpat, t, 0, re.S)
    
            if not re.search(r'registerPar', t):
                t = re.sub(r'#include "Core/Parametrization/ParameterPool.h"\n', '', t)
                t = re.sub(r'#include "Core/Parametrization/RealParameter.h"\n', '', t)
    
            return t
    
        edtools.ed_file(ed_c, fnc)
    
    nsuccess = 0
    nfailure = 0
    nodeEntries = re.split(r'\n', nodeList.rstrip())
    for entry in nodeEntries:
        node, fnbase = re.split(' ', entry)
        try:
            refactor_class(node, fnbase)
            print("SUCCESS "+node)
            nsuccess += 1
        except Exception as e:
            print("FAILURE "+node+": "+str(e))
            nfailure += 1
    print("%i/%i class conversions failed" % (nfailure, nsuccess+nfailure))
    </code>
    c656f00e
    History
    Most FormFactor classes now delegating parameter registration to INode.
    Wuttke, Joachim authored
    <code>
    
    import edtools, re, sys
    
    nodeList = '''\
    FormFactorAnisoPyramid ./Core/HardParticle/FormFactorAnisoPyramid
    FormFactorBox ./Core/HardParticle/FormFactorBox
    FormFactorCantellatedCube ./Core/HardParticle/FormFactorCantellatedCube
    FormFactorCone6 ./Core/HardParticle/FormFactorCone6
    FormFactorCone ./Core/HardParticle/FormFactorCone
    FormFactorCuboctahedron ./Core/HardParticle/FormFactorCuboctahedron
    FormFactorCylinder ./Core/HardParticle/FormFactorCylinder
    FormFactorDodecahedron ./Core/HardParticle/FormFactorDodecahedron
    FormFactorDot ./Core/HardParticle/FormFactorDot
    FormFactorEllipsoidalCylinder ./Core/HardParticle/FormFactorEllipsoidalCylinder
    FormFactorFullSphere ./Core/HardParticle/FormFactorFullSphere
    FormFactorFullSpheroid ./Core/HardParticle/FormFactorFullSpheroid
    FormFactorHollowSphere ./Core/HardParticle/FormFactorHollowSphere
    FormFactorGaussSphere ./Core/SoftParticle/FormFactorGauss
    FormFactorHemiEllipsoid ./Core/HardParticle/FormFactorHemiEllipsoid
    FormFactorIcosahedron ./Core/HardParticle/FormFactorIcosahedron
    FormFactorLongBoxGauss ./Core/HardParticle/FormFactorLongBoxGauss
    FormFactorLongBoxLorentz ./Core/HardParticle/FormFactorLongBoxLorentz
    FormFactorPrism3 ./Core/HardParticle/FormFactorPrism3
    FormFactorPrism6 ./Core/HardParticle/FormFactorPrism6
    FormFactorPyramid ./Core/HardParticle/FormFactorPyramid
    FormFactorSphereGaussianRadius ./Core/SoftParticle/FormFactorSphereGaussianRadius
    FormFactorSphereLogNormalRadius ./Core/SoftParticle/FormFactorSphereLogNormalRadius
    FormFactorTetrahedron ./Core/HardParticle/FormFactorTetrahedron
    FormFactorTriangle ./Core/HardParticle/FormFactorTriangle
    FormFactorTruncatedCube ./Core/HardParticle/FormFactorTruncatedCube
    FormFactorTruncatedSphere ./Core/HardParticle/FormFactorTruncatedSphere
    FormFactorTruncatedSpheroid ./Core/HardParticle/FormFactorTruncatedSpheroid
    '''
    
    def get_and_check_ctor_args(t, vars):
        avars = []
        if t!="":
            args = re.split(',\s+', t)
            for a in args:
                mm = re.search(r'double (\w+)( = \S+?)?', a)
                if not mm:
                    raise Exception("Unexpected argument '%s' in constructor" % a)
                avars.append(mm.group(1))
        ndiff = len(avars) - len(vars)
        if ndiff<0:
            raise Exception("Not enough constructor args")
        for i in range(len(vars)):
            if avars[ndiff+i] != vars[i]:
                raise Exception("Argument '%s' does not match variable '%s'" %
                                (avars[ndiff+i], vars[i]))
        return avars
    
    def refactor_class(node, fnbase):
        fnc = fnbase+".cpp"
        fnh = fnbase+".h"
    
        with open(fnh, 'r') as f:
            th = f.read()
    
        with open(fnc, 'r') as f:
            tc = f.read()
    
        # class declaration -> find base class
        m = re.search(r'\nclass (BA_CORE_API_ )?%s\s+(final\s+)?:\s+public\s+(\w+)' % node, th)
        if not m:
            raise Exception(node+": base class not found")
        baseClass = m.group(3)
    
        print("\n"+fnbase+": "+node+" < "+baseClass)
    
        # find constructor implementation
        ctors = []
        for m in re.finditer(r'^%s::%s(.*?^){(.*?)^}' % (node, node), tc, re.M | re.DOTALL):
            inits = m.group(1)
            if re.search(node, inits):
                continue # it's a delegating c'tor, ignorable for our purpose
            ctors.append(m.group(2))
        if len(ctors)==0:
            raise Exception("Constructor for "+node+" not found in "+fnc)
        if len(ctors)>1:
            raise Exception("Several constructors for "+node+" found in "+fnc)
        blocks = re.split(r';', ctors[0])
    
        names = []
        vars = []
        units = []
        minis = []
        maxis = []
        cname = '"NamelessClass"'
        for cmd in blocks:
            m = re.search(r'setName\((".*?")\)', cmd)
            if m:
                cname = m.group(1)
                continue
        for cmd in blocks:
            m = re.search(r'registerParameter(.*)', cmd)
            if not m:
                continue
            txt = m.group(1)
            m = re.match(r'\((".*?"), &m_(\w+)\)(\.setUnit\((".*?")\))?(\.set\w+\(.*?\))?$', txt)
            if not m:
                print(node, "-->nonstandard args-->", txt)
                continue
            names.append(m.group(1))
            vars.append(m.group(2))
            units.append(m.group(4) or '""')
            if not m.group(5):
                minis.append("-INF")
                maxis.append("+INF")
            else:
                limits = m.group(5)
                if re.match(r'\.set(Nonnegative|Postive)', limits):
                    minis.append("0")
                    maxis.append("+INF")
                else:
                    mm = re.match(r'.setLimited\((.*?),\s+(.*?)\)', limits)
                    minis.append(mm.group(1))
                    maxis.append(mm.group(2))
        print(node, "  ", cname, names, vars, units, minis, maxis)
    
        def ed_h(fn, t):
            ti = t
            # add P-based c'tor
            pattern = r'(\n    %s\(' % node
            pattern += r'((double\s+\w+)?'
            pattern += r'(,\s+double\s+\w+)*)'
            pattern += r'(,\s+bool position_at_center = false)?'
            pattern += r'(,\s+size_t n_samples)?'
            pattern += r'\);\n)'
            m = re.search(pattern, t, re.S)
            if not m:
                raise Exception("Constructor not matched")
            ctor = m.group(1)
            avars = get_and_check_ctor_args(m.group(2), vars)
    
            arg_pac = edtools.found_or_empty(r', bool position_at_center = false', ctor)
            arg_nsa = ""
            if re.search(r', size_t n_samples', ctor):
                arg_nsa = ', size_t n_samples = 0'
            outpat = r'\n    %s(const std::vector<double> P%s%s);\1' % (node, arg_pac, arg_nsa)
            t = re.sub(pattern, outpat, t, 0, re.S)
    
            # declare references;
            for var in vars:
                t = re.sub(r'(\n    )(double)( m_%s;)' % var, r'\1const \2&\3', t)
            return t
    
        edtools.ed_file(ed_h, fnh)
    
        def ed_c(fn, t):
            # add P-based c'tor
            pattern = r'\n%s::%s\(' % (node, node)
            pattern += r'((.*?)'
            pattern += r'((,\s+bool position_at_center)?'
            pattern += r'(,\s+size_t n_samples)?))'
            pattern += r'\)(.*?)\n({.*?\n})'
            m = re.search(pattern, t, re.S)
            if not m:
                print(pattern)
                raise Exception("c'tor not found in cpp file")
            allargs = m.group(1)
            avars = get_and_check_ctor_args(m.group(2), vars)
            optargs = m.group(3)
            have_pac = (m.group(4) is not None)
            have_nsa = m.group(5) is not None
            block = m.group(7)
    
            for i in range(len(vars)):
                block = re.sub(r'.*registerPar.*\n', '', block)
            block = re.sub(r'.*setName\(.*\n', '', block)
    
            # new c'tor with old implementation block
            outpat = r'\n%s::%s(const std::vector<double> P' % (node, node)
            if have_pac:
                outpat += r', bool position_at_center'
            if have_nsa:
                outpat += r', size_t n_samples'
            outpat += r')\n : %s({%s, %s, {' % (baseClass, cname, '"class_tooltip"')
            outpat += ', '.join([r'{%s, %s, %s, %s, %s, 0}' %
                                 (names[i], units[i], '"para_tooltip"',
                                  minis[i], maxis[i]) for i in range(len(names))])
            outpat += r'}}, P)\n'
            for i in range(len(vars)):
                outpat += r' , m_%s(m_P[%i])\n' % (vars[i], i)
            if have_pac:
                outpat += r' , m_position_at_center(position_at_center)\n'
            if have_nsa:
                outpat += r' , m_n_samples(n_samples)\n'
            outpat += edtools.text2re(block)
            # old c'tor refers to new c'tor
            outpat += r'\n\n%s::%s(' % (node, node)
            outpat += r'%s)\n : %s(std::vector<double>{%s}' % (allargs, node, ', '.join(avars))
            if have_pac:
                outpat += r', position_at_center'
            if have_nsa:
                outpat += r', n_samples'
            outpat += r')\n{}\n'
    
            t = re.sub(pattern, outpat, t, 0, re.S)
    
            if not re.search(r'registerPar', t):
                t = re.sub(r'#include "Core/Parametrization/ParameterPool.h"\n', '', t)
                t = re.sub(r'#include "Core/Parametrization/RealParameter.h"\n', '', t)
    
            return t
    
        edtools.ed_file(ed_c, fnc)
    
    nsuccess = 0
    nfailure = 0
    nodeEntries = re.split(r'\n', nodeList.rstrip())
    for entry in nodeEntries:
        node, fnbase = re.split(' ', entry)
        try:
            refactor_class(node, fnbase)
            print("SUCCESS "+node)
            nsuccess += 1
        except Exception as e:
            print("FAILURE "+node+": "+str(e))
            nfailure += 1
    print("%i/%i class conversions failed" % (nfailure, nsuccess+nfailure))
    </code>