Skip to content

Commit e12e0b0

Browse files
asiaszmekccluri
authored andcommitted
sKCSD (#14)
* sKCSD support for swc morphologies * Params improvement * Small test * Ploting function for skCSD results, 2D morphology plot improved * Comment added * Loader, saver for simulation * Fix slashes in paths * Make Python2 and Python3 compatible * Empty __init__ file * Add untracked directories * Tutorial data * Comments on morphology and electrode positions data format * Ignore *~ and #* * Object loading and storing data for sKCSD3D * Find paths of the morphology, LFP and electrode positions files * Data for tests * Test loading morphology * Load electrode positions * Load data * Ball and stick model with 8 electrodes * Ball and stick model with 16 electrodes * Ball and stick model with 128 electrodes * Correct morphology * Use data loder * Correct morphology * Store preprocessed data in data directory * Correct axes labels in morphology plots * Fix paths in sKCD3D example * Add extent * Calculate kernels for ball and stick * Fix plotting neurons * Change pickle to json * Script for running simulations and different morphologies * Ignore backup files while loading files for sKCSD * Fix paths * Choose which electrode to plot * Script for generating fig 2 * Load only swc files * Remove unnecessary prints * Loop over electrode number * Save membrane current * Add tstop * Fix elctrode distance bug * Bug fix -- last segment does have a parent * Loop back using parent information * Fix setting correct electrode positions * Make figure * Wider range for morphology * Use parent section information to build swc tree * Fix scaling in sKCSD3D example * Test if all the sources are distributed within the cell * Save ids of dendrites connected while enclosing morphology * Change width of gauss and source number in example * Fix comparing paths in loadData test * Add checking if all branches are covered with loops * Test data * Ignore pngs * Test kCSD calculation for ball and stick * Save loops as an array * Try out more points in fig 2 * Fix imports and paths * More interpolation points for potential estimation for skCSD * Implement KCSD calculation using points on the 1D morphology for estimation. cell_pos, which stores dendrite locations on the morphology loop, was added to sKCSDcell. B tilda uses distance between sources and dendrites on the morphology loop now. B uses distance between source positions (x,y,z) and electrode positions now. Add transformation of CSD which is calculated on the morphology loop to cartesian coordinates. Basis was switch to 1D. The grid parameters are no longer necessary. * Sinusoid synaptic stimulation for fig 1 * Remove unnecessary parameters * Dendritic segment cannot be smaller than 2 um for CSD and potential transformation * Remove unnecessary grid parameters from example of sKCSD reconstruction * First version of the code * Change output filenames * Cosine synaptic stimulation with frequency dependent on segment location * CSD calculation as default * Code refactoring * Save potential and current on 1D morphology and 3D grid * Move csd transformation from sKCSD3D to sKCSDcell * Hoc file to generate y-shaped neuron * Fix bug in finding parent * Code refactorization for csd and potential calculation in 3D * Symmetric stimulation of a Y-shaped neuron * First version of Fig 3 * Random grid * Fig 4 of eLife article * Change script names to match figure numbers in the published article * Change get to pop to notify user if he used nonexistent key arguments * Make one figure * Create separate directory for figures * Fix typo * Move most common sequences of operations to module functions * Fig 7 * Domi electrodes * Correct Domi path * Correct L1 error calculation * Make compatible with new LFPy * Small branched morphology for tests * Account for branches longer than shorterst branch * Add small non-trivial neuron morphology to test transformation to 3D * Add extent argument to plotting with imshow * Remove looping over R and lambda. Clean up the code * Remove unused code * Return cell object after simulations not just the directory * Hex grid and injection of oscillatory current with random synaptic stimulation * Set dt * Correct potential calculation Intergrate over s from -2R to morphology loop length +2R of source divided by position (Eq 17). * .5 ms simulation dt * Add hexagonal grid parameter to keyword arguments of simulation functions * A more reasonable default R * Print path when saving csd * Fix order in oscillatory stimulation * Default grain of the 3D grid 2e-6 * Add more buttons * Use classmethod setupClass instead of setUp function * Clean up code to reflect changes in sKCSD3D * Assure absolute imports (Python3 compatibility) * Python 3 compatibility -- absolute imports * Add changing dt * Take into account point 0 of the morphology * Add option of returning CSD/potential in the loop space * Add test checking 1D loop to 3D cartesian interpolation * Specify the initial point at the beginning of the morphology file * Loop over possible R and lambda values Transform Dori's lambda values to kCSD lambda values: in kCSD Gaussian functions are normalized (divided) by (2*pi)^0.5*R, kernels are normalized by number of sources and potentials are divided by 4*pi*sigma. * Add interpolation tests for the larger cell * Add interpolation tests for the larger cell * Simplify placing sources Fist loop around morphology (same algorythm as before, without placing sources). Place sources on the morphology. Find source cartesian coordinates using interpolation and loop coordinates, both on the morphology loop and in 3D. * Fix import and typo * Fix saving 3D morphology * Remove unused variables * Add max_dist tests * Further tests for total length of the morphology loop Check if max_dist calculated during looping over morphology is equall to total distance calculated using the morphology file. * Add docstrings. Remove unused function * Add class description * Add autorship * Change sKCSD3D class name to sKCSD * Rename sKCSD3D to sKCSD * Remove weights * Works with skmonaco * Add tests for sKCSDcell.points_in_between() * Change cell to one used in tutorials * Divide get_grid to 2 functions * Y-shaped neuron * Test finding 3D loop coordinates * Test continuity * Remove unnecessary prints * Add dist_table_density to docstring * On transformation parameter for sKCSD '3D' -- transforms quantity (CSD or potential) to 3D 'segments' -- transforms quantity to neuron's segments None -- no transformation, quantity is in the morphology loop space * Test, if CSD/potential is the right shape * Move loop to segment transformation to sKCSDcell object * Save CSD and potential in loop space * Fix too many arguments in saving simulations * Basic version of plotting results in 3D, loop and segment space * Extent matching 3D properties of the cell * Move ploting maps to plotting_functions * Ball and stick data for tests * import run_LFP after compiling sinsyn.mod * Move compiling sinsyn.mod before importing LFPy * Move specifying saving directory to utility functions * Remove unused buttons * Linear interpolation on xyz position on the morphology loop * 1 or 3 column files with electrode positions * Move loadData to tutorials * Lower cosine injection * Add running sKCSD for arbitrary data Specify path to morphology, electrode positions and LFP. Move loadData to tutorials. * loadData in tutorials * Fix lambda range
1 parent 30da013 commit e12e0b0

58 files changed

Lines changed: 14001 additions & 15 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,16 @@ target/
6262

6363
#Ipython Notebook
6464
.ipynb_checkpoints
65+
#testing files
66+
testing/
67+
68+
#data
69+
examples/
70+
.idea/
71+
preprocessed_data/
72+
raw_data/
73+
*~
74+
/#*
75+
*png
76+
Data/gang_min/
77+
simulation

corelib/KCSD.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,18 @@
99
KCSD1D[1][2], KCSD2D[1], KCSD3D[1], MoIKCSD[1]
1010
1111
"""
12-
from __future__ import division
12+
from __future__ import division, print_function, absolute_import
1313

1414
import numpy as np
1515
from scipy import special, integrate, interpolate
1616
from scipy.spatial import distance
1717
from numpy.linalg import LinAlgError
18-
import utility_functions as utils
19-
import basis_functions as basis
18+
import sys
19+
import os
20+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
21+
22+
import corelib.utility_functions as utils
23+
import corelib.basis_functions as basis
2024

2125
# from . import utility_functions as utils
2226
# from . import basis_functions as basis
@@ -112,6 +116,7 @@ def parameters(self, **kwargs):
112116
self.xmin = kwargs.pop('xmin', np.min(self.ele_pos[:, 0]))
113117
self.xmax = kwargs.pop('xmax', np.max(self.ele_pos[:, 0]))
114118
self.gdx = kwargs.pop('gdx', 0.01*(self.xmax - self.xmin))
119+
self.dist_table_density = kwargs.pop('dist_table_density',20)
115120
if self.dim >= 2:
116121
self.ext_y = kwargs.pop('ext_y', 0.0)
117122
self.ymin = kwargs.pop('ymin', np.min(self.ele_pos[:, 1]))
@@ -139,7 +144,7 @@ def method(self):
139144
self.update_b_src() # update crskernel
140145
self.update_b_interp_pot() # update pot interp
141146

142-
def create_lookup(self, dist_table_density=20):
147+
def create_lookup(self):
143148
"""Creates a table for easy potential estimation from CSD.
144149
Updates and Returns the potentials due to a
145150
given basis source like a lookup
@@ -148,10 +153,10 @@ def create_lookup(self, dist_table_density=20):
148153
Parameters
149154
----------
150155
dist_table_density : int
151-
number of distance values at which potentials are computed.
156+
number of distance points at which potentials are computed.
152157
Default 100
153158
"""
154-
xs = np.logspace(0., np.log10(self.dist_max+1.), dist_table_density)
159+
xs = np.logspace(0., np.log10(self.dist_max+1.), self.dist_table_density)
155160
xs = xs - 1.0 # starting from 0
156161
dist_table = np.zeros(len(xs))
157162
for i, pos in enumerate(xs):
@@ -162,7 +167,6 @@ def create_lookup(self, dist_table_density=20):
162167
self.basis)
163168
self.interpolate_pot_at = interpolate.interp1d(xs, dist_table,
164169
kind='cubic')
165-
166170
def update_b_pot(self):
167171
"""Updates the b_pot - array is (#_basis_sources, #_electrodes)
168172
Updates the k_pot - array is (#_electrodes, #_electrodes) K(x,x')
@@ -190,6 +194,7 @@ def update_b_src(self):
190194
----------
191195
None
192196
"""
197+
#Tu jest basis!
193198
self.b_src = self.basis(self.src_estm_dists, self.R).T
194199
self.k_interp_cross = np.dot(self.b_src, self.b_pot) # K_t(x,y) Eq17
195200
self.k_interp_cross /= self.n_src
@@ -407,6 +412,9 @@ def __init__(self, ele_pos, pots, **kwargs):
407412
lambd : float
408413
regularization parameter for ridge regression
409414
Defaults to 0.
415+
dist_table_density : int
416+
size of the potential interpolation table
417+
Defaults to 20
410418
411419
Raises
412420
------

corelib/basis_functions.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@
1010
Laboratory of Neuroinformatics,
1111
Nencki Institute of Experimental Biology, Warsaw.
1212
"""
13-
from __future__ import division
14-
13+
from __future__ import division, print_function, absolute_import
1514
import numpy as np
1615

1716
def gauss(d, stdev, dim):
@@ -66,7 +65,7 @@ def gauss_1D(d, three_stdev):
6665
-------
6766
Z : (three_std/3)*(1/2*pi)*(exp(-0.5)*stddev**(-2) *(d**2))
6867
"""
69-
stdev = three_stdev/3.0
68+
stdev = three_stdev/3
7069
Z = gauss(d, stdev, 1)
7170
return Z
7271

@@ -121,7 +120,7 @@ def gauss_2D(d, three_stdev):
121120
Z : function
122121
Normalized gaussian 2D function
123122
"""
124-
stdev = three_stdev/3.0
123+
stdev = three_stdev/3
125124
Z = gauss(d, stdev, 2)
126125
return Z
127126

@@ -158,7 +157,7 @@ def gauss_3D(d, three_stdev):
158157
Z : funtion
159158
Normalized gaussian 3D function
160159
"""
161-
stdev = three_stdev/3.0
160+
stdev = three_stdev/3
162161
Z = gauss(d, stdev, 3)
163162
return Z
164163

corelib/bresenhamline.py

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
"""
2+
N-D Bresenham line algo
3+
4+
5+
Copyright 2012 Vikas Dhiman
6+
7+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8+
9+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10+
11+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12+
13+
"""
14+
import numpy as np
15+
16+
def _bresenhamline_nslope(slope):
17+
"""
18+
Normalize slope for Bresenham's line algorithm.
19+
>>> s = np.array([[-2, -2, -2, 0]])
20+
>>> _bresenhamline_nslope(s)
21+
array([[-1., -1., -1., 0.]])
22+
>>> s = np.array([[0, 0, 0, 0]])
23+
>>> _bresenhamline_nslope(s)
24+
array([[ 0., 0., 0., 0.]])
25+
>>> s = np.array([[0, 0, 9, 0]])
26+
>>> _bresenhamline_nslope(s)
27+
array([[ 0., 0., 1., 0.]])
28+
"""
29+
scale = np.amax(np.abs(slope), axis=1).reshape(-1, 1)
30+
zeroslope = (scale == 0).all(1)
31+
scale[zeroslope] = np.ones(1)
32+
normalizedslope = np.array(slope, dtype=np.double) / scale
33+
normalizedslope[zeroslope] = np.zeros(slope[0].shape)
34+
return normalizedslope
35+
36+
def _bresenhamlines(start, end, max_iter):
37+
"""
38+
Returns npts lines of length max_iter each. (npts x max_iter x dimension)
39+
>>> s = np.array([[3, 1, 9, 0],[0, 0, 3, 0]])
40+
>>> _bresenhamlines(s, np.zeros(s.shape[1]), max_iter=-1)
41+
array([[[ 3, 1, 8, 0],
42+
[ 2, 1, 7, 0],
43+
[ 2, 1, 6, 0],
44+
[ 2, 1, 5, 0],
45+
[ 1, 0, 4, 0],
46+
[ 1, 0, 3, 0],
47+
[ 1, 0, 2, 0],
48+
[ 0, 0, 1, 0],
49+
[ 0, 0, 0, 0]],
50+
<BLANKLINE>
51+
[[ 0, 0, 2, 0],
52+
[ 0, 0, 1, 0],
53+
[ 0, 0, 0, 0],
54+
[ 0, 0, -1, 0],
55+
[ 0, 0, -2, 0],
56+
[ 0, 0, -3, 0],
57+
[ 0, 0, -4, 0],
58+
[ 0, 0, -5, 0],
59+
[ 0, 0, -6, 0]]])
60+
"""
61+
if max_iter == -1:
62+
max_iter = np.amax(np.amax(np.abs(end - start), axis=1))
63+
npts, dim = start.shape
64+
nslope = _bresenhamline_nslope(end - start)
65+
66+
# steps to iterate on
67+
stepseq = np.arange(1, max_iter + 1)
68+
stepmat = np.tile(stepseq, (dim, 1)).T
69+
70+
# some hacks for broadcasting properly
71+
bline = start[:, np.newaxis, :] + nslope[:, np.newaxis, :] * stepmat
72+
73+
# Approximate to nearest int
74+
return np.array(np.rint(bline), dtype=start.dtype)
75+
76+
def bresenhamline(start, end, max_iter=5):
77+
"""
78+
Returns a list of points from (start, end] by ray tracing a line b/w the
79+
points.
80+
Parameters:
81+
start: An array of start points (number of points x dimension)
82+
end: An end points (1 x dimension)
83+
or An array of end point corresponding to each start point
84+
(number of points x dimension)
85+
max_iter: Max points to traverse. if -1, maximum number of required
86+
points are traversed
87+
Returns:
88+
linevox (n x dimension) A cumulative array of all points traversed by
89+
all the lines so far.
90+
>>> s = np.array([[3, 1, 9, 0],[0, 0, 3, 0]])
91+
>>> bresenhamline(s, np.zeros(s.shape[1]), max_iter=-1)
92+
array([[ 3, 1, 8, 0],
93+
[ 2, 1, 7, 0],
94+
[ 2, 1, 6, 0],
95+
[ 2, 1, 5, 0],
96+
[ 1, 0, 4, 0],
97+
[ 1, 0, 3, 0],
98+
[ 1, 0, 2, 0],
99+
[ 0, 0, 1, 0],
100+
[ 0, 0, 0, 0],
101+
[ 0, 0, 2, 0],
102+
[ 0, 0, 1, 0],
103+
[ 0, 0, 0, 0],
104+
[ 0, 0, -1, 0],
105+
[ 0, 0, -2, 0],
106+
[ 0, 0, -3, 0],
107+
[ 0, 0, -4, 0],
108+
[ 0, 0, -5, 0],
109+
[ 0, 0, -6, 0]])
110+
"""
111+
# Return the points as a single array
112+
return _bresenhamlines(start, end, max_iter).reshape(-1, start.shape[-1])
113+
114+
115+
if __name__ == "__main__":
116+
import doctest
117+
doctest.testmod()

0 commit comments

Comments
 (0)