@@ -390,18 +390,14 @@ def _read(cls, fileobj, header, buffer_size=4):
390
390
buffer_size = int (buffer_size * MEGABYTE )
391
391
buffer_size += coordinate_size - (buffer_size % coordinate_size )
392
392
393
- # Markers for streamline end and file end
394
- fiber_marker = cls .FIBER_DELIMITER .astype (dtype ).tostring ()
395
- eof_marker = cls .EOF_DELIMITER .astype (dtype ).tostring ()
396
-
397
393
with Opener (fileobj ) as f :
398
394
start_position = f .tell ()
399
395
400
396
# Set the file position at the beginning of the data.
401
397
f .seek (header ["_offset_data" ], os .SEEK_SET )
402
398
403
399
eof = False
404
- buffs = []
400
+ leftover = np . empty (( 0 , 3 ), dtype = '<f4' )
405
401
n_streams = 0
406
402
407
403
while not eof :
@@ -411,37 +407,36 @@ def _read(cls, fileobj, header, buffer_size=4):
411
407
if eof :
412
408
buff = buff [:n_read ]
413
409
414
- buffs .append (buff )
415
-
416
- # Make sure we've read enough to find a streamline delimiter.
417
- if fiber_marker not in buff :
418
- # If we've read the whole file, then fail.
419
- if eof :
420
- # Could have minimal buffering, and have read only the
421
- # EOF delimiter
422
- buffs = [bytearray ().join (buffs )]
423
- if not buffs [0 ] == eof_marker :
424
- raise DataError (
425
- "Cannot find a streamline delimiter. This file"
426
- " might be corrupted." )
427
- else :
428
- # Otherwise read a bit more.
429
- continue
430
-
431
- all_parts = bytearray ().join (buffs ).split (fiber_marker )
432
- point_parts , buffs = all_parts [:- 1 ], all_parts [- 1 :]
433
- point_parts = [p for p in point_parts if p != b'' ]
434
-
435
- for point_part in point_parts :
436
- # Read floats.
437
- pts = np .frombuffer (point_part , dtype = dtype )
438
- # Convert data to little-endian if needed.
439
- yield pts .astype ('<f4' , copy = False ).reshape ([- 1 , 3 ])
440
-
441
- n_streams += len (point_parts )
442
-
443
- if not buffs [- 1 ] == eof_marker :
444
- raise DataError ("Expecting end-of-file marker 'inf inf inf'" )
410
+ raw_values = np .frombuffer (buff , dtype = dtype )
411
+
412
+ # Convert raw_values into a list of little-endian triples (for x,y,z coord)
413
+ coords = raw_values .astype ('<f4' , copy = False ).reshape ((- 1 , 3 ))
414
+
415
+ # Find stream delimiter locations (all NaNs)
416
+ delims = np .where (np .isnan (coords ).all (axis = 1 ))[0 ]
417
+
418
+ # Recover leftovers, which can't have delimiters in them
419
+ if leftover .size :
420
+ delims += leftover .shape [0 ]
421
+ coords = np .vstack ((leftover , coords ))
422
+
423
+ begin = 0
424
+ for delim in delims :
425
+ pts = coords [begin :delim ]
426
+ if pts .size :
427
+ yield pts
428
+ n_streams += 1
429
+ begin = delim + 1
430
+
431
+ # The rest becomes the new leftover.
432
+ leftover = coords [begin :]
433
+
434
+ if not (leftover .shape == (1 , 3 ) and np .isinf (leftover ).all ()):
435
+ if n_streams == 0 :
436
+ msg = "Cannot find a streamline delimiter. This file might be corrupted."
437
+ else :
438
+ msg = "Expecting end-of-file marker 'inf inf inf'"
439
+ raise DataError (msg )
445
440
446
441
# In case the 'count' field was not provided.
447
442
header [Field .NB_STREAMLINES ] = n_streams
0 commit comments