Skip to content

Commit 8a42d4c

Browse files
committed
Merge branch 'main' of github.com:SpikeInterface/probeinterface into prepare_release
2 parents a6352be + 2768246 commit 8a42d4c

File tree

21 files changed

+3859
-1133
lines changed

21 files changed

+3859
-1133
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@ dev_*
2525
.coverage
2626
cov.xml
2727
.DS_Store
28+
29+
30+
neuropixel_library_generated/*

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v4.6.0
3+
rev: v5.0.0
44
hooks:
55
- id: check-yaml
66
- id: end-of-file-fixer
77
- id: trailing-whitespace
88
- repo: https://github.com/psf/black
9-
rev: 24.8.0
9+
rev: 25.1.0
1010
hooks:
1111
- id: black
1212
files: ^src/|^tests/

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,14 @@ package-dir = {"probeinterface" = "src/probeinterface"}
4040
[project.optional-dependencies]
4141

4242
test = [
43+
"jsonschema",
4344
"pytest",
4445
"pytest-cov",
4546
"matplotlib",
4647
"scipy",
4748
"pandas",
4849
"h5py",
49-
"zarr>=2.16.0"
50+
"zarr>=2.16.0,<3.0.0"
5051
]
5152

5253
docs = [

resources/generate_cambridgeneurotech_libray.py

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@
5050
# work_dir = '/home/samuel/Documents/SpikeInterface/2022-05-20-probeinterface_CambridgeNeurotech/'
5151
# work_dir = '/home/samuel/Documents/SpikeInterface/2022-10-18-probeinterface_CambridgeNeurotech/'
5252
# work_dir = '/home/samuel/OwnCloudCNRS/probeinterface/2023-06-14-probeinterface-CambridgeNeurotech/'
53-
work_dir = '/home/samuel/OwnCloudCNRS/probeinterface/2023-10-30-probeinterface-CambridgeNeurotech/'
53+
# work_dir = '/home/samuel/OwnCloudCNRS/probeinterface/2023-10-30-probeinterface-CambridgeNeurotech/'
54+
work_dir = '/home/samuel/NextcloudCNRS/probeinterface/2025-01-27-probeinterface-CambridgeNeurotech/'
5455

5556

5657
library_folder = '/home/samuel/Documents/SpikeInterface/probeinterface_library/cambridgeneurotech/'
@@ -59,7 +60,7 @@
5960

6061
work_dir = Path(work_dir).absolute()
6162

62-
export_folder = work_dir / 'export_2023_10_30'
63+
export_folder = work_dir / 'export_2025_01_27'
6364
probe_map_file = work_dir / 'ProbeMaps_Final2023.xlsx'
6465
probe_info_table_file = work_dir / 'ProbesDataBase_Final2023.csv'
6566

@@ -112,18 +113,21 @@ def get_contact_order(connector, probe_type):
112113
if probe_type == 'H5' or probe_type == 'H9':
113114
probe_type = 'H5 & H9'
114115

115-
#~ print(df[probe_type])
116+
# print(df[probe_type])
116117
tmpList = []
117118
for i in df[probe_type].columns:
119+
# print('i', i, len(df[probe_type].columns))
118120
if len(df[probe_type].columns) == 1:
119121
tmpList = np.flip(df[probe_type].values.astype(int).flatten())
120122
else:
121123
tmp = df[probe_type][i].values
122124
tmp = tmp[~np.isnan(tmp)].astype(int) # get rid of nan and convert to integer
123125
tmp = np.flip(tmp) # this flips the value to match index that goes from tip to headstage of the probe
126+
# print('tmp', tmp)
124127
tmpList = np.append(tmpList, tmp)
125128
tmpList = tmpList.astype(int)
126129

130+
# print('tmpList', tmpList)
127131
return tmpList
128132

129133

@@ -200,7 +204,7 @@ def create_CN_figure(probe_name, probe):
200204
ax.spines['right'].set_visible(False) #remove external axis
201205
ax.spines['top'].set_visible(False) #remove external axis
202206

203-
ax.set_title('\n' +'CambridgeNeuroTech' +'\n'+ probe.annotations.get('name'), fontsize = 24)
207+
ax.set_title('\n' +'CambridgeNeuroTech' +'\n'+ probe.annotations.get('model_name'), fontsize = 24)
204208

205209
fig.tight_layout() #modif tight layout
206210

@@ -242,6 +246,11 @@ def generate_all_probes():
242246
for i, probe_info in probe_info_table.iterrows():
243247
print(i, probe_info['part'])
244248

249+
# DEBUG
250+
# if not probe_info['part'] in ('P-1', 'P-2'):
251+
# continue
252+
253+
# print(probe_info)
245254

246255
if probe_info['shanks_n'] == 1:
247256
# one shank
@@ -254,16 +263,29 @@ def generate_all_probes():
254263
for connector in list(probe_info[probe_info.index.str.contains('ASSY')].dropna().index):
255264
probe_name = connector+'-'+probe_info['part']
256265

257-
#~ if probe_name != 'ASSY-77-H10':
258-
#~ continue
266+
# DEBUG
267+
# if connector != 'ASSY-1':
268+
# continue
269+
270+
259271
print(' ', probe_name)
260272

261273
contact_order = get_contact_order(connector = connector, probe_type = probe_info['part'])
262274

275+
# print(probe_unordered)
276+
# print(probe_unordered.contact_ids)
277+
# print(contact_order)
278+
# print(probe_unordered.)
279+
# fig, ax = plt.subplots()
280+
# plot_probe(probe_unordered, ax=ax, with_contact_id=True)
281+
# plt.show()
282+
283+
284+
263285
sorted_indices = np.argsort(contact_order)
264286
probe = probe_unordered.get_slice(sorted_indices)
265287

266-
probe.annotate(name=probe_name, manufacturer='cambridgeneurotech')
288+
probe.annotate(model_name=probe_name, manufacturer='cambridgeneurotech')
267289

268290
# one based in cambridge neurotech
269291
contact_ids = np.arange(sorted_indices.size) + 1
@@ -272,6 +294,7 @@ def generate_all_probes():
272294

273295
export_one_probe(probe_name, probe)
274296

297+
# break
275298

276299
def synchronize_library():
277300

@@ -309,6 +332,8 @@ def synchronize_library():
309332

310333
# library_folder
311334

335+
336+
312337
if __name__ == '__main__':
313-
# generate_all_probes()
338+
generate_all_probes()
314339
synchronize_library()
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import shutil
2+
from pathlib import Path
3+
4+
import numpy as np
5+
import matplotlib.pyplot as plt
6+
7+
from probeinterface.neuropixels_tools import npx_descriptions, probe_part_number_to_probe_type, _make_npx_probe_from_description
8+
from probeinterface.plotting import plot_probe
9+
from probeinterface import write_probeinterface
10+
11+
12+
base_folder = Path("./neuropixels_library_generated")
13+
14+
15+
16+
def generate_all_npx():
17+
18+
# if not base_folder.exists():
19+
base_folder.mkdir(exist_ok=True)
20+
21+
22+
for probe_number, probe_type in probe_part_number_to_probe_type.items():
23+
24+
if probe_number is None:
25+
continue
26+
27+
if probe_number == "1110":
28+
# the formula by the imrow table is wrong and more complicated
29+
continue
30+
31+
probe_folder = base_folder / probe_number
32+
probe_folder.mkdir(exist_ok=True)
33+
34+
print(probe_number, probe_type)
35+
36+
probe_description = npx_descriptions[probe_type]
37+
38+
39+
40+
num_shank = probe_description["shank_number"]
41+
contact_per_shank = probe_description["ncols_per_shank"] * probe_description["nrows_per_shank"]
42+
if num_shank == 1:
43+
elec_ids = np.arange(contact_per_shank)
44+
shank_ids = None
45+
else:
46+
elec_ids = np.concatenate([np.arange(contact_per_shank) for i in range(num_shank)])
47+
shank_ids = np.concatenate([np.zeros(contact_per_shank) + i for i in range(num_shank)])
48+
49+
probe = _make_npx_probe_from_description(probe_description, elec_ids, shank_ids)
50+
51+
# ploting
52+
fig, axs = plt.subplots(ncols=2)
53+
54+
ax = axs[0]
55+
plot_probe(probe, ax=ax)
56+
ax.set_title("")
57+
58+
ax.xaxis.set_visible(False)
59+
ax.spines["top"].set_visible(False)
60+
ax.spines["right"].set_visible(False)
61+
ax.spines["bottom"].set_visible(False)
62+
63+
ax = axs[1]
64+
65+
66+
# plot_probe(probe, ax=ax, text_on_contact=probe._contact_ids)
67+
plot_probe(probe, ax=ax)
68+
ax.set_title("")
69+
70+
yp = probe_description["y_pitch"]
71+
ax.set_ylim(-yp*8, yp*13)
72+
ax.yaxis.set_visible(False)
73+
ax.spines["top"].set_visible(False)
74+
ax.spines["right"].set_visible(False)
75+
ax.spines["left"].set_visible(False)
76+
77+
n = probe.get_contact_count()
78+
79+
title = probe_number
80+
title += f"\n{probe.manufacturer} - {probe.model_name}"
81+
title += f"\n {n}ch"
82+
if probe.shank_ids is not None:
83+
num_shank = probe.get_shank_count()
84+
title += f" - {num_shank}shanks"
85+
86+
87+
fig.suptitle(title)
88+
89+
# plt.show()
90+
91+
fig.savefig(probe_folder / f"{probe_number}.png")
92+
93+
write_probeinterface(probe_folder / f"{probe_number}.json", probe)
94+
95+
plt.close(fig)
96+
97+
98+
99+
100+
101+
102+
103+
104+
105+
if __name__ == "__main__":
106+
generate_all_npx()

resources/probe.json.schema

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@
2626
"annotations": {
2727
"type": "object",
2828
"properties": {
29-
"name": { "type": "string" },
29+
"model_name": { "type": "string" },
3030
"manufacturer": { "type": "string" }
3131
},
32-
"required": ["name", "manufacturer"],
32+
"required": ["model_name", "manufacturer"],
3333
"additionalProperties": true
3434
},
3535
"contact_annotations": {
@@ -71,14 +71,14 @@
7171
"anyOf": [
7272
{
7373
"type": "object",
74-
"properties": { "radius": { "type": "integer", "minimum": 0 } },
74+
"properties": { "radius": { "type": "number", "minimum": 0 } },
7575
"required": ["radius"]
7676
},
7777
{
7878
"type": "object",
7979
"properties": {
80-
"width": { "type": "integer", "minimum": 0 },
81-
"height": { "type": "integer", "minimum": 0 }
80+
"width": { "type": "number", "minimum": 0 },
81+
"height": { "type": "number", "minimum": 0 }
8282
},
8383
"required": ["width"]
8484
}
@@ -101,6 +101,10 @@
101101
"shank_ids": {
102102
"type": "array",
103103
"items": { "type": "string" }
104+
},
105+
"device_channel_indices": {
106+
"type": "array",
107+
"items": { "type": "integer" }
104108
}
105109
},
106110
"required": [

src/probeinterface/__init__.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,23 @@
1212
write_prb,
1313
read_csv,
1414
write_csv,
15-
read_imro,
16-
write_imro,
1715
read_BIDS_probe,
1816
write_BIDS_probe,
1917
read_spikegadgets,
18+
read_mearec,
19+
read_nwb,
20+
read_maxwell,
21+
read_3brain,
22+
)
23+
from .neuropixels_tools import (
24+
read_imro,
25+
write_imro,
2026
read_spikeglx,
2127
parse_spikeglx_meta,
28+
parse_spikeglx_snsGeomMap,
2229
get_saved_channel_indices_from_spikeglx_meta,
2330
read_openephys,
2431
get_saved_channel_indices_from_openephys_settings,
25-
read_mearec,
26-
read_nwb,
27-
read_maxwell,
28-
read_3brain,
2932
)
3033
from .utils import combine_probes
3134
from .generator import (

0 commit comments

Comments
 (0)