Skip to content

Commit

Permalink
Add strict_gap_mode=True/False to handle new clock sustem in neuralynx
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelgarcia committed Mar 4, 2024
1 parent 23bc316 commit 28cc1a5
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 7 deletions.
22 changes: 18 additions & 4 deletions neo/rawio/neuralynxrawio/ncssections.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ def _buildNcsGeneric(ncsMemMap, sampFreq, gapTolerance=0):
return ncsSects

@staticmethod
def build_for_ncs_file(ncsMemMap, nlxHdr, gapTolerance=None):
def build_for_ncs_file(ncsMemMap, nlxHdr, gapTolerance=None, strict_gap_mode=True):
"""
Build an NcsSections object for an NcsFile, given as a memmap and NlxHeader,
handling gap detection appropriately given the file type as specified by the header.
Expand All @@ -512,15 +512,25 @@ def build_for_ncs_file(ncsMemMap, nlxHdr, gapTolerance=None):
microsPerSampUsed = math.floor(NcsSectionsFactory.get_micros_per_samp_for_freq(freq))
sampFreqUsed = NcsSectionsFactory.get_freq_for_micros_per_samp(microsPerSampUsed)
if gapTolerance is None:
gapTolerance = 0
if strict_gap_mode:
# this is the old behavior, maybe we could put 0.9 sample interval no ?
gapTolerance = 0
else:
gapTolerance = 0

ncsSects = NcsSectionsFactory._buildNcsGeneric(ncsMemMap, sampFreqUsed, gapTolerance=gapTolerance)
ncsSects.sampFreqUsed = sampFreqUsed
ncsSects.microsPerSampUsed = microsPerSampUsed

elif acqType in ["DIGITALLYNX", "DIGITALLYNXSX", "CHEETAH64", "CHEETAH560", "RAWDATAFILE"]:
# digital lynx style with fractional frequency and micros per samp determined from block times
if gapTolerance is None:
gapTolerance = round(NcsSectionsFactory._maxGapSampFrac * 1e6 / freq)
if strict_gap_mode:
# this is the old behavior
gapTolerance = round(NcsSectionsFactory._maxGapSampFrac * 1e6 / freq)
else:
# quarter of paquet size is tolerate
gapTolerance = round(0.25 * NcsSection._RECORD_SIZE * 1e6 / freq)
ncsSects = NcsSectionsFactory._buildNcsGeneric(ncsMemMap, freq, gapTolerance=gapTolerance)


Expand All @@ -543,8 +553,12 @@ def build_for_ncs_file(ncsMemMap, nlxHdr, gapTolerance=None):

elif acqType == "BML" or acqType == "ATLAS":
# BML & ATLAS style with fractional frequency and micros per samp
if gapTolerance is None:
if strict_gap_mode:
# this is the old behavior, maybe we could put 0.9 sample interval no ?
gapTolerance = 0
else:
# quarter of paquet size is tolerate
gapTolerance = round(0.25 * NcsSection._RECORD_SIZE * 1e6 / freq)
ncsSects = NcsSectionsFactory._buildNcsGeneric(ncsMemMap, freq, gapTolerance=gapTolerance)
ncsSects.sampFreqUsed = freq
ncsSects.microsPerSampUsed = NcsSectionsFactory.get_micros_per_samp_for_freq(freq)
Expand Down
13 changes: 10 additions & 3 deletions neo/rawio/neuralynxrawio/neuralynxrawio.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,13 @@ class NeuralynxRawIO(BaseRawIO):
keep_original_times: bool, default: False
If True, keep original start time as in files,
Otherwise set 0 of time to first time in dataset
strict_gap_mode: bool, default: True
Detect gaps using strict mode or not.
* strict_gap_mode = True then a gap is consider when timstamp difference between two
consequtive data packet is more than one sample interval.
* strict_gap_mode = False then a gap has an increased tolerance. Some new system with different clock need this option
otherwise, too many gaps are detected
Notes
-----
* This IO supports NCS, NEV, NSE and NTT file formats (not NVT or NRD yet)
Expand Down Expand Up @@ -125,7 +131,7 @@ class NeuralynxRawIO(BaseRawIO):
("samples", "int16", (NcsSection._RECORD_SIZE)),
]

def __init__(self, dirname="", filename="", exclude_filename=None, keep_original_times=False, **kargs):
def __init__(self, dirname="", filename="", exclude_filename=None, keep_original_times=False, strict_gap_mode=True, **kargs):

if dirname != "":
self.dirname = dirname
Expand All @@ -137,6 +143,7 @@ def __init__(self, dirname="", filename="", exclude_filename=None, keep_original
raise ValueError("One of dirname or filename must be provided.")

self.keep_original_times = keep_original_times
self.strict_gap_mode = strict_gap_mode
self.exclude_filename = exclude_filename
BaseRawIO.__init__(self, **kargs)

Expand Down Expand Up @@ -790,7 +797,7 @@ def scan_stream_ncs_files(self, ncs_filenames):

verify_sec_struct = NcsSectionsFactory._verifySectionsStructure
if not chanSectMap or (not verify_sec_struct(data, chan_ncs_sections)):
chan_ncs_sections = NcsSectionsFactory.build_for_ncs_file(data, nlxHeader)
chan_ncs_sections = NcsSectionsFactory.build_for_ncs_file(data, nlxHeader, strict_gap_mode=self.strict_gap_mode)

# register file section structure for all contained channels
for chan_uid in zip(nlxHeader["channel_names"], np.asarray(nlxHeader["channel_ids"], dtype=str)):
Expand Down

0 comments on commit 28cc1a5

Please sign in to comment.