Skip to content

Commit 5d5a920

Browse files
authored
Merge branch 'master' into release-14.2
2 parents b19a4b5 + 10d6ab5 commit 5d5a920

File tree

6 files changed

+96
-75
lines changed

6 files changed

+96
-75
lines changed

.github/workflows/plexon2-testing.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@ name: NeoPlexon2Test
22

33
on:
44
workflow_dispatch:
5-
schedule:
6-
- cron: "0 12 * * 0" # weekly at noon UTC on Sundays
5+
schedule:
6+
- cron: "0 12 * * 0" # weekly at noon UTC on Sundays
77

88

99
jobs:
1010
build-and-test:
11-
name: Test on (${{ inputs.os }}) (${{ matrix.python-version}}) (${{ matrix.numpy-version }})
12-
runs-on: ${{ inputs.os }}
11+
name: Test on (${{ matrix.os }}) (${{ matrix.python-version}}) (${{ matrix.numpy-version }})
12+
runs-on: ${{ matrix.os }}
1313
strategy:
1414
fail-fast: true
1515
matrix:
16+
os: [ubuntu-latest]
1617
python-version: ['3.9', '3.12']
1718
numpy-version: ['1.26', '2.0']
1819
defaults:

neo/rawio/neuralynxrawio/ncssections.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class AcqType(IntEnum):
5151
ATLAS = auto()
5252
UNKNOWN = auto()
5353

54+
5455
class NcsSections:
5556
"""
5657
Contains information regarding the contiguous sections of records in an Ncs file.
@@ -279,8 +280,13 @@ def build_for_ncs_file(ncsMemMap, nlxHdr, gapTolerance=None, strict_gap_mode=Tru
279280
ncsSects.sampFreqUsed = sampFreqUsed
280281
ncsSects.microsPerSampUsed = microsPerSampUsed
281282

282-
elif acqType in [AcqType.DIGITALLYNX, AcqType.DIGITALLYNXSX, AcqType.CHEETAH64,
283-
AcqType.CHEETAH560, AcqType.RAWDATAFILE]:
283+
elif acqType in [
284+
AcqType.DIGITALLYNX,
285+
AcqType.DIGITALLYNXSX,
286+
AcqType.CHEETAH64,
287+
AcqType.CHEETAH560,
288+
AcqType.RAWDATAFILE,
289+
]:
284290
# digital lynx style with fractional frequency and micros per samp determined from block times
285291
if gapTolerance is None:
286292
if strict_gap_mode:

neo/rawio/neuralynxrawio/nlxheader.py

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,13 @@ def _to_bool(txt):
8484
#
8585
# There are now separate patterns for the in header line and in properties cases which cover
8686
# the known variations in each case. They are compiled here once for efficiency.
87-
_openDatetime1_pat = re.compile(r"## (Time|Date) Opened:* \((m/d/y|mm/dd/yyy)\): (?P<date>\S+)"\
88-
r"\s+(\(h:m:s\.ms\)|At Time:) (?P<time>\S+)")
87+
_openDatetime1_pat = re.compile(
88+
r"## (Time|Date) Opened:* \((m/d/y|mm/dd/yyy)\): (?P<date>\S+)" r"\s+(\(h:m:s\.ms\)|At Time:) (?P<time>\S+)"
89+
)
8990
_openDatetime2_pat = re.compile(r"-TimeCreated (?P<date>\S+) (?P<time>\S+)")
90-
_closeDatetime1_pat = re.compile(r"## (Time|Date) Closed:* \((m/d/y|mm/dd/yyy)\): " \
91-
r"(?P<date>\S+)\s+(\(h:m:s\.ms\)|At Time:) (?P<time>\S+)")
91+
_closeDatetime1_pat = re.compile(
92+
r"## (Time|Date) Closed:* \((m/d/y|mm/dd/yyy)\): " r"(?P<date>\S+)\s+(\(h:m:s\.ms\)|At Time:) (?P<time>\S+)"
93+
)
9294
_closeDatetime2_pat = re.compile(r"-TimeClosed (?P<date>\S+) (?P<time>\S+)")
9395

9496
# Precompiled filename pattern
@@ -287,8 +289,9 @@ def _setBitToMicroVolt(self):
287289
if len(btm_entries) == 1:
288290
btm_entries = btm_entries * len(self["channel_ids"])
289291
self["bit_to_microVolt"] = [float(e) * 1e6 for e in btm_entries]
290-
assert len(self["bit_to_microVolt"]) == len( self["channel_ids"]), \
291-
"Number of channel ids does not match bit_to_microVolt conversion factors."
292+
assert len(self["bit_to_microVolt"]) == len(
293+
self["channel_ids"]
294+
), "Number of channel ids does not match bit_to_microVolt conversion factors."
292295

293296
def _setInputRanges(self, numChidEntries):
294297
if "InputRange" in self:
@@ -297,44 +300,48 @@ def _setInputRanges(self, numChidEntries):
297300
self["InputRange"] = [int(ir_entries[0])] * numChidEntries
298301
else:
299302
self["InputRange"] = [int(e) for e in ir_entries]
300-
assert len(self["InputRange"]) == numChidEntries, \
301-
"Number of channel ids does not match input range values."
303+
assert len(self["InputRange"]) == numChidEntries, "Number of channel ids does not match input range values."
302304

303305
def _setFilenameProp(self, txt_header):
304306
"""
305307
Add an OriginalFileName property if in header.
306308
"""
307-
if not 'OriginalFileName' in self.keys():
309+
if not "OriginalFileName" in self.keys():
308310
fnm = NlxHeader._filename_pat.search(txt_header)
309-
if not fnm: return
310-
else: self['OriginalFileName'] = fnm.group(1).strip(' "\t\r\n')
311+
if not fnm:
312+
return
313+
else:
314+
self["OriginalFileName"] = fnm.group(1).strip(' "\t\r\n')
311315
else:
312316
# some file types quote the property so strip that also
313-
self['OriginalFileName'] = self['OriginalFileName'].strip(' "\t\r\n')
317+
self["OriginalFileName"] = self["OriginalFileName"].strip(' "\t\r\n')
314318

315319
def _setTimeDate(self, txt_header):
316320
"""
317321
Read time and date from text of header
318322
"""
319323
import dateutil
324+
320325
# opening time
321326
sr = NlxHeader._openDatetime1_pat.search(txt_header)
322-
if not sr: sr=NlxHeader._openDatetime2_pat.search(txt_header)
327+
if not sr:
328+
sr = NlxHeader._openDatetime2_pat.search(txt_header)
323329
if not sr:
324330
raise IOError(
325-
f"No matching header open date/time for application {self['ApplicationName']} " +
326-
f"version {self['ApplicationVersion']}. Please contact developers."
331+
f"No matching header open date/time for application {self['ApplicationName']} "
332+
+ f"version {self['ApplicationVersion']}. Please contact developers."
327333
)
328334
else:
329335
dt1 = sr.groupdict()
330-
self['recording_opened'] = dateutil.parser.parse(f"{dt1['date']} {dt1['time']}")
336+
self["recording_opened"] = dateutil.parser.parse(f"{dt1['date']} {dt1['time']}")
331337

332338
# close time, if available
333339
sr = NlxHeader._closeDatetime1_pat.search(txt_header)
334-
if not sr: sr=NlxHeader._closeDatetime2_pat.search(txt_header)
340+
if not sr:
341+
sr = NlxHeader._closeDatetime2_pat.search(txt_header)
335342
if sr:
336343
dt2 = sr.groupdict()
337-
self['recording_closed'] = dateutil.parser.parse(f"{dt2['date']} {dt2['time']}")
344+
self["recording_closed"] = dateutil.parser.parse(f"{dt2['date']} {dt2['time']}")
338345

339346
def type_of_recording(self):
340347
"""

neo/rawio/neuronexusrawio.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ def _parse_header(self):
132132
self._n_samples, self._n_channels = self.metadata["status"]["shape"]
133133
# Stored as a simple float32 binary file
134134
BINARY_DTYPE = "float32"
135-
TIMESTAMP_DTYPE = "int64" # this is from the allego sample reader timestamps are np.int64
135+
TIMESTAMP_DTYPE = "int64" # this is from the allego sample reader timestamps are np.int64
136136
binary_file = self.binary_file
137137
timestamp_file = self.timestamp_file
138138

@@ -150,7 +150,7 @@ def _parse_header(self):
150150
# Make the memory map for timestamp
151151
self._timestamps = np.memmap(
152152
timestamp_file,
153-
dtype=TIMESTAMP_DTYPE,
153+
dtype=TIMESTAMP_DTYPE,
154154
mode="r",
155155
offset=0, # headerless binary file
156156
)

neo/rawio/spikeglxrawio.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ def _parse_header(self):
184184
chan_id = f"{stream_name}#{chan_name}"
185185

186186
# Separate sync channel in its own stream
187-
is_sync_channel = "SY" in chan_name and not self.load_sync_channel
188-
if is_sync_channel :
187+
is_sync_channel = "SY" in chan_name and not self.load_sync_channel
188+
if is_sync_channel:
189189
# This is a sync channel and should be added as its own stream
190190
sync_stream_id = f"{stream_name}-SYNC"
191191
sync_stream_id_to_buffer_id[sync_stream_id] = buffer_id
@@ -387,7 +387,7 @@ def scan_files(dirname):
387387
continue
388388
meta_filename = Path(root) / file
389389
bin_filename = meta_filename.with_suffix(".bin")
390-
390+
391391
if meta_filename.exists() and bin_filename.exists():
392392
meta = read_meta_file(meta_filename)
393393
info = extract_stream_info(meta_filename, meta)
@@ -401,6 +401,7 @@ def scan_files(dirname):
401401

402402
return info_list
403403

404+
404405
def _add_segment_order(info_list):
405406
"""
406407
Uses gate and trigger numbers to construct a segment index (`seg_index`) for each signal in `info_list`.
@@ -413,7 +414,7 @@ def _add_segment_order(info_list):
413414
"""
414415
# This sets non-integers values before integers
415416
normalize = lambda x: x if isinstance(x, int) else -1
416-
417+
417418
# Segment index is determined by the gate_num and trigger_num in that order
418419
def get_segment_tuple(info):
419420
# Create a key from the normalized gate_num and trigger_num
@@ -475,7 +476,7 @@ def parse_spikeglx_fname(fname):
475476
stream_kind: str or None
476477
The data type identifier, "lf", "ap", "obx", or None
477478
"""
478-
479+
479480
# Standard case: contains gate, trigger, device, and stream kind
480481
# Example: Noise4Sam_g0_t0.imec0.ap
481482
# Format: {run_name}_g{gate_num}_t{trigger_num}.{device}.{stream_kind}
@@ -502,7 +503,7 @@ def parse_spikeglx_fname(fname):
502503
gd = match.groupdict()
503504
return gd["run_name"], int(gd["gate_num"]), "cat", gd["device"], gd["stream_kind"]
504505

505-
# OneBox case: ends in .obx
506+
# OneBox case: ends in .obx
506507
# Example: myRun_g0_t0.obx0.obx
507508
# Format: {run_name}_g{gate_num}_t{trigger_num}.{device}.obx
508509
# Regex tokens:
@@ -641,7 +642,7 @@ def extract_stream_info(meta_file, meta):
641642
device = fname.split(".")[-2] if "." in fname else device
642643
stream_kind = ""
643644
units = "V"
644-
645+
645646
# OneBox gain calculation
646647
# V = i * Vmax / Imax where Imax = obMaxInt, Vmax = obAiRangeMax
647648
# See: https://billkarsh.github.io/SpikeGLX/Sgl_help/Metadata_30.html
@@ -669,7 +670,7 @@ def extract_stream_info(meta_file, meta):
669670
probe_slot = meta.get("imDatPrb_slot", None)
670671
probe_port = meta.get("imDatPrb_port", None)
671672
probe_dock = meta.get("imDatPrb_dock", None)
672-
673+
673674
# OneBox specific metadata
674675
obx_slot = meta.get("imDatObx_slot", None)
675676

@@ -697,10 +698,10 @@ def extract_stream_info(meta_file, meta):
697698
info["probe_port"] = int(probe_port) if probe_port else None
698699
info["probe_dock"] = int(probe_dock) if probe_dock else None
699700
info["obx_slot"] = int(obx_slot) if obx_slot else None
700-
701+
701702
# Add device index
702703
if info.get("device_kind") == "imec":
703-
info["device_index"] = info["device"].split("imec")[-1]
704+
info["device_index"] = info["device"].split("imec")[-1]
704705
elif info.get("device_kind") == "obx":
705706
info["device_index"] = info["device"].split("obx")[-1]
706707
else:
@@ -732,5 +733,4 @@ def extract_stream_info(meta_file, meta):
732733
info["digital_channels"] = [channel for channel in info["channel_names"] if channel.startswith("XD")]
733734
info["analog_channels"] = [channel for channel in info["channel_names"] if channel.startswith("XA")]
734735

735-
736736
return info

0 commit comments

Comments
 (0)