@@ -51,13 +51,13 @@ class NcsSection:
5151
5252 _RECORD_SIZE = 512 # nb sample per signal record
5353
54- def __init__ (self , sb , st , eb , et , ns ):
55- self .startRec = sb # index of starting record
56- self .startTime = st # starttime of first record
57- self .endRec = eb # index of last record (inclusive)
58- self .endTime = et # end time of last record, that is, the end time of the last
54+ def __init__ (self , startRec , startTime , endRec , endTime , n_samples ):
55+ self .startRec = startRec # index of starting record
56+ self .startTime = startTime # starttime of first record
57+ self .endRec = endRec # index of last record (inclusive)
58+ self .endTime = endTime # end time of last record, that is, the end time of the last
5959 # sampling period contained in the last record of the section
60- self .n_samples = ns # number of samples in record which are valid
60+ self .n_samples = n_samples # number of samples in record which are valid
6161
6262 def __eq__ (self , other ):
6363 return (
@@ -159,33 +159,26 @@ def _parseGivenActualFrequency(ncsMemMap, ncsSects, chanNum, reqFreq, blkOnePred
159159 -------
160160 NcsSections object with block locations marked
161161 """
162- startBlockPredTime = blkOnePredTime
163- blk_len = 0
164- curBlock = ncsSects .sects [0 ]
165- for recn in range (1 , ncsMemMap .shape [0 ]):
166- timestamp = ncsMemMap ["timestamp" ][recn ]
167- channel_id = ncsMemMap ["channel_id" ][recn ]
168- sample_rate = ncsMemMap ["sample_rate" ][recn ]
169- nb_valid = ncsMemMap ["nb_valid" ][recn ]
170-
171- if channel_id != chanNum or sample_rate != reqFreq :
172- raise IOError ("Channel number or sampling frequency changed in " + "records within file" )
173- predTime = NcsSectionsFactory .calc_sample_time (ncsSects .sampFreqUsed , startBlockPredTime , blk_len )
174- nValidSamps = nb_valid
175- if timestamp != predTime :
176- curBlock .endRec = recn - 1
177- curBlock .endTime = predTime
178- curBlock .n_samples = blk_len
179- curBlock = NcsSection (recn , timestamp , - 1 , - 1 , - 1 )
180- ncsSects .sects .append (curBlock )
181- startBlockPredTime = NcsSectionsFactory .calc_sample_time (ncsSects .sampFreqUsed , timestamp , nValidSamps )
182- blk_len = 0
183- else :
184- blk_len += nValidSamps
185-
186- curBlock .endRec = ncsMemMap .shape [0 ] - 1
187- endTime = NcsSectionsFactory .calc_sample_time (ncsSects .sampFreqUsed , startBlockPredTime , blk_len )
188- curBlock .endTime = endTime
162+
163+ # New code numpy vector based (speedup X50)
164+ delta = (ncsMemMap ["timestamp" ][1 :] - ncsMemMap ["timestamp" ][:- 1 ]).astype (np .int64 )
165+ delta_prediction = ((ncsMemMap ["nb_valid" ][:- 1 ] / ncsSects .sampFreqUsed ) * 1e6 ).astype (np .int64 )
166+ gap_inds = np .flatnonzero ((delta - delta_prediction ) != 0 )
167+ gap_inds += 1
168+ sections_limits = [ 0 ] + gap_inds .tolist () + [len (ncsMemMap )]
169+
170+ for i in range (len (gap_inds ) + 1 ):
171+ start = sections_limits [i ]
172+ stop = sections_limits [i + 1 ]
173+ ncsSects .sects .append (
174+ NcsSection (
175+ startRec = start ,
176+ startTime = ncsMemMap ["timestamp" ][start ],
177+ endRec = stop - 1 ,
178+ endTime = ncsMemMap ["timestamp" ][stop - 1 ] + np .uint64 (ncsMemMap ["nb_valid" ][stop - 1 ] / ncsSects .sampFreqUsed * 1e6 ),
179+ n_samples = np .sum (ncsMemMap ["nb_valid" ][start :stop ])
180+ )
181+ )
189182
190183 return ncsSects
191184
@@ -219,9 +212,9 @@ def _buildGivenActualFrequency(ncsMemMap, actualSampFreq, reqFreq):
219212 raise IOError ("Sampling frequency in first record doesn't agree with header." )
220213 chanNum = ncsMemMap ["channel_id" ][0 ]
221214
222- secs = NcsSections ()
223- secs .sampFreqUsed = actualSampFreq
224- secs .microsPerSampUsed = NcsSectionsFactory .get_micros_per_samp_for_freq (actualSampFreq )
215+ ncsSects = NcsSections ()
216+ ncsSects .sampFreqUsed = actualSampFreq
217+ ncsSects .microsPerSampUsed = NcsSectionsFactory .get_micros_per_samp_for_freq (actualSampFreq )
225218
226219 # check if file is one block of records, which is often the case, and avoid full parse
227220 lastBlkI = ncsMemMap .shape [0 ] - 1
@@ -241,15 +234,17 @@ def _buildGivenActualFrequency(ncsMemMap, actualSampFreq, reqFreq):
241234 n_samples = NcsSection ._RECORD_SIZE * lastBlkI
242235 curBlock = NcsSection (0 , ts0 , lastBlkI , lastBlkEndTime , n_samples )
243236
244- secs .sects .append (curBlock )
245- return secs
237+ ncsSects .sects .append (curBlock )
238+ return ncsSects
246239
247- # otherwise need to scan looking for breaks
240+
248241 else :
242+ # otherwise need to scan looking for data gaps
249243 blkOnePredTime = NcsSectionsFactory .calc_sample_time (actualSampFreq , ts0 , nb0 )
250- curBlock = NcsSection (0 , ts0 , - 1 , - 1 , - 1 )
251- secs .sects .append (curBlock )
252- return NcsSectionsFactory ._parseGivenActualFrequency (ncsMemMap , secs , chanNum , reqFreq , blkOnePredTime )
244+ # curBlock = NcsSection(0, ts0, -1, -1, -1)
245+ # ncsSects.sects.append(curBlock)
246+ ncsSects = NcsSectionsFactory ._parseGivenActualFrequency (ncsMemMap , ncsSects , chanNum , reqFreq , blkOnePredTime )
247+ return ncsSects
253248
254249 @staticmethod
255250 def _parseForMaxGap (ncsMemMap , ncsSects , maxGapLen ):
0 commit comments