From c2371c06835026c0270930f057f722be2c9a7223 Mon Sep 17 00:00:00 2001 From: alejoe91 Date: Thu, 8 Dec 2016 12:13:15 +0100 Subject: [PATCH 01/11] square contact added --- LFPy/recextelectrode.py | 94 +++++++++++++++++++++++++++++------------ 1 file changed, 68 insertions(+), 26 deletions(-) diff --git a/LFPy/recextelectrode.py b/LFPy/recextelectrode.py index fc4e0980..368f1bde 100644 --- a/LFPy/recextelectrode.py +++ b/LFPy/recextelectrode.py @@ -40,6 +40,9 @@ class RecExtElectrodeSetup(object): n : int, if N is not None and r > 0, the number of points to use for each contact point in order to calculate average + square : bool, + if square is True, the electrode shape is a square and r is used + as square side method : str, ['linesource']/'pointsource'/'som_as_point' switch color : str, @@ -57,7 +60,7 @@ class RecExtElectrodeSetup(object): ''' def __init__(self, cell=None, sigma=0.3, x=np.array([0]), y=np.array([0]), z=np.array([0]), - N=None, r=None, n=None, r_z=None, + N=None, r=None, n=None, shape=None, r_z=None, perCellLFP=False, method='linesource', color='g', marker='o', from_file=False, cellfile=None, verbose=False, @@ -100,6 +103,13 @@ def __init__(self, cell=None, sigma=0.3, self.r = r self.n = n + if shape is None: + self.shape = 'circle' + elif shape in ['circle', 'square']: + self.shape = shape + else: + raise ValueError('The shape argument must be either: None, \'circle\', \'square\'') + self.r_z = r_z self.perCellLFP = perCellLFP @@ -212,7 +222,7 @@ class RecExtElectrode(RecExtElectrodeSetup): def __init__(self, cell=None, sigma=0.3, x=np.array([0]), y=np.array([0]), z=np.array([0]), - N=None, r=None, n=0, r_z=None, + N=None, r=None, n=0, shape=None, r_z=None, perCellLFP=False, method='linesource', color='g', marker='o', from_file=False, cellfile=None, verbose=False, @@ -227,7 +237,7 @@ def __init__(self, cell=None, sigma=0.3, sigma : ''' RecExtElectrodeSetup.__init__(self, cell, sigma, x, y, z, - N, r, n, r_z, perCellLFP, + N, r, n, shape, r_z, perCellLFP, method, color, marker, from_file, cellfile, verbose, seedvalue, **kwargs) @@ -236,6 +246,7 @@ def calc_lfp(self, t_indices=None, cell=None): '''Calculate LFP on electrode geometry from all cell instances. Will chose distributed calculated if electrode contain 'n', 'N', and 'r' ''' + if cell is not None: self.cell = cell self._test_imem_sum() @@ -252,8 +263,8 @@ def calc_lfp(self, t_indices=None, cell=None): raise ValueError("n = %i must be larger that 1" % self.n) else: pass - - [self.circle, self.offsets, LFP_temp] = \ + + [self.circle_circum, self.offsets, LFP_temp] = \ self._lfp_el_pos_calc_dist(t_indices=t_indices, r_limit=self.cell.diam/2) if self.verbose: @@ -303,11 +314,12 @@ def _lfp_el_pos_calc_dist(self, ): ''' Calc. of LFP over an n-point integral approximation over flat - electrode surface with radius r. The locations of these n points on - the electrode surface are random, within the given radius. ''' + electrode surface: circle of radius r or square of side r. The + locations of these n points on the electrode surface are random, + within the given surface. ''' lfp_el_pos = np.zeros(self.LFP.shape) offsets = {} - circle = {} + circle_circ = {} def create_crcl(m, i): '''make circumsize of contact point''' @@ -327,6 +339,21 @@ def create_crcl(m, i): return crclx, crcly, crclz + def create_sqr(m, i): + '''make circle in which square contact is circumscribed''' + sqr = np.zeros((m, 3)) + for j in range(m): + B = [(np.random.rand() - 0.5), + (np.random.rand() - 0.5), + (np.random.rand() - 0.5)] + sqr[j,] = np.cross(self.N[i,], B)/np.linalg.norm(np.cross(self.N[i,], B)) * self.r * np.sqrt(2)/2 + + sqrx = sqr[:, 0] + self.x[i] + sqry = sqr[:, 1] + self.y[i] + sqrz = sqr[:, 2] + self.z[i] + + return sqrx, sqry, sqrz + def calc_xyz_n(i): '''calculate some offsets''' #offsets and radii init @@ -336,18 +363,27 @@ def calc_xyz_n(i): #assert the same random numbers are drawn every time if self.seedvalue is not None: np.random.seed(self.seedvalue) - for j in range(self.n): - A = [(np.random.rand()-0.5)*self.r*2, - (np.random.rand()-0.5)*self.r*2, - (np.random.rand()-0.5)*self.r*2] - offs[j, ] = np.cross(self.N[i, ], A) - r2[j] = offs[j, 0]**2 + offs[j, 1]**2 + offs[j, 2]**2 - while r2[j] > self.r**2: + + if self.shape is 'circle': + for j in range(self.n): A = [(np.random.rand()-0.5)*self.r*2, (np.random.rand()-0.5)*self.r*2, (np.random.rand()-0.5)*self.r*2] offs[j, ] = np.cross(self.N[i, ], A) r2[j] = offs[j, 0]**2 + offs[j, 1]**2 + offs[j, 2]**2 + while r2[j] > self.r**2: + A = [(np.random.rand()-0.5)*self.r*2, + (np.random.rand()-0.5)*self.r*2, + (np.random.rand()-0.5)*self.r*2] + offs[j, ] = np.cross(self.N[i, ], A) + r2[j] = offs[j, 0]**2 + offs[j, 1]**2 + offs[j, 2]**2 + elif self.shape is 'square': + for j in range(self.n): + A = [(np.random.rand()-0.5), + (np.random.rand()-0.5), + (np.random.rand()-0.5)] + offs[j, ] = np.cross(self.N[i, ], A)*self.r + r2[j] = offs[j, 0]**2 + offs[j, 1]**2 + offs[j, 2]**2 x_n = offs[:, 0] + self.x[i] y_n = offs[:, 1] + self.y[i] @@ -387,9 +423,6 @@ def loop_over_points(x_n, y_n, z_n): #fetch offsets: x_n, y_n, z_n = calc_xyz_n(i) - - - #fill in with contact average lfp_el_pos[i] = loop_over_points(x_n, y_n, z_n) #lfp_e.mean(axis=0) @@ -413,15 +446,24 @@ def loop_over_points(x_n, y_n, z_n): } - #fetch circle around contact - crcl = create_crcl(m, i) - circle[i] = { - 'x' : crcl[0], - 'y' : crcl[1], - 'z' : crcl[2], - } + #fetch circumscribed circle around contact + if self.shape is 'circle': + crcl = create_crcl(m, i) + circle_circ[i] = { + 'x' : crcl[0], + 'y' : crcl[1], + 'z' : crcl[2], + } + elif self.shape is 'square': + sqr = create_sqr(m, i) + circle_circ[i] = { + 'x': sqr[0], + 'y': sqr[1], + 'z': sqr[2], + } + - return circle, offsets, lfp_el_pos + return circle_circ, offsets, lfp_el_pos From ed8c0e2f6a860d1017aaabb2c25e55e21d44021a Mon Sep 17 00:00:00 2001 From: alejoe91 Date: Tue, 10 Jan 2017 12:20:32 +0100 Subject: [PATCH 02/11] Cell.set_pos() fixed when cell has pt3d --- LFPy/cell.py | 68 ++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/LFPy/cell.py b/LFPy/cell.py index 98a5681a..fd2498a4 100644 --- a/LFPy/cell.py +++ b/LFPy/cell.py @@ -994,30 +994,28 @@ def set_pos(self, xpos=0, ypos=0, zpos=0): Move the cell geometry so that midpoint of soma section is in (xpos, ypos, zpos). If no soma pos, use the first segment ''' - diffx = self.somapos[0]-xpos - diffy = self.somapos[1]-ypos - diffz = self.somapos[2]-zpos - - + diffx = xpos-self.somapos[0] + diffy = ypos-self.somapos[1] + diffz = zpos-self.somapos[2] + self.somapos[0] = xpos self.somapos[1] = ypos self.somapos[2] = zpos #also update the pt3d_pos: if self.pt3d and hasattr(self, 'x3d'): - self._set_pt3d_pos() - else: - self.xstart -= diffx - self.ystart -= diffy - self.zstart -= diffz - - self.xend -= diffx - self.yend -= diffy - self.zend -= diffz + self._set_pt3d_pos(diffx, diffy, diffz) + + self.xstart += diffx + self.ystart += diffy + self.zstart += diffz + + self.xend += diffx + self.yend += diffy + self.zend += diffz self._calc_midpoints() self._update_synapse_positions() - def strip_hoc_objects(self): @@ -1454,14 +1452,14 @@ def _update_pt3d(self): self._collect_geometry() - def _set_pt3d_pos(self): + def _set_pt3d_pos(self, diffx=0, diffy=0, diffz=0): ''' - Offset pt3d geometry with cell.somapos + Offset pt3d geometry with differential displacement indicated in Cell.set_pos() ''' for i in range(len(self.x3d)): - self.x3d[i] += self.somapos[0] - self.y3d[i] += self.somapos[1] - self.z3d[i] += self.somapos[2] + self.x3d[i] += diffx + self.y3d[i] += diffy + self.z3d[i] += diffz self._update_pt3d() @@ -1566,43 +1564,43 @@ def _real_pt3d_positions(self, rel_pos): return x, y, z def _create_polygon(self, i, projection=('x', 'z')): - '''create a polygon to fill for each section''' + '''create a polygon to fill for each section''' x = getattr(self, projection[0]+'3d')[i] y = getattr(self, projection[1]+'3d')[i] #x = self.x3d[i] #z = self.z3d[i] d = self.diam3d[i] - - #calculate angles + + #calculate angles dx = np.diff(x) dy = np.diff(y) theta = np.arctan2(dy, dx) - + x = np.r_[x, x[::-1]] y = np.r_[y, y[::-1]] - + theta = np.r_[theta, theta[::-1]] d = np.r_[d, d[::-1]] - + #1st corner: x[0] -= 0.5 * d[0] * np.sin(theta[0]) y[0] += 0.5 * d[0] * np.cos(theta[0]) - + ##pt3d points between start and end of section, first side x[1:dx.size] -= 0.25 * d[1:dx.size] * ( np.sin(theta[:dx.size-1]) + np.sin(theta[1:dx.size])) y[1:dy.size] += 0.25 * d[1:dy.size] * ( np.cos(theta[:dy.size-1]) + np.cos(theta[1:dx.size])) - + #end of section, first side x[dx.size] -= 0.5 * d[dx.size] * np.sin(theta[dx.size]) y[dy.size] += 0.5 * d[dy.size] * np.cos(theta[dy.size]) - + #other side #end of section, second side x[dx.size+1] += 0.5 * d[dx.size+1] * np.sin(theta[dx.size]) y[dy.size+1] -= 0.5 * d[dy.size+1] * np.cos(theta[dy.size]) - + ##pt3d points between start and end of section, second side x[::-1][1:dx.size] += 0.25 * d[::-1][1:dx.size] * ( np.sin(theta[::-1][:dx.size-1]) + np.sin(theta[::-1][1:dx.size])) @@ -1612,7 +1610,7 @@ def _create_polygon(self, i, projection=('x', 'z')): #last corner: x[-1] += 0.5 * d[-1] * np.sin(theta[-1]) y[-1] -= 0.5 * d[-1] * np.cos(theta[-1]) - + return x, y def get_pt3d_polygons(self, projection=('x', 'z')): @@ -1645,7 +1643,7 @@ def get_pt3d_polygons(self, projection=('x', 'z')): plt.show() ''' - if len(projection) != 2: + if len(projection) != 2 or projection is '3d': raise ValueError("projection arg be a tuple like ('x', 'y')") if 'x' in projection and 'y' in projection: pass @@ -1653,9 +1651,11 @@ def get_pt3d_polygons(self, projection=('x', 'z')): pass elif 'y' in projection and 'z' in projection: pass + elif projection is '3d': + pass else: mssg = "projection must be a length 2 tuple of 'x', 'y' or 'z'!" - raise ValueError(messg) + raise ValueError(mssg) polygons = [] for i in range(len(self.x3d)): @@ -1751,7 +1751,7 @@ def get_idx_polygons(self, projection=('x', 'z')): pass else: mssg = "projection must be a length 2 tuple of 'x', 'y' or 'z'!" - raise ValueError(messg) + raise ValueError(mssg) polygons = [] for i in np.arange(self.totnsegs): From 840a08bdaecfecba856f1d7f122b085ec4e12628 Mon Sep 17 00:00:00 2001 From: alejoe91 Date: Tue, 10 Jan 2017 17:24:35 +0100 Subject: [PATCH 03/11] cleaned _create_polygon --- LFPy/cell.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/LFPy/cell.py b/LFPy/cell.py index fd2498a4..2f545ff7 100644 --- a/LFPy/cell.py +++ b/LFPy/cell.py @@ -1643,7 +1643,7 @@ def get_pt3d_polygons(self, projection=('x', 'z')): plt.show() ''' - if len(projection) != 2 or projection is '3d': + if len(projection) != 2: raise ValueError("projection arg be a tuple like ('x', 'y')") if 'x' in projection and 'y' in projection: pass @@ -1651,8 +1651,6 @@ def get_pt3d_polygons(self, projection=('x', 'z')): pass elif 'y' in projection and 'z' in projection: pass - elif projection is '3d': - pass else: mssg = "projection must be a length 2 tuple of 'x', 'y' or 'z'!" raise ValueError(mssg) From 051c569c286687a40c14f83efbc3d815487dec5c Mon Sep 17 00:00:00 2001 From: alejoe91 Date: Tue, 10 Jan 2017 18:05:25 +0100 Subject: [PATCH 04/11] cell.py cleaned --- LFPy/cell.py | 1 + 1 file changed, 1 insertion(+) diff --git a/LFPy/cell.py b/LFPy/cell.py index 2f545ff7..789d38b5 100644 --- a/LFPy/cell.py +++ b/LFPy/cell.py @@ -1643,6 +1643,7 @@ def get_pt3d_polygons(self, projection=('x', 'z')): plt.show() ''' + if len(projection) != 2: raise ValueError("projection arg be a tuple like ('x', 'y')") if 'x' in projection and 'y' in projection: From e2bd43190540f9c71f17e1378bb23baddf78a401 Mon Sep 17 00:00:00 2001 From: alejoe91 Date: Tue, 10 Jan 2017 18:07:44 +0100 Subject: [PATCH 05/11] recelec.py cleaned --- LFPy/cell.py | 2 +- LFPy/recextelectrode.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/LFPy/cell.py b/LFPy/cell.py index 789d38b5..01154ce5 100644 --- a/LFPy/cell.py +++ b/LFPy/cell.py @@ -1643,7 +1643,7 @@ def get_pt3d_polygons(self, projection=('x', 'z')): plt.show() ''' - + if len(projection) != 2: raise ValueError("projection arg be a tuple like ('x', 'y')") if 'x' in projection and 'y' in projection: diff --git a/LFPy/recextelectrode.py b/LFPy/recextelectrode.py index 368f1bde..e7dd4d15 100644 --- a/LFPy/recextelectrode.py +++ b/LFPy/recextelectrode.py @@ -236,6 +236,7 @@ def __init__(self, cell=None, sigma=0.3, cell : LFPy.Cell like object sigma : ''' + RecExtElectrodeSetup.__init__(self, cell, sigma, x, y, z, N, r, n, shape, r_z, perCellLFP, method, color, marker, from_file, From 4dc1a6ec05ba97a81f4aa9813c2a3ddba8f3adf6 Mon Sep 17 00:00:00 2001 From: alejoe91 Date: Tue, 10 Jan 2017 18:17:35 +0100 Subject: [PATCH 06/11] Revert "recelec.py cleaned" This reverts commit e2bd43190540f9c71f17e1378bb23baddf78a401. --- LFPy/cell.py | 2 +- LFPy/recextelectrode.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/LFPy/cell.py b/LFPy/cell.py index 01154ce5..789d38b5 100644 --- a/LFPy/cell.py +++ b/LFPy/cell.py @@ -1643,7 +1643,7 @@ def get_pt3d_polygons(self, projection=('x', 'z')): plt.show() ''' - + if len(projection) != 2: raise ValueError("projection arg be a tuple like ('x', 'y')") if 'x' in projection and 'y' in projection: diff --git a/LFPy/recextelectrode.py b/LFPy/recextelectrode.py index e7dd4d15..368f1bde 100644 --- a/LFPy/recextelectrode.py +++ b/LFPy/recextelectrode.py @@ -236,7 +236,6 @@ def __init__(self, cell=None, sigma=0.3, cell : LFPy.Cell like object sigma : ''' - RecExtElectrodeSetup.__init__(self, cell, sigma, x, y, z, N, r, n, shape, r_z, perCellLFP, method, color, marker, from_file, From 116c4b02c285babe8f1277004dc224d9d13a8cf4 Mon Sep 17 00:00:00 2001 From: alejoe91 Date: Tue, 10 Jan 2017 18:17:45 +0100 Subject: [PATCH 07/11] Revert "cell.py cleaned" This reverts commit 051c569c286687a40c14f83efbc3d815487dec5c. --- LFPy/cell.py | 1 - 1 file changed, 1 deletion(-) diff --git a/LFPy/cell.py b/LFPy/cell.py index 789d38b5..2f545ff7 100644 --- a/LFPy/cell.py +++ b/LFPy/cell.py @@ -1643,7 +1643,6 @@ def get_pt3d_polygons(self, projection=('x', 'z')): plt.show() ''' - if len(projection) != 2: raise ValueError("projection arg be a tuple like ('x', 'y')") if 'x' in projection and 'y' in projection: From 554792da21ffd0c2aa8cae3ac8e7492d517cbfa2 Mon Sep 17 00:00:00 2001 From: alejoe91 Date: Tue, 10 Jan 2017 18:40:34 +0100 Subject: [PATCH 08/11] cleaned --- LFPy/recextelectrode.py | 1 + 1 file changed, 1 insertion(+) diff --git a/LFPy/recextelectrode.py b/LFPy/recextelectrode.py index 4d4726f3..20ffb383 100644 --- a/LFPy/recextelectrode.py +++ b/LFPy/recextelectrode.py @@ -103,6 +103,7 @@ def __init__(self, cell=None, sigma=0.3, self.r = r self.n = n + if shape is None: self.shape = 'circle' elif shape in ['circle', 'square']: From d05f4c8c7984c52b3a3730b7d2aaa9629fc0bcaf Mon Sep 17 00:00:00 2001 From: alejoe91 Date: Wed, 11 Jan 2017 16:35:39 +0100 Subject: [PATCH 09/11] reinserted if-else, kept diffx, diffy, diffz --- LFPy/cell.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/LFPy/cell.py b/LFPy/cell.py index 2f545ff7..d7d6fda7 100644 --- a/LFPy/cell.py +++ b/LFPy/cell.py @@ -1005,14 +1005,14 @@ def set_pos(self, xpos=0, ypos=0, zpos=0): #also update the pt3d_pos: if self.pt3d and hasattr(self, 'x3d'): self._set_pt3d_pos(diffx, diffy, diffz) + else: + self.xstart += diffx + self.ystart += diffy + self.zstart += diffz - self.xstart += diffx - self.ystart += diffy - self.zstart += diffz - - self.xend += diffx - self.yend += diffy - self.zend += diffz + self.xend += diffx + self.yend += diffy + self.zend += diffz self._calc_midpoints() self._update_synapse_positions() From 2dd0a630e7538f59054a545a19cc1905d56c2e66 Mon Sep 17 00:00:00 2001 From: alejoe91 Date: Wed, 11 Jan 2017 17:59:14 +0100 Subject: [PATCH 10/11] inserted somapos = (0,0,0) at beginning --- LFPy/cell.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/LFPy/cell.py b/LFPy/cell.py index d7d6fda7..78823a0d 100644 --- a/LFPy/cell.py +++ b/LFPy/cell.py @@ -209,6 +209,7 @@ def __init__(self, morphology, #Gather geometry, set position and rotation of morphology self._collect_geometry() if hasattr(self, 'somapos'): + self.somapos = [0, 0, 0] self.set_pos() else: if self.verbose: @@ -568,9 +569,9 @@ def _collect_geometry(self): _collect_geometry_neuron(self) self._calc_midpoints() - + self.somaidx = self.get_idx(section='soma') - + if self.somaidx.size > 1: xmids = self.xmid[self.somaidx] ymids = self.ymid[self.somaidx] @@ -595,6 +596,8 @@ def _collect_geometry(self): self.somapos[2] = self.zmid[self.somaidx] else: raise Exception('Huh?!') + + def _calc_midpoints(self): '''Calculate midpoints of each segment''' @@ -998,6 +1001,8 @@ def set_pos(self, xpos=0, ypos=0, zpos=0): diffy = ypos-self.somapos[1] diffz = zpos-self.somapos[2] + print diffx, diffy, diffz + self.somapos[0] = xpos self.somapos[1] = ypos self.somapos[2] = zpos @@ -1013,7 +1018,7 @@ def set_pos(self, xpos=0, ypos=0, zpos=0): self.xend += diffx self.yend += diffy self.zend += diffz - + self._calc_midpoints() self._update_synapse_positions() From 7502ffe0e267e7f9bd38f35f7a860e72ad7b800c Mon Sep 17 00:00:00 2001 From: alejoe91 Date: Wed, 11 Jan 2017 18:51:29 +0100 Subject: [PATCH 11/11] removed extra print --- LFPy/cell.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/LFPy/cell.py b/LFPy/cell.py index 78823a0d..864d51b2 100644 --- a/LFPy/cell.py +++ b/LFPy/cell.py @@ -1001,8 +1001,6 @@ def set_pos(self, xpos=0, ypos=0, zpos=0): diffy = ypos-self.somapos[1] diffz = zpos-self.somapos[2] - print diffx, diffy, diffz - self.somapos[0] = xpos self.somapos[1] = ypos self.somapos[2] = zpos