66import numpy as np
77import pandas as pd
88
9+ import panel as pn
10+
911from channelmap_generator .backend import format_imro_string , get_electrodes
1012from channelmap_generator .constants import PROBE_N , PROBE_TYPE_MAP , REF_ELECTRODES
1113
12-
1314def 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
177196def generate_imro_channelmap (
178197 probe_type ,
0 commit comments