Skip to content

Commit 10a3014

Browse files
wsredniawaccluri
authored andcommitted
Figures L-curve (#107)
* Removes old files to generate L-curve figures * New scripts to generate 3 L-curve figures figure_LC.py - generates figure 5 figure_LCandCVperformance.py - generates figure 6 figure_LCandCV.py - generates figure 14 L_curve_simulation.py - generates data and figures if parameter plot=True * updated for test
1 parent 053cf7e commit 10a3014

9 files changed

Lines changed: 463 additions & 679 deletions
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
'''
2+
This script is used to test Current Source Density Estimates,
3+
using the kCSD method Jan et.al (2012)
4+
5+
This script is in alpha phase.
6+
7+
This was written by :
8+
Chaitanya Chintaluri,
9+
Laboratory of Neuroinformatics,
10+
Nencki Institute of Exprimental Biology, Warsaw.
11+
'''
12+
import os
13+
import numpy as np
14+
from scipy.integrate import simps
15+
import matplotlib.pyplot as plt
16+
from kcsd import KCSD1D
17+
from figure_LC import make_plots
18+
from figure_LCandCVperformance import make_plot_perf
19+
from figure_LCandCV import plot_surface
20+
21+
def do_kcsd(i, ele_pos, pots, **params):
22+
"""
23+
Function that calls the KCSD1D module
24+
"""
25+
num_ele = len(ele_pos)
26+
pots = pots.reshape(num_ele, 1)
27+
ele_pos = ele_pos.reshape(num_ele, 1)
28+
k = KCSD1D(ele_pos, pots, **params)
29+
noreg_csd = k.values('CSD')
30+
k.cross_validate(Rs=Rs, lambdas=lambdas)
31+
errsy = k.errs
32+
LandR[1,0,i] = k.lambd
33+
LandR[1,1,i] = k.R
34+
est_csd_cv = k.values('CSD')
35+
k.L_curve(lambdas=lambdas, Rs=Rs)
36+
LandR[0,0,i] = k.lambd
37+
LandR[0,1,i] = k.R
38+
est_csd = k.values('CSD')
39+
est_pot = k.values('POT')
40+
return k, est_csd, est_pot, noreg_csd, errsy, est_csd_cv
41+
42+
def generate_csd_1D(src_width, name, srcs=np.array([0]),
43+
start_x=0., end_x=1.,
44+
start_y=0., end_y=1.,
45+
res_x=50, res_y=50):
46+
"""
47+
Gives CSD profile at the requested spatial location, at 'res' resolution
48+
"""
49+
csd_y = np.linspace(start_x, end_x, res_x)
50+
csd_x = np.linspace(start_x, end_x, res_x)
51+
src_peak = .7*np.exp(-((csd_x-0.25)**2)/(2.*src_width))
52+
src_thr1 = .35*np.exp(-((csd_x-0.45)**2)/(2.*src_width))
53+
src_thr2 = .35*np.exp(-((csd_x-0.65)**2)/(2.*src_width))
54+
f = src_peak-src_thr1-src_thr2
55+
csd_y = np.linspace(start_x, end_x, res_x)
56+
return csd_x, csd_y, f
57+
58+
def integrate_1D(x0, csd_x, csd, h):
59+
m = np.sqrt((csd_x-x0)**2 + h**2) - abs(csd_x-x0)
60+
y = csd * m
61+
I = simps(y, csd_x)
62+
return I
63+
64+
def calculate_potential_1D(csd, measure_locations, csd_space_x, h):
65+
sigma = 1
66+
print(measure_locations.shape, csd_space_x.shape, csd.shape)
67+
pots = np.zeros(len(measure_locations))
68+
for ii in range(len(measure_locations)):
69+
pots[ii] = integrate_1D(measure_locations[ii], csd_space_x, csd, h)
70+
pots *= 1/(2.*sigma) #eq.: 26 from Potworowski et al
71+
return pots
72+
73+
def transformAndNormalizeLongGrid(D):
74+
#D is a dictionary
75+
locations = np.zeros((len(D), 2))
76+
for i in range(len(D)):
77+
locations[i, 0] = D[i]['x']
78+
locations[i, 1] = D[i]['y']
79+
return locations
80+
81+
def generate_electrodes(inpos, lpos, b):
82+
loc = {}
83+
cordx = -(inpos[0] - lpos[0])/b
84+
cordy = -(inpos[1] - lpos[1])/b
85+
def _addLocToDict(D, chnum, x, y):
86+
d = {}
87+
d['x'] = x
88+
d['y'] = y
89+
D[chnum] = d
90+
#first add locations just as they suppose to be
91+
for i in range(b):
92+
_addLocToDict(loc, i, inpos[0] + cordx*i, inpos[1] + cordy*i)
93+
loc_mtrx = transformAndNormalizeLongGrid(loc)
94+
loc_mtrx = loc_mtrx.T
95+
return loc_mtrx[0], loc_mtrx[1]
96+
97+
def electrode_config(ele_res, true_csd, csd_x, csd_y, inpos, lpos):
98+
"""
99+
What is the configuration of electrode positions, between what and what positions
100+
"""
101+
ele_x, ele_y = generate_electrodes(inpos, lpos, ele_res)
102+
pots = calculate_potential_1D(true_csd, ele_y.T, csd_y, h=1)
103+
ele_pos = np.vstack((ele_x, ele_y)).T #Electrode configs
104+
return ele_pos, pots
105+
106+
def main_loop(src_width, total_ele, inpos, lpos, nm, noise=0, srcs=1):
107+
"""
108+
Loop that decides the random number seed for the CSD profile,
109+
electrode configurations and etc.
110+
"""
111+
#TrueCSD
112+
t_csd_x, t_csd_y, true_csd = generate_csd_1D(src_width, nm, srcs=srcs,
113+
start_x=0, end_x=1.,
114+
start_y=0, end_y=1,
115+
res_x=100, res_y=100)
116+
if type(noise) == float: n_spec = [noise]
117+
else: n_spec = noise
118+
for i, noise in enumerate(n_spec):
119+
plt.close('all')
120+
noise = np.round(noise, 5)
121+
print('numer rekonstrukcji: ', i, 'noise level: ', noise)
122+
#Electrodes
123+
ele_pos, pots = electrode_config(total_ele, true_csd, t_csd_x, t_csd_y, inpos, lpos)
124+
ele_y = ele_pos[:, 1]
125+
gdX = 0.01
126+
x_lims = [0, 1] #CSD estimation place
127+
np.random.seed(srcs)
128+
pots_n = pots + (np.random.rand(total_ele)*np.max(abs(pots))-np.max(abs(pots))/2)*noise
129+
k, est_csd, est_pot, noreg_csd, errsy, est_csd_cv = do_kcsd(i, ele_y, pots_n, h=1., gdx=gdX, sigma = 1,
130+
xmin=x_lims[0], xmax=x_lims[1], n_src_init=1e3)
131+
save_as = nm + '_noise' + str(np.round(noise*100, 1))
132+
m_norm = k.m_norm
133+
m_resi = k.m_resi
134+
curve_surf = k.curve_surf
135+
title = [str(k.lambd), str(k.R), str(noise), nm]
136+
if plot:
137+
make_plots(title, m_norm, m_resi, true_csd, curve_surf, ele_y, pots_n,
138+
pots, k.estm_x, est_pot, est_csd, noreg_csd, save_as)
139+
plot_surface(curve_surf, errsy, save_as+'surf')
140+
vals_to_save = {'m_norm':m_norm, 'm_resi':m_resi, 'true_csd':true_csd,
141+
'curve_surf':curve_surf, 'ele_y':ele_y, 'pots_n':pots_n,
142+
'pots':pots, 'estm_x':k.estm_x, 'est_pot':est_pot,
143+
'est_csd':est_csd, 'noreg_csd':noreg_csd, 'errsy':errsy}
144+
np.savez('data_fig4_and_fig13_'+save_as, **vals_to_save)
145+
RMS_wek[0, i] = np.linalg.norm(true_csd/np.linalg.norm(true_csd) - est_csd[:,0]/np.linalg.norm(est_csd[:,0]))
146+
RMS_wek[1, i] = np.linalg.norm(true_csd/np.linalg.norm(true_csd) - est_csd_cv[:,0]/np.linalg.norm(est_csd_cv[:,0]))
147+
148+
if __name__=='__main__':
149+
saveDir = "./LCurve/"
150+
try:
151+
os.chdir(saveDir)
152+
except FileNotFoundError:
153+
os.mkdir(saveDir)
154+
os.chdir(saveDir)
155+
plot = False
156+
total_ele = 32
157+
src_width = 0.001
158+
noises = 9
159+
seeds = 9
160+
inpos = [0.5, 0.1]#od dolu
161+
lpos = [0.5, 0.9]
162+
noise_lvl = np.linspace(0, 0.5, noises)
163+
Rs = np.linspace(0.025, 8*0.025, 8)
164+
lambdas = np.logspace(-7, -3, 50)
165+
sim_results = np.zeros((2, 4, seeds, noises))
166+
sim_results[:, 3] = noise_lvl
167+
for src in range(seeds):
168+
print('noise seed:', src)
169+
RMS_wek = np.zeros((2,len(noise_lvl)))
170+
LandR = np.zeros((2,2, len(noise_lvl)))
171+
mypath = 'LC' + str(src) + '/'
172+
if not os.path.isdir(mypath): os.makedirs(mypath)
173+
os.chdir(mypath)
174+
main_loop(src_width, total_ele, inpos,
175+
lpos, 'LC', noise=noise_lvl, srcs=src)
176+
sim_results[:,:2, src] = LandR
177+
sim_results[:, 2, src] = RMS_wek
178+
os.chdir('..')
179+
np.save('sim_results', sim_results)
180+
sim_results = np.load('sim_results.npy')
181+
make_plot_perf(sim_results)
182+

figures/kCSD_properties/README.txt

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,28 @@ Figure 2 - 1D spectral properties of kCSD method
1111
figure_eigensources_M_1D.py
1212

1313
~~~~~~~~~~~~~~~~~~~~~~~
14-
Figure 3 and 4 - Noise-free Electrode / Basis source placement
14+
Figure 3 - Noise-free Electrode / Basis source placement
1515

1616
figure_Tbasis.py
1717

1818
~~~~~~~~~~~~~~~~~~~~~~~
19-
Figure 3 and 4 - Noisy electrodes / Basis source placement
19+
Figure 4 - Noisy electrodes / Basis source placement
2020

2121
figure_Tbasis_noise.py
2222

2323
~~~~~~~~~~~~~~~~~~~~~~~
2424
Figure 5 - L-curve method for regularization
2525

26+
You will need to run L_curve_simulation.py first or download files from here:
27+
...
28+
figure_LC.py
29+
2630
~~~~~~~~~~~~~~~~~~~~~~~
2731
Figure 6 - L-curve versus Cross-validation
2832

29-
fig2_cv_vs_lc.py
33+
You will need to run L_curve_simulation.py first or download files from here:
34+
...
35+
figure_LCandCVperformance.py
3036

3137
~~~~~~~~~~~~~~~~~~~~~~~
3238
Figure 7 - Error propagation map
@@ -83,6 +89,9 @@ tutorial_broken_electrodes.py
8389
~~~~~~~~~~~~~~~~~~~~~~~~
8490
Figure 14 - L-Curve and CV landscape
8591

92+
You will need to run L_curve_simulation.py first or download files from here:
93+
...
94+
figure_LCandCV.py
8695

8796
=====================
8897
Supplementary Figures

figures/kCSD_properties/fig2_cv_vs_lc.py

Lines changed: 0 additions & 83 deletions
This file was deleted.

0 commit comments

Comments
 (0)