Skip to content

Commit

Permalink
Merge pull request #398 from NeuroML/feat/visualise-morph-only
Browse files Browse the repository at this point in the history
Support visualisation of morphology only files
  • Loading branch information
sanjayankur31 authored Jun 27, 2024
2 parents 65c6582 + 6b04df6 commit b36bf40
Show file tree
Hide file tree
Showing 6 changed files with 5,083 additions and 51 deletions.
50 changes: 28 additions & 22 deletions pyneuroml/plot/PlotMorphology.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import matplotlib
import numpy
from matplotlib import pyplot as plt
from neuroml import Cell, NeuroMLDocument, SegmentGroup
from neuroml import Cell, Morphology, NeuroMLDocument, SegmentGroup
from neuroml.neuro_lex_ids import neuro_lex_ids

from pyneuroml.pynml import read_neuroml2_file
Expand Down Expand Up @@ -301,6 +301,7 @@ def plot_2D(
if verbose:
print("Plotting %s" % nml_file)

# if it's a file, load it first
if isinstance(nml_file, str):
# load without optimization for older HDF5 API
# TODO: check if this is required: must for MultiscaleISN
Expand All @@ -315,38 +316,43 @@ def plot_2D(
optimized=True,
)
load_minimal_morphplottable__model(nml_model, nml_file)
# note that from this point, the model object is not necessarily valid,
# because we've removed lots of bits.
else:
nml_model = nml_file

# if it isn't a NeuroMLDocument, create one
if isinstance(nml_model, Cell):
logger.info("Got a cell")
plottable_nml_model = NeuroMLDocument(id="newdoc")
plottable_nml_model.add(nml_model)
logger.info(f"plottable cell model is: {plottable_nml_model.cells[0]}")
if title is None:
try:
title = f"{nml_model.networks[0].id} from {nml_file}"
except IndexError:
title = f"{nml_model.cells[0].id} from {nml_file}"

elif isinstance(nml_file, Cell):
nml_model = NeuroMLDocument(id="newdoc")
nml_model.add(nml_file)
title = f"{plottable_nml_model.cells[0].id}"

# if it's only a cell, add it to an empty cell in a document
elif isinstance(nml_model, Morphology):
logger.info("Received morph, adding to a dummy cell")
plottable_nml_model = NeuroMLDocument(id="newdoc")
nml_cell = plottable_nml_model.add(
Cell, id=nml_model.id, morphology=nml_model, validate=False
)
plottable_nml_model.add(nml_cell)
logger.info(f"plottable cell model is: {plottable_nml_model.cells[0]}")
if title is None:
title = f"{nml_model.cells[0].id}"

elif isinstance(nml_file, NeuroMLDocument):
nml_model = nml_file
title = f"{plottable_nml_model.cells[0].id}"
elif isinstance(nml_model, NeuroMLDocument):
plottable_nml_model = nml_model
if title is None:
try:
title = f"{nml_model.networks[0].id} from {nml_file.id}"
except IndexError:
title = f"{nml_model.cells[0].id} from {nml_file.id}"
else:
raise TypeError(
"Passed model is not a NeuroML file path, nor a neuroml.Cell, nor a neuroml.NeuroMLDocument"
)
title = f"{plottable_nml_model.id}"

(
cell_id_vs_cell,
pop_id_vs_cell,
positions,
pop_id_vs_color,
pop_id_vs_radii,
) = extract_position_info(nml_model, verbose)
) = extract_position_info(plottable_nml_model, verbose)

if verbose:
logger.debug(f"positions: {positions}")
Expand Down
60 changes: 34 additions & 26 deletions pyneuroml/plot/PlotMorphologyVispy.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

import numpy
import progressbar
from neuroml import Cell, NeuroMLDocument, SegmentGroup
from neuroml import Cell, Morphology, NeuroMLDocument, SegmentGroup
from neuroml.neuro_lex_ids import neuro_lex_ids
from scipy.spatial.transform import Rotation

Expand Down Expand Up @@ -302,7 +302,7 @@ def vispy_on_key_press(event):


def plot_interactive_3D(
nml_file: typing.Union[str, Cell, NeuroMLDocument],
nml_file: typing.Union[str, Cell, Morphology, NeuroMLDocument],
min_width: float = DEFAULTS["minWidth"],
verbose: bool = False,
plot_type: str = "constant",
Expand Down Expand Up @@ -335,8 +335,10 @@ def plot_interactive_3D(
:param nml_file: path to NeuroML cell file or
:py:class:`neuroml.NeuroMLDocument` or :py:class:`neuroml.Cell` object
:type nml_file: str or neuroml.NeuroMLDocument or neuroml.Cell
:py:class:`neuroml.NeuroMLDocument` or :py:class:`neuroml.Cell`
or :py:class:`neuroml.Morphology` object
:type nml_file: str or neuroml.NeuroMLDocument or neuroml.Cell or
neuroml.Morphology
:param min_width: minimum width for segments (useful for visualising very
thin segments): default 0.8um
:type min_width: float
Expand Down Expand Up @@ -449,6 +451,7 @@ def plot_interactive_3D(
if verbose:
logger.info(f"Visualising {nml_file}")

# if it's a file, load it first
if isinstance(nml_file, str):
# load without optimization for older HDF5 API
# TODO: check if this is required: must for MultiscaleISN
Expand All @@ -463,38 +466,43 @@ def plot_interactive_3D(
optimized=True,
)
load_minimal_morphplottable__model(nml_model, nml_file)
# note that from this point, the model object is not necessarily valid,
# because we've removed lots of bits.
else:
nml_model = nml_file

# if it isn't a NeuroMLDocument, create one
if isinstance(nml_model, Cell):
logger.info("Got a cell")
plottable_nml_model = NeuroMLDocument(id="newdoc")
plottable_nml_model.add(nml_model)
logger.info(f"plottable cell model is: {plottable_nml_model.cells[0]}")
if title is None:
try:
title = f"{nml_model.networks[0].id} from {nml_file}"
except IndexError:
title = f"{nml_model.cells[0].id} from {nml_file}"

elif isinstance(nml_file, Cell):
nml_model = NeuroMLDocument(id="newdoc")
nml_model.add(nml_file)
title = f"{plottable_nml_model.cells[0].id}"

# if it's only a cell, add it to an empty cell in a document
elif isinstance(nml_model, Morphology):
logger.info("Received morph, adding to a dummy cell")
plottable_nml_model = NeuroMLDocument(id="newdoc")
nml_cell = plottable_nml_model.add(
Cell, id=nml_model.id, morphology=nml_model, validate=False
)
plottable_nml_model.add(nml_cell)
logger.info(f"plottable cell model is: {plottable_nml_model.cells[0]}")
if title is None:
title = f"{nml_model.cells[0].id}"

elif isinstance(nml_file, NeuroMLDocument):
nml_model = nml_file
title = f"{plottable_nml_model.cells[0].id}"
elif isinstance(nml_model, NeuroMLDocument):
plottable_nml_model = nml_model
if title is None:
try:
title = f"{nml_model.networks[0].id} from {nml_file.id}"
except IndexError:
title = f"{nml_model.cells[0].id} from {nml_file.id}"
else:
raise TypeError(
"Passed model is not a NeuroML file path, nor a neuroml.Cell, nor a neuroml.NeuroMLDocument"
)
title = f"{plottable_nml_model.id}"

(
cell_id_vs_cell,
pop_id_vs_cell,
positions,
pop_id_vs_color,
pop_id_vs_radii,
) = extract_position_info(nml_model, verbose)
) = extract_position_info(plottable_nml_model, verbose)

logger.debug(f"positions: {positions}")
logger.debug(f"pop_id_vs_cell: {pop_id_vs_cell}")
Expand Down Expand Up @@ -726,7 +734,7 @@ def plot_interactive_3D(
f"More meshes than threshold ({len(meshdata.keys())}/{precision[1]}), reducing precision to {precision[0]} and re-calculating."
)
plot_interactive_3D(
nml_file=nml_model,
nml_file=plottable_nml_model,
min_width=min_width,
verbose=verbose,
plot_type=plot_type,
Expand Down
12 changes: 10 additions & 2 deletions pyneuroml/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@

import neuroml
import numpy
import pyneuroml.utils.misc
from lems.model.model import Model
from neuroml.loaders import read_neuroml2_file

import pyneuroml.utils.misc
from pyneuroml.errors import UNKNOWN_ERR
from pyneuroml.utils.plot import get_next_hex_color


logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

Expand Down Expand Up @@ -86,12 +86,20 @@ def extract_position_info(
pop_id_vs_color = {}
pop_id_vs_radii = {}

morph_elements = []
cell_elements = []
popElements = []

cell_elements.extend(nml_model.cells)
cell_elements.extend(nml_model.cell2_ca_poolses)

# handle morphology elements by adding them into dummy cells
ctr = 1
morph_elements.extend(nml_model.morphology)
for m in morph_elements:
cell_elements.append(neuroml.Cell(id=f"Dummy cell {ctr}", morphology=m))
ctr += 1

# if the model does not include a network, plot all the cells in the
# model in new dummy populations
if len(nml_model.networks) == 0:
Expand Down
6 changes: 5 additions & 1 deletion pyneuroml/utils/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ def load_minimal_morphplottable__model(
required_members = [
"id",
"cells",
"morphology",
"cell2_ca_poolses",
"networks",
"populations",
Expand All @@ -360,6 +361,7 @@ def load_minimal_morphplottable__model(
for m in model_members:
if m not in required_members:
setattr(nml_model, m, None)
logger.debug(f"Dropped {m}")

# if the model contains a network, use it
if len(nml_model.networks) > 0:
Expand All @@ -385,11 +387,13 @@ def load_minimal_morphplottable__model(
acell.biophysical_properties = None
nml_model.add(acell)
else:
# add any included cells to the main document
# add any included cells or morphologies to the main document
for inc in nml_model.includes:
incl_loc = os.path.abspath(os.path.join(base_path, inc.href))
if os.path.isfile(incl_loc):
inc = read_neuroml2_file(incl_loc)
for acell in inc.cells:
acell.biophysical_properties = None
nml_model.add(acell)
for morph in inc.morphology:
nml_model.add(morph)
Loading

0 comments on commit b36bf40

Please sign in to comment.