Skip to content

Commit 00f1f64

Browse files
committed
feat(2d-morph-plot): implement highlighting of individual segments
1 parent 7b8ed27 commit 00f1f64

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed

pyneuroml/plot/PlotMorphology.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ def plot_2D(
182182
plot_spec: typing.Optional[
183183
typing.Dict[str, typing.Union[str, typing.List[int], float]]
184184
] = None,
185+
highlight_spec: typing.Optional[typing.Dict[typing.Any, typing.Any]] = None,
185186
):
186187
"""Plot cells in a 2D plane.
187188
@@ -192,6 +193,10 @@ def plot_2D(
192193
193194
This method uses matplotlib.
194195
196+
.. versionadded:: 1.1.12
197+
The hightlight_spec parameter
198+
199+
195200
:param nml_file: path to NeuroML cell file, or a NeuroMLDocument object
196201
:type nml_file: str or :py:class:`neuroml.NeuroMLDocument` or
197202
:py:class:`neuroml.Cell`
@@ -239,13 +244,43 @@ def plot_2D(
239244
The last three lists override the point_fraction setting. If a cell id
240245
is not included in the spec here, it will follow the plot_type provided
241246
before.
247+
:type plot_spec: dict
248+
:param highlight_spec: dictionary that allows passing some
249+
specifications to allow highlighting of particular elements. Only used
250+
when plotting multi-compartmental cells for marking segments on them
251+
("plot_type" is either "constant" or "detailed")
252+
253+
Each key in the dictionary will be of the cell id and the values will
254+
be more dictionaries, with the segment id as key and the following keys
255+
in it:
256+
257+
- marker_color: color of the marker
258+
- marker_size: width of the marker
259+
260+
E.g.:
261+
262+
.. code-block:: python
263+
264+
{
265+
"cell id1": {
266+
"seg id1": {
267+
"marker_color": "blue",
268+
"marker_size": 10
269+
}
270+
}
271+
}
272+
273+
:type highlight_spec: dict
242274
"""
243275

244276
if plot_type not in ["detailed", "constant", "schematic", "point"]:
245277
raise ValueError(
246278
"plot_type must be one of 'detailed', 'constant', 'schematic', 'point'"
247279
)
248280

281+
if highlight_spec is None:
282+
highlight_spec = {}
283+
249284
if verbose:
250285
print("Plotting %s" % nml_file)
251286

@@ -412,6 +447,11 @@ def plot_2D(
412447
or plot_type == "constant"
413448
or cell.id in constant_cells
414449
):
450+
cell_highlight_spec = {}
451+
try:
452+
cell_highlight_spec = highlight_spec[cell.id]
453+
except KeyError:
454+
pass
415455
plot_2D_cell_morphology(
416456
offset=pos,
417457
cell=cell,
@@ -427,6 +467,7 @@ def plot_2D(
427467
nogui=True,
428468
autoscale=False,
429469
square=False,
470+
highlight_spec=cell_highlight_spec,
430471
)
431472

432473
add_scalebar_to_matplotlib_plot(axis_min_max, ax)
@@ -467,6 +508,7 @@ def plot_2D_cell_morphology(
467508
datamin: typing.Optional[float] = None,
468509
datamax: typing.Optional[float] = None,
469510
colormap_name: str = "viridis",
511+
highlight_spec: typing.Optional[typing.Dict[typing.Any, typing.Any]] = None,
470512
):
471513
"""Plot the detailed 2D morphology of a cell in provided plane.
472514
@@ -534,6 +576,16 @@ def plot_2D_cell_morphology(
534576
:type datamin: float
535577
:param datamax: max limits of data (useful to compare different plots)
536578
:type datamax: float
579+
:param highlight_spec: dictionary that allows passing some
580+
specifications to allow highlighting of particular elements. Mostly
581+
only helpful for marking segments on multi-compartmental cells. In the
582+
main dictionary are more dictionaries, one for each segment id which
583+
will be the key:
584+
585+
- marker_color: color of the marker
586+
- marker_size: width of the marker
587+
588+
:type highlight_spec: dict
537589
538590
:raises: ValueError if `cell` is None
539591
@@ -543,6 +595,10 @@ def plot_2D_cell_morphology(
543595
"No cell provided. If you would like to plot a network of point neurons, consider using `plot_2D_point_cells` instead"
544596
)
545597

598+
if highlight_spec is None:
599+
highlight_spec = {}
600+
logging.debug("highlight_spec is " + str(highlight_spec))
601+
546602
try:
547603
soma_segs = cell.get_all_segments_in_group("soma_group")
548604
except Exception:
@@ -599,12 +655,27 @@ def plot_2D_cell_morphology(
599655
d = seg.distal
600656
width = (p.diameter + d.diameter) / 2
601657

658+
segment_spec = {
659+
"marker_size": None,
660+
"marker_color": None,
661+
}
662+
try:
663+
segment_spec.update(highlight_spec[str(seg.id)])
664+
# if there's no spec for this segment
665+
except KeyError:
666+
logger.debug("No segment highlight spec found for segment" + str(seg.id))
667+
668+
logger.debug("segment_spec for " + str(seg.id) + " is" + str(segment_spec))
669+
602670
if width < min_width:
603671
width = min_width
604672

605673
if plot_type == "constant":
606674
width = min_width
607675

676+
if segment_spec["marker_size"] is not None:
677+
width = float(segment_spec["marker_size"])
678+
608679
if overlay_data and acolormap and norm:
609680
try:
610681
seg_color = acolormap(norm(overlay_data[seg.id]))
@@ -617,6 +688,9 @@ def plot_2D_cell_morphology(
617688
elif seg.id in axon_segs:
618689
seg_color = "r"
619690

691+
if segment_spec["marker_color"] is not None:
692+
seg_color = segment_spec["marker_color"]
693+
620694
spherical = (
621695
p.x == d.x and p.y == d.y and p.z == d.z and p.diameter == d.diameter
622696
)

0 commit comments

Comments
 (0)