@@ -177,9 +177,30 @@ def _intan_hwchans_in_binary_order(self, sconf, num_ephy_channels, num_ephy_chan
177177 intan_chans_per_chip = int (sconf .attrib .get ("chanPerChip" , 32 )) # RHD2132 default for legacy files
178178 hw_chans_in_xml = [int (schan .attrib ["hwChan" ]) for trode in sconf for schan in trode ]
179179
180+ if intan_chans_per_chip > num_ephy_channels :
181+ # chanPerChip larger than the total channel count is structurally impossible
182+ # for any real Intan chip layout. Reported in #1830 with the example value
183+ # 1645402192, suspected to come from a Trodes header-write bug.
184+ self .logger .warning (
185+ f"SpikeGadgets chanPerChip={ intan_chans_per_chip } exceeds "
186+ f"num_ephy_channels={ num_ephy_channels } ; treating as invalid "
187+ f"and falling back to XML document order. This could indicate "
188+ f"a bug; verify that channel order matches your expectation, "
189+ f"and please open an issue at "
190+ f"https://github.com/NeuralEnsemble/python-neo/issues if you "
191+ f"encounter this. See PR #1830 for an earlier report."
192+ )
193+
180194 channels_fit_chip_layout = intan_chans_per_chip > 0 and num_ephy_channels % intan_chans_per_chip == 0
181195 if not channels_fit_chip_layout :
182- return hw_chans_in_xml
196+ # The Trodes always write the data so the binary
197+ # stream is hwChan-ascending for every SpikeGadgets device. Source:
198+ # `Trodes/src-threads/recordThread.cpp` lines ~281-298 in the
199+ # canonical Trodes repo at https://bitbucket.org/mkarlsso/trodes
200+ # (checked May 2026). The correct ordering for the fallback path
201+ # is therefore hwChan ascending; sort rather than trust XML
202+ # document order in case the user reordered the xml
203+ return sorted (hw_chans_in_xml )
183204
184205 # Reproduce the chip-interleaved hwChan sequence (local-channel outer, chip inner)
185206 # so that hwchans_in_binary_order[i] is the hwChan whose data lives at byte pair i.
0 commit comments