@@ -402,11 +402,23 @@ def get_annotations(self, index=None):
402402 list of dict
403403 Each dictionary contains one annotation for the sample at `index`.
404404 '''
405- return [
406- x for x in self ._metadata .get (self .ANNOTATION_KEY , [])
407- if index is None or (x [self .START_INDEX_KEY ] <= index
408- and x [self .START_INDEX_KEY ] + x [self .LENGTH_INDEX_KEY ] > index )
409- ]
405+ annotations = self ._metadata .get (self .ANNOTATION_KEY , [])
406+ if index is None :
407+ return annotations
408+
409+ annotations_including_index = []
410+ for annotation in annotations :
411+ if index < annotation [self .START_INDEX_KEY ]:
412+ # index is before annotation starts -> skip
413+ continue
414+ if self .LENGTH_INDEX_KEY in annotation :
415+ # Annotation includes sample_count -> check end index
416+ if index >= annotation [self .START_INDEX_KEY ] + annotation [self .LENGTH_INDEX_KEY ]:
417+ # index is after annotation end -> skip
418+ continue
419+
420+ annotations_including_index .append (annotation )
421+ return annotations_including_index
410422
411423 def get_sample_size (self ):
412424 """
@@ -418,16 +430,13 @@ def get_sample_size(self):
418430 def _count_samples (self ):
419431 """
420432 Count, set, and return the total number of samples in the data file.
421- If there is no data file but there are annotations, use the end index
422- of the final annotation instead. If there are no annotations, use 0.
433+ If there is no data file but there are annotations, use the sample_count
434+ from the annotation with the highest end index. If there are no annotations,
435+ use 0.
423436 For complex data, a 'sample' includes both the real and imaginary part.
424437 """
425- annotations = self .get_annotations ()
426438 if self .data_file is None :
427- if len (annotations ) > 0 :
428- sample_count = annotations [- 1 ][self .START_INDEX_KEY ] + annotations [- 1 ][self .LENGTH_INDEX_KEY ]
429- else :
430- sample_count = 0
439+ sample_count = self ._get_sample_count_from_annotations ()
431440 else :
432441 header_bytes = sum ([c .get (self .HEADER_BYTES_KEY , 0 ) for c in self .get_captures ()])
433442 file_size = path .getsize (self .data_file ) if self .offset_and_size is None else self .offset_and_size [1 ]
@@ -438,12 +447,32 @@ def _count_samples(self):
438447 if file_data_size % (sample_size * num_channels ) != 0 :
439448 warnings .warn (f'File `{ self .data_file } ` does not contain an integer '
440449 'number of samples across channels. It may be invalid data.' )
441- if len ( annotations ) > 0 and annotations [ - 1 ][ self .START_INDEX_KEY ] + annotations [ - 1 ][ self . LENGTH_INDEX_KEY ] > sample_count :
450+ if self ._get_sample_count_from_annotations () > sample_count :
442451 warnings .warn (f'File `{ self .data_file } ` ends before the final annotation '
443452 'in the corresponding SigMF metadata.' )
444453 self .sample_count = sample_count
445454 return sample_count
446455
456+ def _get_sample_count_from_annotations (self ):
457+ """
458+ Returns the number of samples based on annotation with highest end index.
459+ NOTE: Annotations are ordered by START_INDEX_KEY and not end index, so we
460+ need to go through all annotations
461+ """
462+ annon_sample_count = []
463+ for annon in self .get_annotations ():
464+ if self .LENGTH_INDEX_KEY in annon :
465+ # Annotation with sample_count
466+ annon_sample_count .append (annon [self .START_INDEX_KEY ] + annon [self .LENGTH_INDEX_KEY ])
467+ else :
468+ # Annotation without sample_count - sample count must be at least sample_start
469+ annon_sample_count .append (annon [self .START_INDEX_KEY ])
470+
471+ if annon_sample_count :
472+ return max (annon_sample_count )
473+ else :
474+ return 0
475+
447476 def calculate_hash (self ):
448477 """
449478 Calculates the hash of the data file and adds it to the global section.
0 commit comments