Skip to content

Commit 7b395ff

Browse files
committed
implemented electrode extraction from metadata and added kCSD plot
1 parent 1a9a23d commit 7b395ff

1 file changed

Lines changed: 259 additions & 0 deletions

File tree

figures/npx/dan_kCSD_from_npx.py

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
import numpy as np
2+
from kcsd import KCSD2D
3+
from pathlib import Path
4+
from openpyxl import load_workbook
5+
import DemoReadSGLXData.readSGLX as readSGLX
6+
# from DemoReadSGLXData.readSGLX import readMeta, SampRate, makeMemMapRaw,
7+
# GainCorrectIM, GainCorrectNI, ExtractDigital
8+
import matplotlib.pyplot as plt
9+
import matplotlib.cm as cm
10+
# from matplotlib import gridspec
11+
12+
13+
def make_plot(xx, yy, zz, title='True CSD', cmap=cm.bwr):
14+
fig = plt.figure(figsize=(7, 7))
15+
ax = plt.subplot(111)
16+
ax.set_aspect('equal')
17+
t_max = np.max(np.abs(zz))
18+
levels = np.linspace(-1 * t_max, t_max, 32)
19+
im = ax.contourf(xx, yy, zz, levels=levels, cmap=cmap)
20+
ax.set_xlabel('X (mm)')
21+
ax.set_ylabel('Y (mm)')
22+
ax.set_title(title)
23+
ticks = np.linspace(-1 * t_max, t_max, 3, endpoint=True)
24+
plt.colorbar(im, orientation='horizontal', format='%.2f', ticks=ticks)
25+
return ax
26+
27+
28+
# Specific to Ewas experimental setup
29+
def load_chann_map():
30+
book = load_workbook('NP_do_map.xlsx')
31+
sheet = book.get_sheet_by_name('sov12 sorted')
32+
eleid = sheet['C3':'C386']
33+
chanid = sheet['J3':'J386']
34+
chan_ele_dict = {}
35+
ele_chan_dict = {}
36+
for e,c in zip(eleid, chanid):
37+
chan_ele_dict[int(c[0].value)] = int(e[0].value)
38+
ele_chan_dict[int(e[0].value)] = int(c[0].value)
39+
return ele_chan_dict, chan_ele_dict
40+
41+
42+
def dan_fetch_electrodes(meta):
43+
imroList = meta['imroTbl'].split(sep=')')
44+
45+
# One entry for each channel plus header entry,
46+
# plus a final empty entry following the last ')'
47+
nChan = len(imroList) - 2
48+
electrode = np.zeros(nChan, dtype=int) # default type = float
49+
channel = np.zeros(nChan, dtype=int)
50+
bank = np.zeros(nChan, dtype=int)
51+
for i in range(0, nChan):
52+
currList = imroList[i+1].split(sep=' ')
53+
channel[i] = int(currList[0][1:])
54+
bank[i] = int(currList[1])
55+
# reference_electrode[i] = currList[2]
56+
57+
# Channel N => Electrode (1+N+384*A), where N = 0:383, A=0:2
58+
electrode = 1 + channel + 384 * bank
59+
return(electrode, channel)
60+
61+
62+
def fetch_channels(eles):
63+
chans = []
64+
exist_ele = []
65+
for ii in eles:
66+
try:
67+
chans.append(ele_chan_dict[ii])
68+
exist_ele.append(ii)
69+
except KeyError:
70+
print('Not recording from ele', ii)
71+
return chans, exist_ele
72+
73+
def eles_to_rows(eles):
74+
rows = []
75+
for ele in eles:
76+
rows.append(np.int(np.ceil(ele/2)))
77+
return rows
78+
79+
def eles_to_ycoord(eles):
80+
rows = eles_to_rows(eles)
81+
y_coords = []
82+
for ii in rows:
83+
y_coords.append(int((480 - ii)*20))
84+
return y_coords
85+
86+
def eles_to_xcoord(eles):
87+
x_coords = []
88+
for ele in eles:
89+
off = ele%4
90+
if off == 1:
91+
x_coords.append(-24)
92+
elif off == 2:
93+
x_coords.append(8)
94+
elif off == 3:
95+
x_coords.append(-8)
96+
else:
97+
x_coords.append(24)
98+
return x_coords
99+
100+
def eles_to_coords(eles):
101+
xs = eles_to_xcoord(eles)
102+
ys = eles_to_ycoord(eles)
103+
return np.array((xs, ys)).T
104+
105+
106+
# File with the data
107+
# old
108+
# binFullPath = Path('./data/08_refGND_APx500_LFPx125_ApfiltON_corr_banks_stim50V_g0_t0.imec0.lf.bin')
109+
# Daniel
110+
binFullPath = Path('/mnt/zasoby/data/neuropixel/Neuropixel data from Ewa Kublik/SOV_12/data/08_refGND_APx500_LFPx125_ApfiltON_corr_banks_stim50V_g0_t0.imec0.lf.bin')
111+
# Chaitanya
112+
# binFullPath = Path('/home/chaitanya/LFP/SOV_12/data/08_refGND_APx500_LFPx125_ApfiltON_corr_banks_stim50V_g0_t0.imec0.lf.bin')
113+
114+
meta = readSGLX.readMeta(binFullPath)
115+
sRate = readSGLX.SampRate(meta)
116+
117+
tStart, tEnd = 500., 600. # 0., 1. # in seconds
118+
119+
firstSamp = int(sRate*tStart)
120+
lastSamp = int(sRate*tEnd)
121+
122+
123+
# Return array of original channel IDs. As an example, suppose we want the
124+
# imec gain for the ith channel stored in the binary data. A gain array
125+
# can be obtained using ChanGainsIM(), but we need an original channel
126+
# index to do the lookup. Because you can selectively save channels, the
127+
# ith channel in the file isn't necessarily the ith acquired channel.
128+
# Use this function to convert from ith stored to original index.
129+
# Note that the SpikeGLX channels are 0 based.
130+
#
131+
# chans = readSGLX.OriginalChans(meta)
132+
133+
electrodes, channels = dan_fetch_electrodes(meta)
134+
# for Ewa's initial file, channel 768 is SY
135+
# and it hould be removed - this has not been done yet
136+
# DANIEL
137+
138+
139+
140+
141+
142+
# =============================================================================
143+
# # chanList = [0, 6, 9, 383]
144+
# # eleList = np.arange(769, 860)
145+
# eleList = np.arange(0, 959)
146+
#
147+
# ele_chan_dict, chan_ele_dict = load_chann_map()
148+
# # print(ele_dict)
149+
# chanList, eleList = fetch_channels(eleList)
150+
#
151+
# =============================================================================
152+
153+
154+
# Which digital word to read.
155+
# For imec, there is only 1 digital word, dw = 0.
156+
# For NI, digital lines 0-15 are in word 0, lines 16-31 are in word 1, etc.
157+
dw = 0
158+
# Which lines within the digital word, zero-based
159+
# Note that the SYNC line for PXI 3B is stored in line 6.
160+
dLineList = [6]
161+
162+
rawData = readSGLX.makeMemMapRaw(binFullPath, meta)
163+
selectData = rawData[channels, firstSamp:lastSamp+1]
164+
# digArray = readSGLX.ExtractDigital(rawData, firstSamp, lastSamp, dw, dLineList, meta)
165+
166+
# convData is the potential in uV or mV
167+
if meta['typeThis'] == 'imec':
168+
# apply gain correction and convert to uV
169+
convData = 1e6*readSGLX.GainCorrectIM(selectData, channels, meta)
170+
else:
171+
# apply gain correction and convert to mV
172+
convData = 1e3*readSGLX.GainCorrectNI(selectData, channels, meta)
173+
174+
tDat = np.arange(firstSamp, lastSamp+1)
175+
tDat = 1000*tDat/sRate # plot time axis in msec
176+
177+
178+
179+
ele_pos = eles_to_coords(electrodes)
180+
print(ele_pos)
181+
csd_at_time = 30.
182+
pots = []
183+
for ii, chann in enumerate(channels):
184+
print(ii, chann)
185+
pots.append(convData[ii, int(sRate*csd_at_time)])
186+
187+
pots = np.array(pots)
188+
print(pots.shape)
189+
190+
191+
pots = pots.reshape((len(channels), 1))
192+
R_init = 5. # 0.3
193+
h = 20. # 50
194+
sigma = 0.3
195+
k = KCSD2D(ele_pos, pots, h=h, sigma=sigma,
196+
xmin=-35, xmax=35,
197+
ymin=1100, ymax=2000,
198+
# ymin=1000, ymax=10000,
199+
gdx=10, gdy=10,
200+
R_init=R_init, n_src_init=1000,
201+
src_type='gauss') # rest of the parameters are set at default
202+
k.cross_validate(Rs=np.logspace(-1., 1., 10), lambdas=None)
203+
# k.cross_validate(Rs=np.linspace(0.1, 1.001, 2), lambdas=None)
204+
# 2 -> 20
205+
206+
207+
est_csd = k.values('CSD')
208+
est_csd = est_csd.reshape(7, 90)
209+
est_pots = k.values('POT')
210+
est_pots = est_pots.reshape(7, 90)
211+
212+
make_plot(k.estm_x, k.estm_y, est_csd[:, :],
213+
title='Estimated CSD without CV', cmap=cm.bwr)
214+
215+
make_plot(k.estm_x, k.estm_y, est_pots[:, :],
216+
title='Estimated POT without CV', cmap=cm.PRGn)
217+
218+
219+
# # ax = plt.subplot(121)
220+
# # for ii, chan in enumerate(chanList):
221+
# # ax.plot(tDat, convData[ii, :], label=str(chan)+' Ele'+str(chan_dict[chan]))
222+
# # plt.legend()
223+
# # ax = plt.subplot(122)
224+
# # for i in range(0, len(dLineList)):
225+
# # ax.plot(tDat, digArray[i, :])
226+
227+
# rowList = eles_to_rows(eleList)
228+
# num_rows = max(rowList) - min(rowList) + 1
229+
# print(num_rows)
230+
# fig = plt.figure(figsize=(4, num_rows))
231+
# gs = gridspec.GridSpec(nrows=num_rows, ncols=4, wspace=0, hspace=0)
232+
# all_maxy = -100
233+
# axs = []
234+
# for ii, chann in enumerate(chanList):
235+
# ee = chan_ele_dict[chann]
236+
# rr = eles_to_rows([ee])[0] - min(rowList) # last row first
237+
# rr = num_rows - rr - 1
238+
# print(rr, ee, num_rows-rr)
239+
# off = ee%4
240+
# if off == 0:
241+
# ax = fig.add_subplot(gs[rr, 3])
242+
# elif off == 1:
243+
# ax = fig.add_subplot(gs[rr, 0])
244+
# elif off == 2:
245+
# ax = fig.add_subplot(gs[rr, 2])
246+
# else:
247+
# ax = fig.add_subplot(gs[rr, 1])
248+
# ax.plot(tDat, convData[ii, :])
249+
# all_maxy = max(all_maxy, max(convData[ii, :]))
250+
# ax.spines['right'].set_visible(False)
251+
# ax.spines['top'].set_visible(False)
252+
# # ax.spines['left'].set_visible(False)
253+
# # ax.set_yticklabels([])
254+
# # ax.set_yticks([])
255+
# ax.set_title('E('+str(ee)+')')
256+
# axs.append(ax)
257+
# print(all_maxy)
258+
# plt.show()
259+

0 commit comments

Comments
 (0)