Skip to content

Commit 4cef438

Browse files
Peter N. SteinmetzPeter N. Steinmetz
authored andcommitted
Eliminating datetimeformats and tests of header processing.
1 parent c53157d commit 4cef438

File tree

2 files changed

+76
-26
lines changed

2 files changed

+76
-26
lines changed

neo/rawio/neuralynxrawio/nlxheader.py

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import datetime
2+
import dateutil
23
from packaging.version import Version
34
import os
45
import re
@@ -281,7 +282,6 @@ def convert_channel_ids_names(self, filename):
281282
r" At Time: (?P<time>\S+)",
282283
datetime2_regex=r"## (Time|Date) Closed:* \((m/d/y|mm/dd/yyy)\): (?P<date>\S+)" \
283284
r" At Time: (?P<time>\S+)",
284-
datetimeformat="%m/%d/%Y %H:%M:%S",
285285
),
286286
# pegasus version 2.1.1 and Cheetah beyond version 5.6.4 - example
287287
# ######## Neuralynx Data File Header
@@ -292,21 +292,17 @@ def convert_channel_ids_names(self, filename):
292292
"inProps": dict(
293293
datetime1_regex=r"-TimeCreated (?P<date>\S+) (?P<time>\S+)",
294294
datetime2_regex=r"-TimeClosed (?P<date>\S+) (?P<time>\S+)",
295-
datetimeformat=r"%Y/%m/%d %H:%M:%S",
296-
datetime2format=r"%Y/%m/%d %H:%M:%S.%f",
297295
),
298296
# general version for date and time in ## header lines
299297
"inHeader": dict(
300298
datetime1_regex=r"## Time Opened: \(m/d/y\): (?P<date>\S+)" r" At Time: (?P<time>\S+)",
301-
datetimeformat="%m/%d/%y %H:%M:%S.%f",
302299
),
303300
# version with time open and closed in ## header lines
304301
"openClosedInHeader": dict(
305302
datetime1_regex=r"## (Time|Date) Opened:* \(m/d/y\): (?P<date>\S+)" \
306303
r" (\(h:m:s\.ms\)|At Time:) (?P<time>\S+)",
307304
datetime2_regex=r"## (Time|Date) Closed:* \(m/d/y\): (?P<date>\S+)" \
308305
r" (\(h:m:s\.ms\)|At Time:) (?P<time>\S+)",
309-
datetimeformat="%m/%d/%Y %H:%M:%S.%f",
310306
)
311307
}
312308

@@ -351,27 +347,14 @@ def readTimeDate(self, txt_header):
351347
hpd = NlxHeader.header_pattern_dicts["inProps"]
352348

353349
# opening time
354-
# :TODO: Processing for this and close time should be changed to not depend on storing
355-
# in a particular formatted string by header type, but rather always should be
356-
# formatted in one standard way.
357350
sr = re.search(hpd["datetime1_regex"], txt_header)
358351
if not sr:
359352
raise IOError(
360353
f"No matching header open date/time for application {an} " + f"version {av}. Please contact developers."
361354
)
362355
else:
363356
dt1 = sr.groupdict()
364-
try: # allow two possible formats for date and time
365-
self["recording_opened"] = datetime.datetime.strptime(
366-
dt1["date"] + " " + dt1["time"], hpd["datetimeformat"]
367-
)
368-
except:
369-
try:
370-
self["recording_opened"] = datetime.datetime.strptime(
371-
dt1["date"] + " " + dt1["time"], hpd["datetime2format"]
372-
)
373-
except:
374-
self["recording_opened"] = None
357+
self['recording_opened'] = dateutil.parser.parse(f"{dt1['date']} {dt1['time']}")
375358

376359
# close time, if available
377360
if "datetime2_regex" in hpd:
@@ -382,13 +365,8 @@ def readTimeDate(self, txt_header):
382365
+ f"version {av}. Please contact developers."
383366
)
384367
else:
385-
try:
386-
dt2 = sr.groupdict()
387-
self["recording_closed"] = datetime.datetime.strptime(
388-
dt2["date"] + " " + dt2["time"], hpd["datetimeformat"]
389-
)
390-
except:
391-
self["recording_closed"] = None
368+
dt2 = sr.groupdict()
369+
self['recording_closed'] = dateutil.parser.parse(f"{dt2['date']} {dt2['time']}")
392370

393371
def type_of_recording(self):
394372
"""

neo/test/rawiotest/test_neuralynxrawio.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import datetime
2+
import dateutil
23
import unittest
34

45
import os
56
import numpy as np
7+
import re
68

79
from neo.rawio.neuralynxrawio.neuralynxrawio import NeuralynxRawIO
810
from neo.rawio.neuralynxrawio.nlxheader import NlxHeader
@@ -383,5 +385,75 @@ def test_neuraview2(self):
383385
self.assertEqual(datetime.datetime(2015,12,14, 15,58,32), hdr['recording_opened'])
384386
self.assertEqual(datetime.datetime(2015,12,14, 15,58,32), hdr['recording_closed'])
385387

388+
def get_text_header(self, filename):
389+
with open(filename, "rb") as f:
390+
txt_header = f.read(NlxHeader.HEADER_SIZE)
391+
return txt_header.strip(b"\x00").decode("latin-1")
392+
393+
def check_dateutil_parse(self, hdrTxt, hdrPatternName, openDate, closeDate):
394+
hpd = NlxHeader.header_pattern_dicts[hdrPatternName]
395+
mtch = re.search(hpd["datetime1_regex"], hdrTxt)
396+
self.assertIsNotNone(mtch)
397+
dt = mtch.groupdict()
398+
date = dateutil.parser.parse(f"{dt['date']} {dt['time']}")
399+
self.assertEqual(openDate, date)
400+
if closeDate is not None:
401+
mtch = re.search(hpd["datetime2_regex"], hdrTxt)
402+
self.assertIsNotNone(mtch)
403+
dt = mtch.groupdict()
404+
date = dateutil.parser.parse(f"{dt['date']} {dt['time']}")
405+
self.assertEqual(closeDate, date)
406+
407+
def test_datetime_parsing(self):
408+
409+
# neuraview2 'neuraview2'
410+
filename = self.get_local_path("neuralynx/Neuraview_v2/original_data/NeuraviewEventMarkers-sample.nev")
411+
txt_header = self.get_text_header(filename)
412+
self.check_dateutil_parse(txt_header, 'neuraview2',
413+
datetime.datetime(2015,12,14, 15,58,32),
414+
datetime.datetime(2015,12,14, 15,58,32))
415+
hdr = NlxHeader(filename)
416+
self.assertEqual(datetime.datetime(2015,12,14, 15,58,32),
417+
hdr['recording_opened'])
418+
self.assertEqual(datetime.datetime(2015,12,14, 15,58,32),
419+
hdr['recording_closed'])
420+
421+
# Cheetah 5.7.4 'inProps'
422+
filename = self.get_local_path("neuralynx/Cheetah_v5.7.4/original_data/CSC1.ncs")
423+
txt_header = self.get_text_header(filename)
424+
self.check_dateutil_parse(txt_header, 'inProps',
425+
datetime.datetime(2017,2,16, 17,56,4),
426+
datetime.datetime(2017,2,16, 18,1,18))
427+
hdr = NlxHeader(filename)
428+
self.assertEqual(datetime.datetime(2017,2,16, 17,56,4),
429+
hdr['recording_opened'])
430+
self.assertEqual(datetime.datetime(2017,2,16, 18,1,18),
431+
hdr['recording_closed'])
432+
433+
# Cheetah 4.0.2 'inHeader'
434+
filename = self.get_local_path("neuralynx/Cheetah_v4.0.2/original_data/CSC14_trunc.Ncs")
435+
txt_header = self.get_text_header(filename)
436+
self.check_dateutil_parse(txt_header, 'inHeader',
437+
datetime.datetime(2003,10,4, 10,3,0, 578000),
438+
None)
439+
hdr = NlxHeader(filename)
440+
self.assertEqual(datetime.datetime(2003,10,4, 10,3,0, 578000),
441+
hdr['recording_opened'])
442+
self.assertIsNone(hdr.get('recording_closed'))
443+
444+
# Cheetah 5.4.0 'openClosedInHeader'
445+
filename = self.get_local_path("neuralynx/Cheetah_v5.4.0/original_data/CSC5_trunc.Ncs")
446+
txt_header = self.get_text_header(filename)
447+
self.check_dateutil_parse(txt_header, 'openClosedInHeader',
448+
datetime.datetime(2001,1,1, 0,0,0, 0),
449+
datetime.datetime(2001,1,1, 0,0,0, 0))
450+
hdr = NlxHeader(filename)
451+
self.assertEqual(datetime.datetime(2001,1,1, 0,0,0, 0),
452+
hdr['recording_opened'])
453+
self.assertEqual(datetime.datetime(2001,1,1, 0,0,0, 0),
454+
hdr['recording_closed'])
455+
456+
457+
386458
if __name__ == "__main__":
387459
unittest.main()

0 commit comments

Comments
 (0)