scale = "" if unit.scale is not None and unit.scale != 1: scale = "<br/>" + spacer4 + "Scale: " + str(unit.scale) contents += spacer4 + "Dimension: " + dimension( unit.dimension, "", "") + "<br/>" + spacer4 + "Power of 10: " + str( unit.power) + offset + scale + "<br/>\n" for unit2 in model.units: if unit.symbol != unit2.symbol and unit.dimension == unit2.dimension: '''diff = unit.power - unit2.power factor = "10<sup>%i</sup>"%diff if diff == 0: factor = 1''' factor1 = model.get_numeric_value("1%s" % unit.symbol, unit.dimension) factor2 = model.get_numeric_value("1%s" % unit2.symbol, unit2.dimension) contents += "<br/>" + spacer4 + "1 %s = %s <a href='#%s'>%s</a>" % ( unit.symbol, "%s" % (factor1 / factor2), unit2.symbol, unit2.symbol) contents += " </td>\n" contents += " </tr>\n" contents += "</table>\n" for o_comp_type in ordered_comp_types[file]: comp_type = model.component_types[o_comp_type] #print "ComponentType %s is %s"%(comp_type.name, comp_type.description) ext = "" if comp_type.extends is None else "<p>%sextends %s</p>" % (
if unit.offset is not None and unit.offset != 0: offset = "<br/>"+spacer4+"Offset: "+str(unit.offset) scale = "" if unit.scale is not None and unit.scale != 1: scale = "<br/>"+spacer4+"Scale: "+str(unit.scale) contents += spacer4+"Dimension: "+dimension(unit.dimension, "", "")+"<br/>"+spacer4+"Power of 10: "+str(unit.power)+offset+scale+"<br/>\n" for unit2 in model.units: if unit.symbol != unit2.symbol and unit.dimension == unit2.dimension: '''diff = unit.power - unit2.power factor = "10<sup>%i</sup>"%diff if diff == 0: factor = 1''' factor1 = model.get_numeric_value("1%s"%unit.symbol, unit.dimension) factor2 = model.get_numeric_value("1%s"%unit2.symbol, unit2.dimension) contents += "<br/>"+spacer4+"1 %s = %s <a href='#%s'>%s</a>" % (unit.symbol, "%s"%(factor1/factor2), unit2.symbol, unit2.symbol) contents += " </td>\n" contents += " </tr>\n" contents += "</table>\n" for o_comp_type in ordered_comp_types[file]: comp_type = model.component_types[o_comp_type] #print "ComponentType %s is %s"%(comp_type.name, comp_type.description)
def main(srcdir, destdir): """Main parser and generator function. :param srcdir: directory holding source NeuroML Core Type XML files :type srcdir: str :param destdir: directory where generated files should be stored :type destdir: str :returns: nothing """ # If not defined or empty, download a new copy to a temporary directory if not srcdir or src == "": print("No src directory specified. Cloning NeuroML2 repo") tempdir = tempfile.TemporaryDirectory() tmpsrcdir = tempdir.name print("Temporariy directory: {}".format(tmpsrcdir)) clone_command = [ "git", "clone", "--depth", "1", "--branch", nml_branch, GitHubRepo, tmpsrcdir ] subprocess.run(clone_command) else: tmpsrcdir = srcdir # TODO: add LEMS examples # We can't do this at the moment, because the LEMS python bits are in # pyneuroml, while we point to the libNeuroML docs for the NeuroML2 usage # examples. pyneuroml does not currently have docs on RTD, and some more # work will be required to tell our templates when an example is NeuroML # and when it is LEMS so it can point to the correct docs. # exampledirs = [tmpsrcdir + "/examples/", tmpsrcdir + "/LEMSexamples/"] exampledirs = [tmpsrcdir + "/examples/"] tmpsrcdir = tmpsrcdir + "/NeuroML2CoreTypes/" # Get current commit commit_command = ["git", "log", "-1", "--pretty=format:%H"] output = subprocess.run(commit_command, capture_output=True, cwd=tmpsrcdir, text=True) nml_commit = output.stdout # read the downloaded files get_component_types(tmpsrcdir) # get examples get_comp_examples(exampledirs) # get python signatures get_libneuroml_signatures() if not destdir or destdir == "": destdir = "." print("Output files will be written to {} directory".format(destdir)) for comp_definition in comp_definitions: fullpath = "{}/{}.xml".format(tmpsrcdir, comp_definition) outputfile = "{}/{}.md".format(destdir, comp_definition) """Stage 1""" model = Model(include_includes=False) model.import_from_file(fullpath) print("Processing {}".format(fullpath)) print("Writing output to {}".format(outputfile)) ast_doc = open(outputfile, 'w') """Page header""" print(asttemplates.page_header.render( comp_definition=comp_definition, comp_description=format_description(model.description), GitHubCompSources=GitHubCompSources, nml_version=nml_version, nml_branch=nml_branch, nml_date=nml_date, nml_commit=nml_commit), file=ast_doc) """Dimensions and units""" if "Dimensions" in comp_definition: dimensions = model.dimensions dimensions = sorted(dimensions, key=lambda dim: dim.name) units = model.units units = sorted(units, key=lambda unit: unit.symbol) # lables are translated as lowercase in jupyter, so we append two # consecutive underscores to differentiate same ones, like M and m. symbols = [] for unit in units: if unit.symbol.lower() in symbols: unit.symbol = unit.symbol + "__" symbols.append(unit.symbol.lower()) print(asttemplates.dimension.render( comp_definition=comp_definition, dimensions=dimensions, units=units), file=ast_doc) # Get factors for unit in units: unit.factors = [] for unit2 in units: if unit.symbol != unit2.symbol and unit.dimension == unit2.dimension: si_val = model.get_numeric_value( "1%s" % unit.symbol.replace("__", ""), unit.dimension) unit_val = ( (Decimal(si_val) / Decimal(math.pow(10, unit2.power))) / Decimal(unit2.scale)) - Decimal(unit2.offset) conversion = float(unit_val) # to catch 60.0001 etc. if conversion > 1 and int(conversion) != conversion: if conversion - int(conversion) < 0.001: conversion = int(conversion) if conversion > 10000: conversion = '%.2e' % conversion else: conversion = '%s' % conversion if conversion.endswith('.0'): conversion = conversion[:-2] unit.factors.append([conversion, unit2.symbol]) print(asttemplates.unit.render(comp_definition=comp_definition, units=units), file=ast_doc) """Component Types""" for o_comp_type in ordered_comp_types[comp_definition]: o_comp_type = o_comp_type.replace('rdf:', 'rdf_') comp_type = model.component_types[o_comp_type] """Header""" cno = None if " cno_00" in str(comp_type.description): cno = comp_type.description.split(" ")[-1] comp_type.description = comp_type.description.replace(cno, "") comp_type.description = format_description(comp_type.description) if len(comp_type.description) > 0: if comp_type.description[-1] not in "!.": comp_type.description += "." else: comp_type.description = "" print(asttemplates.comp.render(comp_definition=comp_definition, comp_type=comp_type, cno=cno), file=ast_doc) """Process parameters, derived parameters, texts, paths, expsures, requirements and ports""" params = {} derived_params = {} texts = {} paths = {} exposures = {} requirements = {} eventPorts = {} """Get lists of them all""" for param in comp_type.parameters: params[param] = comp_type.name for derived_param in comp_type.derived_parameters: derived_params[derived_param] = comp_type.name for text in comp_type.texts: texts[text] = comp_type.name for path in comp_type.paths: paths[path] = comp_type.paths for exp in comp_type.exposures: exposures[exp] = comp_type.name for req in comp_type.requirements: requirements[req] = comp_type.name for ep in comp_type.event_ports: eventPorts[ep] = comp_type.name """Get parent ComponentType if derived from one.""" extd_comp_type = get_extended_from_comp_type(comp_type.name) """Recursively go up the tree and get attributes inherited from ancestors.""" while extd_comp_type is not None: for param in extd_comp_type.parameters: pk = params.copy().keys() for pp0 in pk: if pp0.name == param.name: del params[pp0] params[param] = extd_comp_type.name for derived_param in extd_comp_type.derived_parameters: derived_params[derived_param] = extd_comp_type.name for text in extd_comp_type.texts: texts[text] = extd_comp_type.name for path in extd_comp_type.paths: paths[path] = extd_comp_type.paths for exp in extd_comp_type.exposures: ek = exposures.copy().keys() for ee0 in ek: if ee0.name == exp.name: del exposures[ee0] exposures[exp] = extd_comp_type.name for req in extd_comp_type.requirements: requirements[req] = extd_comp_type.name for ep in extd_comp_type.event_ports: eventPorts[ep] = extd_comp_type.name """Recurse up the next parent""" extd_comp_type = get_extended_from_comp_type( extd_comp_type.name) if len(params) > 0: keysort = sorted(params.keys(), key=lambda param: param.name) print(asttemplates.params.render(title="Parameters", comp_type=comp_type, entries=params, keysort=keysort), file=ast_doc) if len(derived_params) > 0: keysort = sorted(derived_params.keys(), key=lambda derived_param: derived_param.name) print(asttemplates.params.render(title="Derived parameters", comp_type=comp_type, entries=derived_params, keysort=keysort), file=ast_doc) if len(comp_type.texts ) > 0: # TODO: Check if Text elements are inherited... print(asttemplates.misc2c.render(title="Text fields", textlist=comp_type.texts), file=ast_doc) if len(comp_type.paths ) > 0: # TODO: Check if Path elements are inherited... print(asttemplates.misc2c.render(title="Paths", textlist=comp_type.paths), file=ast_doc) if len(comp_type.component_references) > 0: print(asttemplates.misc3c.render( title="Component References", textlist=comp_type.component_references), file=ast_doc) if len(comp_type.children) > 0: childlist = [] childrenlist = [] for child_or_children in comp_type.children: if not child_or_children.multiple: childlist.append(child_or_children) else: childrenlist.append(child_or_children) if len(childlist) > 0: print(asttemplates.misc3c.render(title="Child list", textlist=childlist), file=ast_doc) if len(childrenlist) > 0: print(asttemplates.misc3c.render(title="Children list", textlist=childrenlist), file=ast_doc) if len(comp_type.constants) > 0: print(asttemplates.constants.render( title="Constants", textlist=comp_type.constants), file=ast_doc) if len(comp_type.properties) > 0: print(asttemplates.properties.render( title="Properties", textlist=comp_type.properties), file=ast_doc) if len(exposures) > 0: keysort = sorted(exposures, key=lambda entry: entry.name) print(asttemplates.exposures.render(title="Exposures", comp_type=comp_type, entries=exposures, keysort=keysort), file=ast_doc) if len(requirements) > 0: keysort = sorted(requirements, key=lambda entry: entry.name) print(asttemplates.requirements.render(title="Requirements", comp_type=comp_type, entries=requirements, keysort=keysort), file=ast_doc) if len(eventPorts) > 0: keysort = sorted(eventPorts, key=lambda entry: entry.name) print(asttemplates.eventPorts.render(title="Event Ports", comp_type=comp_type, entries=eventPorts, keysort=keysort), file=ast_doc) if len(comp_type.attachments) > 0: print(asttemplates.misc3c.render( title="Attachments", textlist=comp_type.attachments), file=ast_doc) if comp_type.dynamics and comp_type.dynamics.has_content(): print(asttemplates.dynamics.render(title="Dynamics", comp_type=comp_type), file=ast_doc) # Examples """ print("{} has: ".format(comp_type.name)) if comp_type_py_api[comp_type.name]: print("\t1 Py def") if len(comp_type_examples[comp_type.name]) > 0: print("\t{} XML examples".format(len(comp_type_examples[comp_type.name]))) """ if comp_type_py_api[comp_type.name] or len( comp_type_examples[comp_type.name]) > 0: print(asttemplates.examples.render( title="Usage", comp_type=comp_type, lemsexamples=comp_type_examples[comp_type.name], pysig=comp_type_py_api[comp_type.name]), file=ast_doc) ast_doc.close() print("Finished processing {}".format(fullpath)) if not srcdir: tempdir.cleanup()