Skip to content

Commit a3a4a37

Browse files
authored
Merge pull request #1041 from JuliaSprenger/enh/neuralynx_multi_rate
[Neuralynx] Add multiple streams
2 parents 2c863ff + bd33c15 commit a3a4a37

File tree

5 files changed

+334
-120
lines changed

5 files changed

+334
-120
lines changed

neo/io/neuralynxio.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ def __init__(self, dirname='', filename='', use_cache=False, cache_path='same_as
3535
----------
3636
dirname : str
3737
Directory containing data files
38+
filename : str
39+
Name of a single ncs, nse, nev, or ntt file to include in dataset. Will be ignored,
40+
if dirname is provided.
3841
use_cache : bool, optional
3942
Cache results of initial file scans for faster loading in subsequent runs.
4043
Default: False

neo/rawio/neuralynxrawio/ncssections.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ def __hash__(self):
2727
return (f'{self.sampFreqUsed};{self.microsPerSampUsed};'
2828
f'{[s.__hash__() for s in self.sects]}').__hash__()
2929

30+
def is_equivalent(self, other, rel_tol=0, abs_tol=0):
31+
if len(self.sects) != len(other.sects):
32+
return False
33+
else:
34+
# do not check for gaps if only a single section is present
35+
for sec_id in range(len(self.sects) - 1):
36+
if not self.sects[sec_id].is_equivalent(
37+
other.sects[sec_id], rel_tol=rel_tol, abs_tol=abs_tol):
38+
return False
39+
return True
40+
3041

3142
class NcsSection:
3243
"""
@@ -66,6 +77,12 @@ def __hash__(self):
6677
s = f'{self.startRec};{self.startTime};{self.endRec};{self.endTime};{self.n_samples}'
6778
return s.__hash__()
6879

80+
def is_equivalent(self, other, rel_tol=0, abs_tol=0):
81+
eq_start = math.isclose(self.startTime, other.startTime, rel_tol=rel_tol, abs_tol=abs_tol)
82+
eq_end = math.isclose(self.endTime, other.endTime, rel_tol=rel_tol, abs_tol=abs_tol)
83+
return eq_start & eq_end
84+
85+
6986
def before_time(self, rhb):
7087
"""
7188
Determine if this section is completely before another section in time.
@@ -211,9 +228,9 @@ def _buildGivenActualFrequency(ncsMemMap, actualSampFreq, reqFreq):
211228
raise IOError("Sampling frequency in first record doesn't agree with header.")
212229
chanNum = ncsMemMap['channel_id'][0]
213230

214-
nb = NcsSections()
215-
nb.sampFreqUsed = actualSampFreq
216-
nb.microsPerSampUsed = NcsSectionsFactory.get_micros_per_samp_for_freq(actualSampFreq)
231+
secs = NcsSections()
232+
secs.sampFreqUsed = actualSampFreq
233+
secs.microsPerSampUsed = NcsSectionsFactory.get_micros_per_samp_for_freq(actualSampFreq)
217234

218235
# check if file is one block of records, which is often the case, and avoid full parse
219236
lastBlkI = ncsMemMap.shape[0] - 1
@@ -231,15 +248,15 @@ def _buildGivenActualFrequency(ncsMemMap, actualSampFreq, reqFreq):
231248
n_samples = NcsSection._RECORD_SIZE * lastBlkI
232249
curBlock = NcsSection(0, ts0, lastBlkI, lastBlkEndTime, n_samples)
233250

234-
nb.sects.append(curBlock)
235-
return nb
251+
secs.sects.append(curBlock)
252+
return secs
236253

237254
# otherwise need to scan looking for breaks
238255
else:
239256
blkOnePredTime = NcsSectionsFactory.calc_sample_time(actualSampFreq, ts0, nb0)
240257
curBlock = NcsSection(0, ts0, -1, -1, -1)
241-
nb.sects.append(curBlock)
242-
return NcsSectionsFactory._parseGivenActualFrequency(ncsMemMap, nb, chanNum, reqFreq,
258+
secs.sects.append(curBlock)
259+
return NcsSectionsFactory._parseGivenActualFrequency(ncsMemMap, secs, chanNum, reqFreq,
243260
blkOnePredTime)
244261

245262
@staticmethod
@@ -369,7 +386,7 @@ def _buildForMaxGap(ncsMemMap, nomFreq):
369386
endTime = NcsSectionsFactory.calc_sample_time(nomFreq, lts, lnb)
370387
curBlock = NcsSection(0, ts0, lastBlkI, endTime, numSampsForPred)
371388
nb.sects.append(curBlock)
372-
nb.sampFreqUsed = numSampsForPred / (lts - ts0) * 1e6
389+
nb.sampFreqUsed = (numSampsForPred + lnb) / (endTime - ts0) * 1e6
373390
nb.microsPerSampUsed = NcsSectionsFactory.get_micros_per_samp_for_freq(nb.sampFreqUsed)
374391

375392
# otherwise parse records to determine blocks using default maximum gap length

0 commit comments

Comments
 (0)