Skip to content

Commit 7572f73

Browse files
committed
fixed IMRO uploading broken by Join Tips referencing implementation from last week + added pop up warnings for detected corrupt IMRO files
1 parent ec1282c commit 7572f73

5 files changed

Lines changed: 60 additions & 123 deletions

File tree

channelmap_generator/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77

88
from .backend import *
99

10-
__version__ = "0.3.3"
10+
__version__ = "0.3.4"
1111
__author__ = "Maxime Beau"
1212
__email__ = "maxime@princeton.edu"

channelmap_generator/gui/gui.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
DEFAULT_PORT = 5007
4848

4949
# Enable Panel extensions
50-
pn.extension("tabulator")
50+
pn.extension("tabulator", notifications=True)
5151

5252

5353
###################################
@@ -672,8 +672,15 @@ def generate_pdf_content(self):
672672

673673
def apply_uploaded_imro(self):
674674

675-
if not any(self.imro_file_loader.value):
676-
print("You must upload an imro file before applying it to the selection.")
675+
if self.imro_file_loader.value is None:
676+
pn.state.notifications.warning("No .imro file found - upload one before clicking this button.",
677+
duration=10_000)
678+
return
679+
680+
file_extension = str(self.imro_file_loader.filename).split(".")[-1]
681+
if file_extension != "imro":
682+
pn.state.notifications.error(f"You must upload an .imro file, not .{file_extension}!",
683+
duration=10_000)
677684
return
678685

679686
imro_file_content = self.imro_file_loader.value
@@ -961,7 +968,7 @@ def create_widgets(self):
961968
)
962969

963970
# IMRO file dropper
964-
self.imro_file_loader = pn.widgets.FileInput(accept=".imro", width=300)
971+
self.imro_file_loader = pn.widgets.FileInput(width=300)
965972
self.apply_uploaded_imro_button = pn.widgets.Button(
966973
name="Apply uploaded IMRO file to selection ⬆", button_type="primary", width=250
967974
)

channelmap_generator/test_types.py

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

channelmap_generator/utils/imro.py

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66
import numpy as np
77
import pandas as pd
88

9+
import panel as pn
10+
911
from channelmap_generator.backend import format_imro_string, get_electrodes
1012
from channelmap_generator.constants import PROBE_N, PROBE_TYPE_MAP, REF_ELECTRODES
1113

12-
1314
def save_to_imro_file(imro_list, filename="channelmap.imro"):
1415
"""
1516
Save IMRO list to a text file in SpikeGLX format.
@@ -98,6 +99,7 @@ def parse_imro_list(imro_list):
9899
probe_type: "1.0", "2.0-1shank", "2.0-4shanks", or "NXT"
99100
Other parameters: as used in original generation
100101
"""
102+
101103
header = imro_list[0]
102104
probe_subtype = header[0]
103105
entries = imro_list[1:]
@@ -109,22 +111,22 @@ def parse_imro_list(imro_list):
109111
probe_type = "2.0-1shank"
110112
elif probe_subtype in PROBE_TYPE_MAP["2.0-4shanks"]:
111113
probe_type = "2.0-4shanks"
112-
elif probe_subtype in PROBE_TYPE_MAP["NXT"]:
113-
probe_type = "NXT"
114+
# elif probe_subtype in PROBE_TYPE_MAP["NXT"]:
115+
# probe_type = "NXT"
114116

115117
selected_electrodes = []
116118

117119
if probe_type == "1.0":
118120
# Format: (channel, bank, ref, ap_gain, lf_gain, hp_filter)
121+
check_entry_elements(6, entries[0], probe_type)
122+
119123
reference_id = entries[0][2] # Same for all entries
124+
reference_string = ref_id_to_string(reference_id, probe_subtype)
125+
120126
ap_gain = entries[0][3]
121127
lf_gain = entries[0][4]
122128
hp_filter = entries[0][5]
123129

124-
# Convert reference value back to string
125-
ref_map = {v: k for k, v in REF_ELECTRODES[probe_subtype].items()}
126-
reference_id = ref_map[reference_id]
127-
128130
# Extract electrodes: channel + 384*bank gives electrode_id, shank is always 0
129131
for entry in entries:
130132
channel, bank = entry[0], entry[1]
@@ -133,34 +135,31 @@ def parse_imro_list(imro_list):
133135

134136
elif probe_type == "2.0-1shank":
135137
# Format: (channel, bank_mask, ref, electrode_id)
138+
check_entry_elements(4, entries[0], probe_type)
139+
136140
reference_id = entries[0][2]
137-
ap_gain = lf_gain = hp_filter = None # Not used in 2.0
141+
reference_string = ref_id_to_string(reference_id, probe_subtype)
138142

139-
# Convert reference value back to string
140-
ref_map = {v: k for k, v in REF_ELECTRODES[probe_subtype].items()}
141-
reference_id = ref_map[reference_id]
143+
ap_gain = lf_gain = hp_filter = None # Not used in 2.0 IMRO tables
142144

143145
# Extract electrodes: electrode_id is directly stored, shank is always 0
144146
for entry in entries:
145147
electrode_id = entry[3]
146148
selected_electrodes.append([0, electrode_id])
147149

148-
else: # 2.0-4shanks or NXT
150+
else: # 2.0-4shanks or NXT in the future
149151
# Format: (channel, shank_id, bank, ref, electrode_id)
150-
reference_id = entries[0][3]
151-
ap_gain = lf_gain = hp_filter = None # Not used in 2.0
152-
153-
# Convert reference value back to string
154-
ref_electrodes = REF_ELECTRODES[probe_subtype]
155-
if "Tip" in ref_electrodes and isinstance(ref_electrodes["Tip"], list):
156-
if reference_id in ref_electrodes["Tip"]:
157-
reference_id = "Tip"
158-
else:
159-
ref_map = {v: k for k, v in ref_electrodes.items() if k != "Tip"}
160-
reference_id = ref_map[reference_id]
152+
check_entry_elements(5, entries[0], probe_type)
153+
154+
# Need the 2 first reference IDs to handle join_tips referencing
155+
reference_ids = [entries[0][3], entries[1][3]]
156+
if reference_ids[0] != reference_ids[1]:
157+
reference_string = 'Join Tips'
161158
else:
162-
ref_map = {v: k for k, v in ref_electrodes.items()}
163-
reference_id = ref_map[reference_id]
159+
reference_id = reference_ids[0]
160+
reference_string = ref_id_to_string(reference_id, probe_subtype)
161+
162+
ap_gain = lf_gain = hp_filter = None # Not used in 2.0 IMRO tables
164163

165164
# Extract electrodes: shank_id and electrode_id are directly stored
166165
for entry in entries:
@@ -170,9 +169,29 @@ def parse_imro_list(imro_list):
170169

171170
selected_electrodes = np.array(selected_electrodes, dtype=int)
172171

173-
return selected_electrodes, probe_type, probe_subtype, reference_id, ap_gain, lf_gain, hp_filter
174-
175-
172+
return (selected_electrodes,
173+
probe_type,
174+
probe_subtype,
175+
reference_string,
176+
ap_gain,
177+
lf_gain,
178+
hp_filter)
179+
180+
181+
def ref_id_to_string(reference_id, probe_subtype):
182+
ref_map = {v: k for k, v in REF_ELECTRODES[probe_subtype].items() if k != "Join Tips"}
183+
if reference_id not in ref_map:
184+
pn.state.notifications.error(f"Unexpected reference id {reference_id} for probe subtype {probe_subtype}!",
185+
duration=10_000)
186+
assert reference_id in ref_map,\
187+
f"Unexpected reference id {reference_id} for probe subtype {probe_subtype}!"
188+
return ref_map[reference_id]
189+
190+
def check_entry_elements(n_expected_elements, entry, probe_type):
191+
n_entry_elements = len(entry)
192+
if n_entry_elements != n_expected_elements:
193+
pn.state.notifications.error(f"Corrupt .imro file - IMRO table entries for {probe_type} probes should have {n_expected_elements} elements, not {n_entry_elements}.",
194+
duration=10_000)
176195

177196
def generate_imro_channelmap(
178197
probe_type,

uv.lock

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)