ModECI / modelspec

Functionality for specifying models & enabling automatic serialization - will be used by MDF & NeuroMLlite
https://modeci.github.io/modelspec/
Apache License 2.0
3 stars 9 forks source link

Cattr unstructure erroring out in the test class #49

Closed mqnifestkelvin closed 1 year ago

mqnifestkelvin commented 1 year ago

while trying to use the cattr class to convert an xml representation to a python representation, I decided to convert the xml to a dictionary and then use the cattr.structure function to convert into a python object. While doing this, I discovered I couldn't convert the NewNetwork class in the modelspec test_base.py to an python objecet using the cattr.unstructure even though it worked perfectly well for the neuroML class in neuroml example directory in the neuroml2_spec.py file

from typing import List
from dataclasses import fields
import modelspec
from modelspec import field, instance_of, optional
from modelspec.base_types import Base, value_expr_types, ValueExprType, print_v
from typing import List, Dict, Any, Optional
import xml.dom.minidom
from pathlib import Path
import sys
import xml.dom.minidom

@modelspec.define
class Population(Base):
    """
    Some description...

    Args:
        id: The id of the population
        component: the component to use in the population
        size: the size of the population
    """

    id: str = field(validator=instance_of(str))
    component: str = field(default=None, validator=optional(instance_of(str)))
    size: int = field(default=None, validator=optional(instance_of(int)))

@modelspec.define
class ExplicitInput(Base):
    """
    Some description...

    Args:
        target: the target of the input
        input: the input, e.g. pulseGenerator
    """

    target: str = field(default=None, validator=optional(instance_of(str)))
    input: str = field(default=None, validator=optional(instance_of(str)))

@modelspec.define
class Network(Base):
    """
    Some description...

    Args:
        id: The id of the network
        populations: the pops in the net
    """

    id: str = field(validator=instance_of(str))

    populations: List[Population] = field(factory=list)
    explicitInputs: List[ExplicitInput] = field(factory=list)

@modelspec.define
class PulseGenerator(Base):
    """
    Some description...

    Args:
        id: The id of the pulseGenerator
        delay: the delay
        duration: the duration
        amplitude: the amplitude
    """

    id: str = field(validator=instance_of(str))
    delay: str = field(validator=instance_of(str))
    duration: str = field(validator=instance_of(str))
    amplitude: str = field(validator=instance_of(str))

@modelspec.define
class Izhikevich2007Cell(Base):
    """
    Some description...

    Args:
        id: The id of the cell...
    """

    id: str = field(validator=instance_of(str))

    C: str = field(validator=instance_of(str))
    v0: str = field(validator=instance_of(str))
    k: str = field(validator=instance_of(str))
    vr: str = field(validator=instance_of(str))
    vt: str = field(validator=instance_of(str))
    vpeak: str = field(validator=instance_of(str))
    a: str = field(validator=instance_of(str))
    b: str = field(validator=instance_of(str))
    c: str = field(validator=instance_of(str))
    d: str = field(validator=instance_of(str))

@modelspec.define
class NeuroML(Base):
    """
    Some description...

    Args:
        id: The id of the NeuroML 2 document
        version: NeuroML version used
        networks: The networks present
    """

    id: str = field(validator=instance_of(str))
    version: str = field(validator=instance_of(str))

    izhikevich2007Cells: List[Izhikevich2007Cell] = field(factory=list)
    pulseGenerators: List[PulseGenerator] = field(factory=list)
    networks: List[Network] = field(factory=list)

nml_doc = NeuroML(id="TestNeuroML", version="NeuroML_v2.3")

izh = Izhikevich2007Cell(
        id="izh2007RS0",
        C="100pF",
        v0="-60mV",
        k="0.7nS_per_mV",
        vr="-60mV",
        vt="-40mV",
        vpeak="35mV",
        a="0.03per_ms",
        b="-2nS",
        c="-50.0mV",
        d="100pA",
)
nml_doc.izhikevich2007Cells.append(izh)

pg = PulseGenerator(
        id="pulseGen_0", delay="100ms", duration="800ms", amplitude="0.07 nA"
)
nml_doc.pulseGenerators.append(pg)

net = Network(id="IzNet")
nml_doc.networks.append(net)

net.populations.append(Population("IzhPop0", component="izh2007RS0", size=1))
net.explicitInputs.append(ExplicitInput(target="IzhPop0[0]", input="pulseGen_0"))
print(nml_doc)

@modelspec.define
class NewCell(Base):
    """
    A new cell definition

    Args:
        id: the cell id
        neuroml2_source_file: The path to the source file
    """

    id: str = field(validator=instance_of(str))
    neuroml2_source_file: str = field(
        default=None, validator=optional(instance_of(str))
    )

@modelspec.define
class NewSynapse(Base):
    """
    A new synapse definition

    Args:
        id: the synapse id
        neuroml2_source_file: The path to the source file
        tested: A boolean attribute
    """

    id: str = field(validator=instance_of(str))
    neuroml2_source_file: str = field(
        default=None, validator=optional(instance_of(str))
    )
    tested: bool = field(default=None, validator=optional(instance_of(bool)))

@modelspec.define
class NewRandomConnectivity(Base):
    """
    A new random connectivity definition

    Args:
        probability: Random probability of connection

    """

    probability: ValueExprType = field(
        default=None, validator=optional(instance_of(value_expr_types))
    )

@modelspec.define
class NewNetwork(Base):
    """
    A new network definition

    Args:
        id: a unique identifier for the network
        cells: a list of cells
        synapses: a list of synapses
        version: Information on verson of NeuroMLlite
        seed: Seed for random number generator used when building network
        stable: Testing...
        parameters: Dictionary of global parameters for the network
        random_connectivity: Use random connectivity
    """

    id: str = field(validator=instance_of(str))
    cells: List[NewCell] = field(factory=list)
    synapses: List[NewSynapse] = field(factory=list)
    version: str = field(default="NeuroMLlite 0.0", validator=instance_of(str))
    seed: int = field(default=None, validator=optional(instance_of(int)))
    stable: bool = field(default=None, validator=optional(instance_of(bool)))
    parameters: Dict[str, Any] = field(
        default=None, validator=optional(instance_of(dict))
    )
    random_connectivity: NewRandomConnectivity = field(
        default=None, validator=optional(instance_of(NewRandomConnectivity))
    )
    ee0: ValueExprType = field(
        default=None, validator=optional(instance_of(value_expr_types))
    )
    ee1: ValueExprType = field(
        default=None, validator=optional(instance_of(value_expr_types))
    )
    ee2: ValueExprType = field(
        default=None, validator=optional(instance_of(value_expr_types))
    )
    ee3: ValueExprType = field(
        default=None, validator=optional(instance_of(value_expr_types))
    )
    ee4: ValueExprType = field(
        default=None, validator=optional(instance_of(value_expr_types))
    )
    ee5: ValueExprType = field(
        default=None, validator=optional(instance_of(value_expr_types))
    )
    ee6: ValueExprType = field(
        default=None, validator=optional(instance_of(value_expr_types))
    )

net = NewNetwork(id="netid", parameters={"size": 3, "name": None})

net.ee0 = "str"
net.ee1 = {"a": 2}
net.ee2 = 1
net.ee3 = 1.1
net.ee4 = True
net.ee5 = [1, 2]
net.ee6 = 2

cell = NewCell(id="cellid1")
cell.neuroml2_source_file = "nnn"
cell2 = NewCell(id="cellid2")
cell2.neuroml2_source_file = "nnn2"
# net.cells.append(cell)

print(net)
print(net.cells)
print(net)
"""  """
net.cells.append(cell)
net.cells.append(cell2)

syn0 = NewSynapse(id="syn0", neuroml2_source_file=None, tested=True)
net.synapses.append(syn0)
syn1 = NewSynapse(id="syn1", neuroml2_source_file="xx", tested=None)
net.synapses.append(syn1)

rc = NewRandomConnectivity(probability=0.01)
net.random_connectivity = rc
net.stable = False
print(rc)
print(net)

from cattr import structure, unstructure
nml_dict = unstructure(nml_doc)

#This is the NeuroML class being unstructured
print("This is NeuroML unstructured format")
print(nml_dict)

#This is the NeuroML class being structured
print("This is NeuroML structured format")
print(structure(nml_dict, NeuroML))

#This is the NewNetwork class being unstructured
print("This is NewNetwork unstructured format")
nml_dict2 = unstructure(net)
print(nml_dict2)

#This is the NewNetwork class being unstructured
print("This is NewNetwork structured format")
print(structure(nml_dict2, NewNetwork))
pgleeson commented 1 year ago

@mqnifestkelvin I assume this issue is no longer relevant?

mqnifestkelvin commented 1 year ago

Good morning mentor @pgleeson It's no longer relevant since I got an alternative working.

pgleeson commented 1 year ago

Thanks @mqnifestkelvin