diff --git a/.github/workflows/full-test.yml b/.github/workflows/full-test.yml index 0dec5abd..be5df1e1 100644 --- a/.github/workflows/full-test.yml +++ b/.github/workflows/full-test.yml @@ -39,7 +39,7 @@ jobs: - name: Install NEURON if: startsWith(matrix.os, 'ubuntu') run: | - python -m pip install "neuron>=9.0.0" + python -m pip install "neuron>=9.0.0" morphio python -m pip install "nrnutils>0.2.0" - name: Install NEST if: startsWith(matrix.os, 'ubuntu') @@ -53,7 +53,7 @@ jobs: - name: Install Arbor if: startsWith(matrix.os, 'ubuntu') run: | - python -m pip install arbor==0.9.0 libNeuroML + python -m pip install arbor==0.9.0 libNeuroML morphio - name: Install PyNN itself run: | python -m pip install -e ".[test]" diff --git a/pyNN/arbor/cells.py b/pyNN/arbor/cells.py index b6ecdd01..54c0173d 100644 --- a/pyNN/arbor/cells.py +++ b/pyNN/arbor/cells.py @@ -6,7 +6,6 @@ from ..morphology import Morphology, NeuroMLMorphology, MorphIOMorphology, IonChannelDistribution from ..models import BaseCellType from ..parameters import ParameterSpace -from morphio import SectionType def convert_point(p3d: Point3DWithDiam) -> arbor.mpoint: diff --git a/pyNN/morphology.py b/pyNN/morphology.py index ceba9a3b..0df5bcf7 100644 --- a/pyNN/morphology.py +++ b/pyNN/morphology.py @@ -14,8 +14,6 @@ have_neuroml = True except ImportError: have_neuroml = False -import morphio -from morphio import SectionType def _download_file(url): @@ -68,6 +66,8 @@ class NeuroMLMorphology(Morphology): """ def __init__(self, morphology): + from morphio import SectionType + if not have_neuroml: raise ImportError("Please install libNeuroML to use the NeuroMLMorphology class") super(NeuroMLMorphology, self).__init__() @@ -158,6 +158,9 @@ class BrianMorphology(Morphology): class MorphIOMorphology(Morphology): def __init__(self, morphology_file): + import morphio + from morphio import SectionType + super().__init__() self.morphology_file = morphology_file self._morphology = morphio.Morphology(morphology_file) diff --git a/pyNN/neuron/cells.py b/pyNN/neuron/cells.py index 66140a7d..d8cb43c7 100644 --- a/pyNN/neuron/cells.py +++ b/pyNN/neuron/cells.py @@ -14,7 +14,6 @@ import numpy as np from neuron import h, nrn, hclass import numpy.random -from morphio import SectionType from .. import errors from ..models import BaseCellType diff --git a/pyNN/neuron/morphology.py b/pyNN/neuron/morphology.py index 45ac20e6..e11c780f 100644 --- a/pyNN/neuron/morphology.py +++ b/pyNN/neuron/morphology.py @@ -4,7 +4,6 @@ """ -from morphio import SectionType import numpy as np from .. import morphology as base_morphology @@ -38,6 +37,8 @@ class dendrites(base_morphology.dendrites): def __call__(self, morphology, filter_by_section=False): """Return an index (integer NumPy array) that can be used to retrieve the sections corresponding to the filter. """ + from morphio import SectionType + section_index = np.array([], dtype=int) for label in (SectionType.apical_dendrite, SectionType.basal_dendrite): if label in morphology.section_groups: @@ -53,6 +54,8 @@ def __call__(self, morphology, filter_by_section=False): class apical_dendrites(base_morphology.apical_dendrites): def __call__(self, morphology, filter_by_section=False): + from morphio import SectionType + if SectionType.apical_dendrite in morphology.section_groups: section_index = morphology.section_groups[SectionType.apical_dendrite] if filter_by_section: @@ -66,6 +69,8 @@ def __call__(self, morphology, filter_by_section=False): class basal_dendrites(base_morphology.basal_dendrites): def __call__(self, morphology, filter_by_section=False): + from morphio import SectionType + if SectionType.basal_dendrite in morphology.section_groups: section_index = morphology.section_groups[SectionType.basal_dendrite] if filter_by_section: @@ -79,6 +84,8 @@ def __call__(self, morphology, filter_by_section=False): class axon(base_morphology.axon): def __call__(self, morphology, filter_by_section=False): + from morphio import SectionType + if SectionType.axon in morphology.section_groups: section_index = morphology.section_groups[SectionType.axon] if filter_by_section: @@ -92,6 +99,8 @@ def __call__(self, morphology, filter_by_section=False): class soma(base_morphology.axon): def __call__(self, morphology, filter_by_section=False): + from morphio import SectionType + if SectionType.soma in morphology.section_groups: section_index = morphology.section_groups[SectionType.soma] if filter_by_section: diff --git a/pyproject.toml b/pyproject.toml index af831fca..92d05e0e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,8 +29,7 @@ classifiers = [ ] dependencies = [ "lazyarray>=0.5.2", - "neo>=0.13.4", - "morphio" + "neo>=0.13.4" ] [project.optional-dependencies] @@ -40,9 +39,10 @@ examples = ["matplotlib", "scipy"] plotting = ["matplotlib", "scipy"] MPI = ["mpi4py"] sonata = ["h5py"] +morphologies = ["morphio"] neuron = ["neuron", "nrnutils"] brian2 = ["brian2"] -arbor = ["arbor==0.9.0", "libNeuroML"] +arbor = ["arbor==0.9.0", "libNeuroML", "morphio"] spiNNaker = ["spyNNaker"] neuroml = ["libNeuroML"] diff --git a/test/system/scenarios/test_scenario5.py b/test/system/scenarios/test_scenario5.py index 0e41ceb3..55e7cbf5 100644 --- a/test/system/scenarios/test_scenario5.py +++ b/test/system/scenarios/test_scenario5.py @@ -1,6 +1,12 @@ import sys import numpy as np +try: + import morphio + have_morphio = True +except ImportError: + have_morphio = False + try: from neuroml import Morphology, Segment, Point3DWithDiam as P have_neuroml = True @@ -21,6 +27,8 @@ def test_scenario5(sim): """ Array of multi-compartment neurons, each injected with a different current. """ + if not have_morphio: + pytest.skip("morphio not available") if not have_neuroml: pytest.skip("libNeuroML not available") diff --git a/test/system/test_neuron.py b/test/system/test_neuron.py index 8df94a02..a21f24f4 100644 --- a/test/system/test_neuron.py +++ b/test/system/test_neuron.py @@ -18,6 +18,11 @@ have_neuron = False import pytest +try: + import morphio + have_morphio = True +except ImportError: + have_morphio = False try: from neuroml import Morphology, Segment, Point3DWithDiam as P @@ -242,8 +247,8 @@ def test_artificial_cells(): def test_2_compartment(): - if not (have_neuron and have_neuroml): - pytest.skip("Need neuron and neuroml") + if not (have_neuron and have_neuroml and have_morphio): + pytest.skip("Need neuron, neuroml, and morphio") sim = pyNN.neuron sim.setup(timestep=0.025) diff --git a/test/unittests/test_morphology.py b/test/unittests/test_morphology.py index 15a8c0d2..46b15ffc 100644 --- a/test/unittests/test_morphology.py +++ b/test/unittests/test_morphology.py @@ -17,7 +17,12 @@ have_neuroml = True except ImportError: have_neuroml = False -from pyNN.morphology import load_morphology, NeuroMLMorphology, SectionType, any as morph_any +try: + from pyNN.morphology import load_morphology, NeuroMLMorphology, any as morph_any + from morphio import SectionType + have_morphio = True +except ImportError: + have_morphio = False try: from pyNN.neuron.morphology import (dendrites, apical_dendrites, basal_dendrites, random_section, with_label, @@ -53,8 +58,10 @@ def setUpModule(): global neuroml_morph, array_morph + if not have_morphio: + pytest.skip("morphio not installed") if not have_neuroml: - pytest.skip("libNeuroML not installed") + pytest.skip("libNeuroML not installed") test_file = "morph_test.swc" with open(test_file, "w") as fp: