@@ -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,58 @@ 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+ # Old code with loops
164+
165+ # ts0 = ncsMemMap["timestamp"][0]
166+ # curBlock = NcsSection(0, ts0, -1, -1, -1)
167+ # ncsSects.sects.append(curBlock)
168+ # startBlockPredTime = blkOnePredTime
169+ # blk_len = 0
170+ # for recn in range(1, ncsMemMap.shape[0]):
171+ # timestamp = ncsMemMap["timestamp"][recn]
172+ # channel_id = ncsMemMap["channel_id"][recn]
173+ # sample_rate = ncsMemMap["sample_rate"][recn]
174+ # nb_valid = ncsMemMap["nb_valid"][recn]
175+
176+ # if channel_id != chanNum or sample_rate != reqFreq:
177+ # raise IOError("Channel number or sampling frequency changed in " + "records within file")
178+ # predTime = NcsSectionsFactory.calc_sample_time(ncsSects.sampFreqUsed, startBlockPredTime, blk_len)
179+ # nValidSamps = nb_valid
180+ # if timestamp != predTime:
181+ # curBlock.endRec = recn - 1
182+ # curBlock.endTime = predTime
183+ # curBlock.n_samples = blk_len
184+ # curBlock = NcsSection(recn, timestamp, -1, -1, -1)
185+ # ncsSects.sects.append(curBlock)
186+ # startBlockPredTime = NcsSectionsFactory.calc_sample_time(ncsSects.sampFreqUsed, timestamp, nValidSamps)
187+ # blk_len = 0
188+ # else:
189+ # blk_len += nValidSamps
190+ # curBlock.endRec = ncsMemMap.shape[0] - 1
191+ # endTime = NcsSectionsFactory.calc_sample_time(ncsSects.sampFreqUsed, startBlockPredTime, blk_len)
192+ # curBlock.endTime = endTime
193+
194+
195+ # New code numpy vector based (speedup X50)
196+ delta = (ncsMemMap ["timestamp" ][1 :] - ncsMemMap ["timestamp" ][:- 1 ]).astype (np .int64 )
197+ delta_prediction = ((ncsMemMap ["nb_valid" ][:- 1 ] / ncsSects .sampFreqUsed ) * 1e6 ).astype (np .int64 )
198+ gap_inds = np .flatnonzero ((delta - delta_prediction ) != 0 )
199+ gap_inds += 1
200+ sections_limits = [ 0 ] + gap_inds .tolist () + [len (ncsMemMap )]
201+
202+ for i in range (len (gap_inds ) + 1 ):
203+ start = sections_limits [i ]
204+ stop = sections_limits [i + 1 ]
205+ ncsSects .sects .append (
206+ NcsSection (
207+ startRec = start ,
208+ startTime = ncsMemMap ["timestamp" ][start ],
209+ endRec = stop - 1 ,
210+ endTime = ncsMemMap ["timestamp" ][stop - 1 ] + np .uint64 (ncsMemMap ["nb_valid" ][stop - 1 ] / ncsSects .sampFreqUsed * 1e6 ),
211+ n_samples = np .sum (ncsMemMap ["nb_valid" ][start :stop ])
212+ )
213+ )
189214
190215 return ncsSects
191216
@@ -219,9 +244,9 @@ def _buildGivenActualFrequency(ncsMemMap, actualSampFreq, reqFreq):
219244 raise IOError ("Sampling frequency in first record doesn't agree with header." )
220245 chanNum = ncsMemMap ["channel_id" ][0 ]
221246
222- secs = NcsSections ()
223- secs .sampFreqUsed = actualSampFreq
224- secs .microsPerSampUsed = NcsSectionsFactory .get_micros_per_samp_for_freq (actualSampFreq )
247+ ncsSects = NcsSections ()
248+ ncsSects .sampFreqUsed = actualSampFreq
249+ ncsSects .microsPerSampUsed = NcsSectionsFactory .get_micros_per_samp_for_freq (actualSampFreq )
225250
226251 # check if file is one block of records, which is often the case, and avoid full parse
227252 lastBlkI = ncsMemMap .shape [0 ] - 1
@@ -241,15 +266,17 @@ def _buildGivenActualFrequency(ncsMemMap, actualSampFreq, reqFreq):
241266 n_samples = NcsSection ._RECORD_SIZE * lastBlkI
242267 curBlock = NcsSection (0 , ts0 , lastBlkI , lastBlkEndTime , n_samples )
243268
244- secs .sects .append (curBlock )
245- return secs
269+ ncsSects .sects .append (curBlock )
270+ return ncsSects
246271
247- # otherwise need to scan looking for breaks
272+
248273 else :
274+ # otherwise need to scan looking for data gaps
249275 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 )
276+ # curBlock = NcsSection(0, ts0, -1, -1, -1)
277+ # ncsSects.sects.append(curBlock)
278+ ncsSects = NcsSectionsFactory ._parseGivenActualFrequency (ncsMemMap , ncsSects , chanNum , reqFreq , blkOnePredTime )
279+ return ncsSects
253280
254281 @staticmethod
255282 def _parseForMaxGap (ncsMemMap , ncsSects , maxGapLen ):
0 commit comments