Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions doc/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,15 @@ class :class:`eegmegcalc.NYHeadModel`
:undoc-members:


Module :mod:`lfpykit.special`
=============================
.. automodule:: lfpykit.special
:members:
:show-inheritance:
:undoc-members:



Indices and tables
==================

Expand Down
4 changes: 2 additions & 2 deletions examples/Example_Arbor.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@
"metadata": {},
"outputs": [],
"source": [
"# Collect CV geometry data using arbor's place_pwlin methoood\n",
"# Collect CV geometry data using arbor's place_pwlin method\n",
"p = arbor.place_pwlin(morphology)\n",
"x, y, z, d = [], [], [], []\n",
"for m in I_m_meta:\n",
Expand Down Expand Up @@ -354,7 +354,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.10"
"version": "3.10.2"
}
},
"nbformat": 4,
Expand Down
124 changes: 20 additions & 104 deletions examples/Example_Arbor_swc.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@
"the line source approximation implementation in class `LineSourcePotential` with a passive neuron model set up in Arbor (https://arbor.readthedocs.io, https://github.com/arbor-sim/arbor). \n",
"\n",
"The neuron receives sinusoid synaptic current input in one arbitrary chosen control volume (CV). \n",
"Its morphology is defined in the file `single_cell.swc`"
"Its morphology is defined in the file `single_cell.swc`\n",
"\n",
"The example produces comparable output as the `Example_Neuron_swc.ipynb` and `Example_LFPy_swc.ipynb` notebooks. \n",
"\n",
"This example showcase the use of `lfpykit.special.CellGeometryArbor` and `lfpykit.special.LineSourcePotential`, \n",
"two modified classes inherited from `lfpykit.CellGeometry` and `lfpykit.LineSourcePotential`, respectively. \n",
"The modifications allow using the full geometry detail from the `.swc` morphology file for computing the extracellular potential."
]
},
{
Expand Down Expand Up @@ -225,7 +231,8 @@
"metadata": {},
"source": [
"## Compute extracellular potentials\n",
"First we define a couple of classes to interface the LFPykit library (https://LFPykit.readthedocs.io, https://github.com/LFPy/LFPykit):"
"Combining the use of `lfpykit.special.CellGeometryArbor` to represent the coordinates of segments for each CV and \n",
"`lfpykit.special.LineSourcePotential` compute the extracellular potential"
]
},
{
Expand All @@ -234,40 +241,8 @@
"metadata": {},
"outputs": [],
"source": [
"class ArborCellGeometry(lfpykit.CellGeometry):\n",
" '''\n",
" Class inherited from ``lfpykit.CellGeometry`` for easier forward-model\n",
" predictions in Arbor that keeps track of arbor.segment information\n",
" for each CV.\n",
"\n",
" Parameters\n",
" ----------\n",
" p: ``arbor.place_pwlin`` object\n",
" 3-d locations and cables in a morphology (cf. ``arbor.place_pwlin``)\n",
" cables: ``list``\n",
" ``list`` of corresponding ``arbor.cable`` objects where transmembrane\n",
" currents are recorded (cf. ``arbor.cable_probe_total_current_cell``)\n",
"\n",
" See also\n",
" --------\n",
" lfpykit.CellGeometry\n",
" '''\n",
"\n",
" def __init__(self, p, cables):\n",
" x, y, z, d = [np.array([], dtype=float).reshape((0, 2))] * 4\n",
" c_ind = np.array([], dtype=int) # tracks which CV owns segment\n",
" for i, m in enumerate(cables):\n",
" segs = p.segments([m])\n",
" for j, seg in enumerate(segs):\n",
" x = np.row_stack([x, [seg.prox.x, seg.dist.x]])\n",
" y = np.row_stack([y, [seg.prox.y, seg.dist.y]])\n",
" z = np.row_stack([z, [seg.prox.z, seg.dist.z]])\n",
" d = np.row_stack(\n",
" [d, [seg.prox.radius * 2, seg.dist.radius * 2]])\n",
" c_ind = np.r_[c_ind, i]\n",
"\n",
" super().__init__(x=x, y=y, z=z, d=d)\n",
" self._c_ind = c_ind"
"# create ``CellGeometryArbor`` instance\n",
"cell_geometry = lfpykit.special.CellGeometryArbor(p, I_m_meta)"
]
},
{
Expand All @@ -276,65 +251,6 @@
"metadata": {},
"outputs": [],
"source": [
"class ArborLineSourcePotential(lfpykit.LineSourcePotential):\n",
" '''subclass of ``lfpykit.LineSourcePotential`` modified for\n",
" instances of ``ArborCellGeometry``.\n",
" Each CV may consist of several segments , and this implementation\n",
" accounts for their contributions normalized by surface area, that is,\n",
" we assume constant transmembrane current density per area across each CV\n",
" and constant current source density per unit length per segment\n",
" (inherent in the line-source approximation).\n",
"\n",
" Parameters\n",
" ----------\n",
" cell: object\n",
" ``ArborCellGeometry`` instance or similar.\n",
" x: ndarray of floats\n",
" x-position of measurement sites (µm)\n",
" y: ndarray of floats\n",
" y-position of measurement sites (µm)\n",
" z: ndarray of floats\n",
" z-position of measurement sites (µm)\n",
" sigma: float > 0\n",
" scalar extracellular conductivity (S/m)\n",
"\n",
" See also\n",
" --------\n",
" lfpykit.LineSourcePotential\n",
" '''\n",
"\n",
" def __init__(self, **kwargs):\n",
" super().__init__(**kwargs)\n",
" self._get_transformation_matrix = super().get_transformation_matrix\n",
"\n",
" def get_transformation_matrix(self):\n",
" '''Get linear response matrix\n",
"\n",
" Returns\n",
" -------\n",
" response_matrix: ndarray\n",
" shape (n_coords, n_cs) ndarray\n",
" '''\n",
" M_tmp = self._get_transformation_matrix()\n",
" n_cs = np.unique(self.cell._c_ind).size\n",
" M = np.zeros((self.x.size, n_cs))\n",
" for i in range(n_cs):\n",
" inds = self.cell._c_ind == i\n",
" M[:, i] = M_tmp[:, inds] @ (self.cell.area[inds] /\n",
" self.cell.area[inds].sum())\n",
"\n",
" return M"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"# create ``ArborCellGeometry`` instance\n",
"cell_geometry = ArborCellGeometry(p, I_m_meta)\n",
"\n",
"# define locations where extracellular potential is predicted in vicinity\n",
"# of cell.\n",
"# Axis limits [x-min, x-max, y-min, y-max] (µm)\n",
Expand All @@ -347,8 +263,8 @@
" int(np.diff(axis[2:]) // dz) + 1))\n",
"Z = np.zeros_like(X)\n",
"\n",
"# ``ArborLineSourcePotential`` instance, get mapping for all segments per CV\n",
"lsp = ArborLineSourcePotential(cell=cell_geometry,\n",
"# ``lfpykit.special.LineSourcePotential`` instance, get mapping for all segments per CV\n",
"lsp = lfpykit.special.LineSourcePotential(cell=cell_geometry,\n",
" x=X.flatten(),\n",
" y=Y.flatten(),\n",
" z=Z.flatten())\n",
Expand All @@ -368,7 +284,7 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -398,7 +314,7 @@
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -423,7 +339,7 @@
" colors = [plt.get_cmap(cmap)(norm(v)) for v in V_m]\n",
" zips = []\n",
" for i in range(V_m.size):\n",
" inds = cell_geometry._c_ind == i\n",
" inds = cell_geometry._compartment_index == i\n",
" zips.append(create_polygon(cell_geometry.x[inds, ].flatten(),\n",
" cell_geometry.y[inds, ].flatten(),\n",
" cell_geometry.d[inds, ].flatten()))\n",
Expand All @@ -436,7 +352,7 @@
},
{
"cell_type": "code",
"execution_count": 13,
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -464,7 +380,7 @@
},
{
"cell_type": "code",
"execution_count": 14,
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -492,7 +408,7 @@
},
{
"cell_type": "code",
"execution_count": 15,
"execution_count": 14,
"metadata": {},
"outputs": [
{
Expand All @@ -501,7 +417,7 @@
"Text(0.5, 1.0, '$V_e$ and $V_m$ at $t$=499.0 ms')"
]
},
"execution_count": 15,
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
},
Expand Down
Loading