Ejemplo n.º 1
0
    def _generate_fun(self, name, specstr, resname, specnames, docodeinserts=False):
        """Generate string with Python code for function `name`"""

        fdef = self._fn_template.format(
            name=name,
            start=self._format_user_code(self.opts["start"]) if docodeinserts else "",
            spec=specstr,
            end=self._format_user_code(self.opts["end"]) if docodeinserts else "",
            result=makeParList(range(len(specnames)), resname),
        )
        return "\n".join([s for s in fdef.split("\n") if s]) + "\n"
Ejemplo n.º 2
0
    def _generate_fun(self, name, specstr, resname, specnames, docodeinserts=False):
        """Generate string with Python code for function `name`"""

        fdef = self._fn_template.format(
            name=name,
            start=self._format_user_code(self.opts['start']) if docodeinserts else '',
            spec=specstr,
            end=self._format_user_code(self.opts['end']) if docodeinserts else '',
            result=makeParList(range(len(specnames)), resname)
        )
        return '\n'.join([s for s in fdef.split('\n') if s]) + '\n'
Ejemplo n.º 3
0
    def _generate_fun(self, name, specstr, resname, specnames, docodeinserts=False):
        """Generate string with Python code for function `name`"""

        fdef = self._fn_template.format(
            name=name,
            start=self._format_user_code(self.opts['start']) if docodeinserts else '',
            spec=specstr,
            end=self._format_user_code(self.opts['end']) if docodeinserts else '',
            result=makeParList(range(len(specnames)), resname)
        )
        return '\n'.join([s for s in fdef.split('\n') if s]) + '\n'
Ejemplo n.º 4
0
    def _generate_fun(self,
                      name,
                      specstr,
                      resname,
                      specnames,
                      docodeinserts=False):
        """Generate string with Python code for function `name`"""

        fdef = self._fn_template.format(
            name=name,
            start=self._format_user_code(self.opts["start"])
            if docodeinserts else "",
            spec=specstr,
            end=self._format_user_code(self.opts["end"])
            if docodeinserts else "",
            result=makeParList(range(len(specnames)), resname),
        )
        return "\n".join([s for s in fdef.split("\n") if s]) + "\n"
Ejemplo n.º 5
0
 def generate_aux(self):
     auxnames = list(self.fspec._auxfnspecs.keys())
     # User aux fn interface
     uafi = {}
     # protectednames = auxnames + self.fspec._protected_mathnames + \
     #                  self.fspec._protected_randomnames + \
     #                  self.fspec._protected_scipynames + \
     #                  self.fspec._protected_specialfns + \
     #                  ['abs', 'and', 'or', 'not', 'True', 'False']
     auxfns = self.builtin_aux
     # the internal functions may be used by user-defined functions,
     # so need them to be accessible to processTokens when parsing
     self.fspec._pyauxfns = auxfns
     # add the user-defined function names for cross-referencing checks
     # (without their definitions)
     for auxname in auxnames:
         self.fspec._pyauxfns[auxname] = None
     # don't process the built-in functions -> unique fns because
     # they are global definitions existing throughout the
     # namespace
     self.fspec._protected_auxnames.extend(["Jacobian", "Jacobian_pars"])
     # protected names are the names that must not be used for
     # user-specified auxiliary fn arguments
     protectednames = (
         self.fspec.pars
         + self.fspec.inputs
         + ["abs", "pow", "and", "or", "not", "True", "False"]
         + self.fspec._protected_auxnames
         + auxnames
         + self.fspec._protected_numpynames
         + self.fspec._protected_scipynames
         + self.fspec._protected_specialfns
         + self.fspec._protected_macronames
         + self.fspec._protected_mathnames
         + self.fspec._protected_randomnames
         + self.fspec._protected_reusenames
     )
     # checks for user-defined auxiliary fns
     # name map for fixing inter-auxfn references
     auxfn_namemap = {}
     specials_base = (
         self.fspec.pars
         + self.fspec._protected_auxnames
         + ["abs", "pow", "and", "or", "not", "True", "False"]
         + auxnames
         + self.fspec._protected_scipynames
         + self.fspec._protected_numpynames
         + self.fspec._protected_specialfns
         + self.fspec._protected_macronames
         + self.fspec._protected_mathnames
         + self.fspec._protected_randomnames
         + self.fspec._protected_reusenames
     )
     for auxname in auxnames:
         auxinfo = self.fspec._auxfnspecs[auxname]
         try:
             if len(auxinfo) != 2:
                 raise ValueError("auxinfo tuple must be of length 2")
         except TypeError:
             raise TypeError("fnspecs argument must contain pairs")
         # auxinfo[0] = tuple or list of parameter names
         # auxinfo[1] = string containing body of function definition
         assert isinstance(auxinfo[0], list), "aux function arguments " "must be given as a list"
         assert isinstance(auxinfo[1], six.string_types), (
             "aux function specification " "must be a string of the function code"
         )
         # Process Jacobian functions, etc., specially, if present
         if auxname == "Jacobian":
             if not compareList(auxinfo[0], ["t"] + self.fspec.vars):
                 print(["t"] + self.fspec.vars)
                 print("Auxinfo =" + str(auxinfo[0]))
                 raise ValueError("Invalid argument list given in Jacobian.")
             auxparlist = ["t", "x", "parsinps"]
             # special symbols to allow in parsing function body
             specials = ["t", "x"]
             auxstr = auxinfo[1]
             if any([pt in auxstr for pt in ("^", "**")]):
                 auxstr = convertPowers(auxstr, "pow")
             specvars = self.fspec.vars
             specvars.sort()
             specdict = {}.fromkeys(specvars)
             if len(specvars) == 1:
                 assert "[" not in auxstr, "'[' character invalid in Jacobian for 1D system"
                 assert "]" not in auxstr, "']' character invalid in Jacobian for 1D system"
                 specdict[specvars[0]] = auxstr
             else:
                 specdict = parseMatrixStrToDictStr(auxstr, specvars)
             reusestr, body_processed_dict = self._processReusedPy(
                 specvars, specdict, specials=specials + specials_base
             )
             body_processed = self._specStrParse(
                 specvars, body_processed_dict, "xjac", specials=specials + specials_base
             )
             auxstr_py = self._generate_fun("_auxfn_Jac", reusestr + body_processed, "xjac", specvars)
             # check Jacobian
             m = n = len(specvars)
             specdict_check = {}.fromkeys(specvars)
             for specname in specvars:
                 temp = body_processed_dict[specname]
                 specdict_check[specname] = count_sep(temp.replace("[", "").replace("]", "")) + 1
             body_processed = ""
             for row in range(m):
                 if specdict_check[specvars[row]] != n:
                     print("Row %i: " % m + specdict[specvars[row]])
                     print("Found length %i" % specdict_check[specvars[row]])
                     raise ValueError("Jacobian should be %sx%s" % (m, n))
         elif auxname == "Jacobian_pars":
             if not compareList(auxinfo[0], ["t"] + self.fspec.pars):
                 print(["t"] + self.fspec.pars)
                 print("Auxinfo =" + str(auxinfo[0]))
                 raise ValueError("Invalid argument list given in Jacobian.")
             auxparlist = ["t", "x", "parsinps"]
             # special symbols to allow in parsing function body
             specials = ["t", "x"]
             auxstr = auxinfo[1]
             if any([pt in auxstr for pt in ("^", "**")]):
                 auxstr = convertPowers(auxstr, "pow")
             specvars = self.fspec.pars
             specvars.sort()
             specdict = {}.fromkeys(self.fspec.vars)
             if len(specvars) == len(self.fspec.vars) == 1:
                 assert "[" not in auxstr, "'[' character invalid in Jacobian for 1D system"
                 assert "]" not in auxstr, "']' character invalid in Jacobian for 1D system"
                 specdict[specvars[0]] = auxstr
             else:
                 specdict = parseMatrixStrToDictStr(auxstr, self.fspec.vars)
             reusestr, body_processed_dict = self._processReusedPy(
                 self.fspec.vars, specdict, specials=specials + specials_base
             )
             body_processed = self._specStrParse(
                 self.fspec.vars, body_processed_dict, "pjac", specials=specials + specials_base
             )
             auxstr_py = self._generate_fun("_auxfn_Jac_p", reusestr + body_processed, "pjac", self.fspec.vars)
             # check Jacobian
             n = len(specvars)
             m = len(self.fspec.vars)
             specdict_check = {}.fromkeys(self.fspec.vars)
             for specname in self.fspec.vars:
                 temp = body_processed_dict[specname]
                 specdict_check[specname] = count_sep(temp.replace("[", "").replace("]", "")) + 1
             body_processed = ""
             for row in range(m):
                 try:
                     if specdict_check[self.fspec.vars[row]] != n:
                         print("Row %i: " % m + specdict[self.fspec.vars[row]])
                         print("Found length %i" % specdict_check[self.fspec.vars[row]])
                         raise ValueError("Jacobian w.r.t. pars should be %sx%s" % (m, n))
                 except IndexError:
                     print("\nFound:\n")
                     info(specdict)
                     raise ValueError("Jacobian w.r.t. pars should be %sx%s" % (m, n))
         elif auxname == "massMatrix":
             if not compareList(auxinfo[0], ["t"] + self.fspec.vars):
                 print(["t"] + self.fspec.vars)
                 print("Auxinfo =" + str(auxinfo[0]))
                 raise ValueError("Invalid argument list given in Mass Matrix.")
             auxparlist = ["t", "x", "parsinps"]
             # special symbols to allow in parsing function body
             specials = ["t", "x"]
             auxstr = auxinfo[1]
             if any([pt in auxstr for pt in ("^", "**")]):
                 auxstr = convertPowers(auxstr, "pow")
             specvars = self.fspec.vars
             specvars.sort()
             specdict = {}.fromkeys(specvars)
             if len(specvars) == 1:
                 assert "[" not in auxstr, "'[' character invalid in mass matrix for 1D system"
                 assert "]" not in auxstr, "']' character invalid in mass matrix for 1D system"
                 specdict[list(specvars.values())[0]] = auxstr
             else:
                 specdict = parseMatrixStrToDictStr(auxstr, specvars)
             reusestr, body_processed_dict = self._processReusedPy(
                 specvars, specdict, specials=specials + specials_base
             )
             body_processed = self._specStrParse(
                 specvars, body_processed_dict, "xmat", specials=specials + specials_base
             )
             auxstr_py = self._generate_fun("_auxfn_massMatrix", reusestr + body_processed, "xmat", specvars)
             # check matrix
             m = n = len(specvars)
             specdict_check = {}.fromkeys(specvars)
             for specname in specvars:
                 specdict_check[specname] = 1 + count_sep(
                     body_processed_dict[specname].replace("[", "").replace("]", "")
                 )
             body_processed = ""
             for row in range(m):
                 if specdict_check[specvars[row]] != n:
                     print("Row %i: " % m + specdict[specvars[row]])
                     print("Found length %i" % specdict_check[specvars[row]])
                     raise ValueError("Mass matrix should be %sx%s" % (m, n))
         else:
             user_parstr = makeParList(auxinfo[0])
             # `parsinps` is always added to allow reference to own
             # parameters
             if user_parstr == "":
                 # no arguments, user calls as fn()
                 auxparstr = "parsinps"
             else:
                 auxparstr = "parsinps, " + user_parstr
             auxstr_py = "def _auxfn_" + auxname + "(ds, " + auxparstr + "):\n"
             auxparlist = auxparstr.replace(" ", "").split(",")
             badparnames = intersect(auxparlist, remain(protectednames, auxnames))
             if badparnames != []:
                 print("Bad parameter names in auxiliary function %s: %r" % (auxname, badparnames))
                 # print(str(auxinfo[0]))
                 # print(str(auxparlist))
                 raise ValueError(
                     "Cannot use protected names (including"
                     " globally visible system parameters for auxiliary "
                     "function arguments"
                 )
             # special symbols to allow in parsing function body
             specials = auxparlist
             specials.remove("parsinps")
             illegalterms = remain(self.fspec.vars + self.fspec.auxvars, specials)
             auxstr = auxinfo[1]
             if any([pt in auxstr for pt in ("^", "**")]):
                 auxstr = convertPowers(auxstr, "pow")
             reusestr, body_processed_dict = self._processReusedPy(
                 [auxname], {auxname: auxstr}, specials=specials + specials_base, dovars=False, illegal=illegalterms
             )
             body_processed = self._specStrParse(
                 [auxname],
                 body_processed_dict,
                 specials=specials + specials_base,
                 dovars=False,
                 noreturndefs=True,
                 illegal=illegalterms,
             )
             auxstr_py += reusestr + _indentstr + "return " + body_processed
         # syntax validation done in makeUniqueFn
         try:
             auxfns[auxname] = makeUniqueFn(auxstr_py)
             # Note: this automatically updates self.fspec._pyauxfns too
         except Exception:
             print("Error in supplied auxiliary spec dictionary code")
             raise
         auxfn_namemap["ds." + auxname] = "ds." + auxfns[auxname][1]
         # prepare user-interface wrapper function (not method)
         if specials == [""] or specials == []:
             fn_args = ""
         else:
             fn_args = "," + ",".join(specials)
         fn_elts = [
             "def ",
             auxname,
             "(self",
             fn_args,
             ",__parsinps__=None):\n\t",
             "if __parsinps__ is None:\n\t\t",
             "__parsinps__=self.map_ixs(self.genref)\n\t",
             "return self.genref.",
             auxfns[auxname][1],
             "(__parsinps__",
             fn_args,
             ")\n",
         ]
         uafi[auxname] = "".join(fn_elts)
     # resolve inter-auxiliary function references
     for auxname, auxspec in auxfns.items():
         dummyQ = QuantSpec("dummy", auxspec[0], preserveSpace=True, treatMultiRefs=False)
         dummyQ.mapNames(auxfn_namemap)
         auxfns[auxname] = (dummyQ(), auxspec[1])
     self.fspec._user_auxfn_interface = uafi
     self.fspec._protected_auxnames.extend(auxnames)
     return auxfns
Ejemplo n.º 6
0
 def generate_aux(self):
     auxnames = list(self.fspec._auxfnspecs.keys())
     # User aux fn interface
     uafi = {}
     # protectednames = auxnames + self.fspec._protected_mathnames + \
     #                  self.fspec._protected_randomnames + \
     #                  self.fspec._protected_scipynames + \
     #                  self.fspec._protected_specialfns + \
     #                  ['abs', 'and', 'or', 'not', 'True', 'False']
     auxfns = self.builtin_aux
     # the internal functions may be used by user-defined functions,
     # so need them to be accessible to processTokens when parsing
     self.fspec._pyauxfns = auxfns
     # add the user-defined function names for cross-referencing checks
     # (without their definitions)
     for auxname in auxnames:
         self.fspec._pyauxfns[auxname] = None
     # don't process the built-in functions -> unique fns because
     # they are global definitions existing throughout the
     # namespace
     self.fspec._protected_auxnames.extend(['Jacobian', 'Jacobian_pars'])
     # protected names are the names that must not be used for
     # user-specified auxiliary fn arguments
     protectednames = self.fspec.pars + self.fspec.inputs \
         + ['abs', 'pow', 'and', 'or', 'not', 'True', 'False'] \
         + self.fspec._protected_auxnames + auxnames \
         + self.fspec._protected_numpynames \
         + self.fspec._protected_scipynames \
         + self.fspec._protected_specialfns \
         + self.fspec._protected_macronames \
         + self.fspec._protected_mathnames \
         + self.fspec._protected_randomnames \
         + self.fspec._protected_reusenames
     # checks for user-defined auxiliary fns
     # name map for fixing inter-auxfn references
     auxfn_namemap = {}
     specials_base = self.fspec.pars + self.fspec._protected_auxnames \
         + ['abs', 'pow', 'and', 'or', 'not', 'True', 'False'] \
         + auxnames + self.fspec._protected_scipynames \
         + self.fspec._protected_numpynames + self.fspec._protected_specialfns \
         + self.fspec._protected_macronames + self.fspec._protected_mathnames \
         + self.fspec._protected_randomnames + self.fspec._protected_reusenames
     for auxname in auxnames:
         auxinfo = self.fspec._auxfnspecs[auxname]
         try:
             if len(auxinfo) != 2:
                 raise ValueError('auxinfo tuple must be of length 2')
         except TypeError:
             raise TypeError('fnspecs argument must contain pairs')
         # auxinfo[0] = tuple or list of parameter names
         # auxinfo[1] = string containing body of function definition
         assert isinstance(auxinfo[0], list), ('aux function arguments '
                                               'must be given as a list')
         assert isinstance(auxinfo[1], str), ('aux function specification '
                                              'must be a string '
                                              'of the function code')
         # Process Jacobian functions, etc., specially, if present
         if auxname == 'Jacobian':
             if not compareList(auxinfo[0], ['t'] + self.fspec.vars):
                 print(['t'] + self.fspec.vars)
                 print("Auxinfo =" + str(auxinfo[0]))
                 raise ValueError(
                     "Invalid argument list given in Jacobian.")
             auxparlist = ["t", "x", "parsinps"]
             # special symbols to allow in parsing function body
             specials = ["t", "x"]
             auxstr = auxinfo[1]
             if any([pt in auxstr for pt in ('^', '**')]):
                 auxstr = convertPowers(auxstr, 'pow')
             specvars = self.fspec.vars
             specvars.sort()
             specdict = {}.fromkeys(specvars)
             if len(specvars) == 1:
                 assert '[' not in auxstr, \
                        "'[' character invalid in Jacobian for 1D system"
                 assert ']' not in auxstr, \
                        "']' character invalid in Jacobian for 1D system"
                 specdict[specvars[0]] = auxstr
             else:
                 specdict = parseMatrixStrToDictStr(auxstr, specvars)
             reusestr, body_processed_dict = self._processReusedPy(
                 specvars, specdict, specials=specials + specials_base)
             body_processed = self._specStrParse(specvars,
                                                 body_processed_dict,
                                                 'xjac',
                                                 specials=specials +
                                                 specials_base)
             auxstr_py = self._generate_fun('_auxfn_Jac',
                                            reusestr + body_processed,
                                            'xjac', specvars)
             # check Jacobian
             m = n = len(specvars)
             specdict_check = {}.fromkeys(specvars)
             for specname in specvars:
                 temp = body_processed_dict[specname]
                 specdict_check[specname] = \
                     count_sep(temp.replace("[", "").replace("]", "")) + 1
             body_processed = ""
             for row in range(m):
                 if specdict_check[specvars[row]] != n:
                     print("Row %i: " % m + specdict[specvars[row]])
                     print("Found length %i" %
                           specdict_check[specvars[row]])
                     raise ValueError("Jacobian should be %sx%s" % (m, n))
         elif auxname == 'Jacobian_pars':
             if not compareList(auxinfo[0], ['t'] + self.fspec.pars):
                 print(['t'] + self.fspec.pars)
                 print("Auxinfo =" + str(auxinfo[0]))
                 raise ValueError(
                     "Invalid argument list given in Jacobian.")
             auxparlist = ["t", "x", "parsinps"]
             # special symbols to allow in parsing function body
             specials = ["t", "x"]
             auxstr = auxinfo[1]
             if any([pt in auxstr for pt in ('^', '**')]):
                 auxstr = convertPowers(auxstr, 'pow')
             specvars = self.fspec.pars
             specvars.sort()
             specdict = {}.fromkeys(self.fspec.vars)
             if len(specvars) == len(self.fspec.vars) == 1:
                 assert '[' not in auxstr, \
                        "'[' character invalid in Jacobian for 1D system"
                 assert ']' not in auxstr, \
                        "']' character invalid in Jacobian for 1D system"
                 specdict[specvars[0]] = auxstr
             else:
                 specdict = parseMatrixStrToDictStr(auxstr, self.fspec.vars)
             reusestr, body_processed_dict = self._processReusedPy(
                 self.fspec.vars,
                 specdict,
                 specials=specials + specials_base)
             body_processed = self._specStrParse(self.fspec.vars,
                                                 body_processed_dict,
                                                 'pjac',
                                                 specials=specials +
                                                 specials_base)
             auxstr_py = self._generate_fun('_auxfn_Jac_p',
                                            reusestr + body_processed,
                                            'pjac', self.fspec.vars)
             # check Jacobian
             n = len(specvars)
             m = len(self.fspec.vars)
             specdict_check = {}.fromkeys(self.fspec.vars)
             for specname in self.fspec.vars:
                 temp = body_processed_dict[specname]
                 specdict_check[specname] = \
                     count_sep(temp.replace("[", "").replace("]", "")) + 1
             body_processed = ""
             for row in range(m):
                 try:
                     if specdict_check[self.fspec.vars[row]] != n:
                         print("Row %i: " % m +
                               specdict[self.fspec.vars[row]])
                         print("Found length %i" %
                               specdict_check[self.fspec.vars[row]])
                         raise ValueError(
                             "Jacobian w.r.t. pars should be %sx%s" %
                             (m, n))
                 except IndexError:
                     print("\nFound:\n")
                     info(specdict)
                     raise ValueError(
                         "Jacobian w.r.t. pars should be %sx%s" % (m, n))
         elif auxname == 'massMatrix':
             if not compareList(auxinfo[0], ['t'] + self.fspec.vars):
                 print(['t'] + self.fspec.vars)
                 print("Auxinfo =" + str(auxinfo[0]))
                 raise ValueError(
                     "Invalid argument list given in Mass Matrix.")
             auxparlist = ["t", "x", "parsinps"]
             # special symbols to allow in parsing function body
             specials = ["t", "x"]
             auxstr = auxinfo[1]
             if any([pt in auxstr for pt in ('^', '**')]):
                 auxstr = convertPowers(auxstr, 'pow')
             specvars = self.fspec.vars
             specvars.sort()
             specdict = {}.fromkeys(specvars)
             if len(specvars) == 1:
                 assert '[' not in auxstr, \
                        "'[' character invalid in mass matrix for 1D system"
                 assert ']' not in auxstr, \
                        "']' character invalid in mass matrix for 1D system"
                 specdict[list(specvars.values())[0]] = auxstr
             else:
                 specdict = parseMatrixStrToDictStr(auxstr, specvars)
             reusestr, body_processed_dict = self._processReusedPy(
                 specvars, specdict, specials=specials + specials_base)
             body_processed = self._specStrParse(specvars,
                                                 body_processed_dict,
                                                 'xmat',
                                                 specials=specials +
                                                 specials_base)
             auxstr_py = self._generate_fun('_auxfn_massMatrix',
                                            reusestr + body_processed,
                                            'xmat', specvars)
             # check matrix
             m = n = len(specvars)
             specdict_check = {}.fromkeys(specvars)
             for specname in specvars:
                 specdict_check[specname] = 1 + \
                     count_sep(
                         body_processed_dict[specname].replace("[", "").replace("]", ""))
             body_processed = ""
             for row in range(m):
                 if specdict_check[specvars[row]] != n:
                     print("Row %i: " % m + specdict[specvars[row]])
                     print("Found length %i" %
                           specdict_check[specvars[row]])
                     raise ValueError("Mass matrix should be %sx%s" %
                                      (m, n))
         else:
             user_parstr = makeParList(auxinfo[0])
             # `parsinps` is always added to allow reference to own
             # parameters
             if user_parstr == '':
                 # no arguments, user calls as fn()
                 auxparstr = 'parsinps'
             else:
                 auxparstr = 'parsinps, ' + user_parstr
             auxstr_py = 'def _auxfn_' + auxname + '(ds, ' + auxparstr \
                         + '):\n'
             auxparlist = auxparstr.replace(" ", "").split(",")
             badparnames = intersect(auxparlist,
                                     remain(protectednames, auxnames))
             if badparnames != []:
                 print("Bad parameter names in auxiliary function %s: %r" %
                       (auxname, badparnames))
                 # print(str(auxinfo[0]))
                 # print(str(auxparlist))
                 raise ValueError(
                     "Cannot use protected names (including"
                     " globally visible system parameters for auxiliary "
                     "function arguments")
             # special symbols to allow in parsing function body
             specials = auxparlist
             specials.remove('parsinps')
             illegalterms = remain(self.fspec.vars + self.fspec.auxvars,
                                   specials)
             auxstr = auxinfo[1]
             if any([pt in auxstr for pt in ('^', '**')]):
                 auxstr = convertPowers(auxstr, 'pow')
             reusestr, body_processed_dict = self._processReusedPy(
                 [auxname], {auxname: auxstr},
                 specials=specials + specials_base,
                 dovars=False,
                 illegal=illegalterms)
             body_processed = self._specStrParse([auxname],
                                                 body_processed_dict,
                                                 specials=specials +
                                                 specials_base,
                                                 dovars=False,
                                                 noreturndefs=True,
                                                 illegal=illegalterms)
             auxstr_py += reusestr + _indentstr + 'return ' \
                 + body_processed
         # syntax validation done in makeUniqueFn
         try:
             auxfns[auxname] = makeUniqueFn(auxstr_py)
             # Note: this automatically updates self.fspec._pyauxfns too
         except Exception:
             print('Error in supplied auxiliary spec dictionary code')
             raise
         auxfn_namemap['ds.' + auxname] = 'ds.' + auxfns[auxname][1]
         # prepare user-interface wrapper function (not method)
         if specials == [''] or specials == []:
             fn_args = ''
         else:
             fn_args = ',' + ','.join(specials)
         fn_elts = [
             'def ', auxname, '(self', fn_args, ',__parsinps__=None):\n\t',
             'if __parsinps__ is None:\n\t\t',
             '__parsinps__=self.map_ixs(self.genref)\n\t',
             'return self.genref.', auxfns[auxname][1], '(__parsinps__',
             fn_args, ')\n'
         ]
         uafi[auxname] = ''.join(fn_elts)
     # resolve inter-auxiliary function references
     for auxname, auxspec in auxfns.items():
         dummyQ = QuantSpec('dummy',
                            auxspec[0],
                            preserveSpace=True,
                            treatMultiRefs=False)
         dummyQ.mapNames(auxfn_namemap)
         auxfns[auxname] = (dummyQ(), auxspec[1])
     self.fspec._user_auxfn_interface = uafi
     self.fspec._protected_auxnames.extend(auxnames)
     return auxfns