13
13
* a *main header*;
14
14
* at least one *matrix list* (mlist);
15
15
16
- ECAT thinks of memory locations in terms of *records *. One record is 512
17
- bytes. Thus record 1 is at 0 bytes, record 2 at 512 bytes, and so on.
16
+ ECAT thinks of memory locations in terms of *blocks *. One block is 512
17
+ bytes. Thus block 1 starts at 0 bytes, block 2 at 512 bytes, and so on.
18
18
19
19
The matrix list is an array with one row per frame in the data.
20
20
21
21
Columns in the matrix list are:
22
22
23
23
* 0 - Matrix identifier (frame number)
24
- * 1 - matrix data start record number (subheader stored here )
25
- * 2 - Last record number of matrix data block.
24
+ * 1 - matrix data start block number (subheader followed by image data )
25
+ * 2 - Last block number of matrix (image) data
26
26
* 3 - Matrix status:
27
27
* 1 - exists - rw
28
28
* 2 - exists - ro
29
29
* 3 - matrix deleted
30
30
31
31
There is one sub-header for each image frame (or matrix in the terminology
32
- above).
32
+ above). A sub-header can also be called an *image header*. The sub-header is
33
+ one block (512 bytes), and the frame (image) data follows.
33
34
34
- A sub-header can also be called an *image header*.
35
-
36
- There is very little documentation of this format, and many of the comments in
37
- this code come from a combination of trial and error and wild speculation.
35
+ There is very little documentation of the ECAT format, and many of the comments
36
+ in this code come from a combination of trial and error and wild speculation.
38
37
39
38
XMedcon can read and write ECAT 6 format, and read ECAT 7 format: see
40
39
http://xmedcon.sourceforge.net and the ECAT files in the source of XMedCon,
55
54
from .wrapstruct import WrapStruct
56
55
from .fileslice import canonical_slicers , predict_shape , slice2outax
57
56
58
- RECORD_BYTES = 512
57
+ BLOCK_SIZE = 512
59
58
60
- MAINHDRSZ = 502
61
59
main_header_dtd = [
62
60
('magic_number' , '14S' ),
63
61
('original_filename' , '32S' ),
@@ -332,57 +330,56 @@ def read_mlist(fileobj, endianness):
332
330
mlist : (nframes, 4) ndarray
333
331
matrix list is an array with ``nframes`` rows and columns:
334
332
335
- * 0 - Matrix identifier.
336
- * 1 - subheader record number
337
- * 2 - Last record number of matrix data block.
333
+ * 0 - Matrix identifier (frame number)
334
+ * 1 - matrix data start block number (subheader followed by image data)
335
+ * 2 - Last block number of matrix (image) data
338
336
* 3 - Matrix status:
339
-
340
- * 1 - exists - rw
341
- * 2 - exists - ro
342
- * 3 - matrix deleted
337
+ * 1 - exists - rw
338
+ * 2 - exists - ro
339
+ * 3 - matrix deleted
343
340
344
341
Notes
345
342
-----
346
- A 'record' or ' block' is 512 bytes.
343
+ A block is 512 bytes.
347
344
348
- ``record_no `` in the code below is 1-based. Record 1 is the main header,
349
- and the mlist records start at record number 2.
345
+ ``block_no `` in the code below is 1-based. block 1 is the main header,
346
+ and the mlist blocks start at block number 2.
350
347
351
- The 512 bytes in an mlist record represents 32 rows of the int32 (nframes,
348
+ The 512 bytes in an mlist block contain 32 rows of the int32 (nframes,
352
349
4) mlist matrix.
353
350
354
351
The first row of these 32 looks like a special row. The 4 values appear
355
352
to be (respectively):
356
353
357
354
* not sure - maybe negative number of mlist rows (out of 31) that are
358
- blank and not used in this record . Called `nfree` but unused in CTI
355
+ blank and not used in this block . Called `nfree` but unused in CTI
359
356
code;
360
- * record_no - of next set of mlist entries or 2 if no more entries. We also
357
+ * block_no - of next set of mlist entries or 2 if no more entries. We also
361
358
allow 1 or 0 to signal no more entries;
362
- * <no idea>. Called `prvblk` in CTI code, so maybe previous record no;
363
- * n_rows - number of mlist rows in this record (between ?0 and 31) (called
359
+ * <no idea>. Called `prvblk` in CTI code, so maybe previous block no;
360
+ * n_rows - number of mlist rows in this block (between ?0 and 31) (called
364
361
`nused` in CTI code).
365
362
"""
366
363
dt = np .dtype (np .int32 ) # should this be uint32 given mlist dtype?
367
364
if not endianness is native_code :
368
365
dt = dt .newbyteorder (endianness )
369
366
mlists = []
370
367
mlist_index = 0
371
- mlist_record_no = 2 # 1-based indexing, record with first mlist
368
+ mlist_block_no = 2 # 1-based indexing, block with first mlist
372
369
while True :
373
- # Read record containing mlist entries
374
- fileobj .seek ((mlist_record_no - 1 ) * RECORD_BYTES ) # fix 1-based indexing
370
+ # Read block containing mlist entries
371
+ fileobj .seek ((mlist_block_no - 1 ) * BLOCK_SIZE ) # fix 1-based indexing
375
372
dat = fileobj .read (128 * 32 ) # isn't this too long? Should be 512?
376
373
rows = np .ndarray (shape = (32 , 4 ), dtype = dt , buffer = dat )
377
374
# First row special, points to next mlist entries if present
378
- n_unused , mlist_record_no , _ , n_rows = rows [0 ]
375
+ n_unused , mlist_block_no , _ , n_rows = rows [0 ]
379
376
if not (n_unused + n_rows ) == 31 : # Some error condition here?
380
377
mlist = []
381
378
return mlist
382
379
# Use all but first housekeeping row
383
380
mlists .append (rows [1 :n_rows + 1 ])
384
381
mlist_index += n_rows
385
- if mlist_record_no <= 2 : # should record_no in (1, 2) be an error?
382
+ if mlist_block_no <= 2 : # should block_no in (1, 2) be an error?
386
383
break
387
384
# Code in ``get_frame_order`` seems to imply ids can be < 0; is that
388
385
# true? Should the dtype be uint32 or int32?
@@ -481,8 +478,8 @@ def read_subheaders(fileobj, mlist, endianness):
481
478
mlist : (nframes, 4) ndarray
482
479
Columns are:
483
480
* 0 - Matrix identifier.
484
- * 1 - subheader record number
485
- * 2 - Last record number of matrix data block.
481
+ * 1 - subheader block number
482
+ * 2 - Last block number of matrix data block.
486
483
* 3 - Matrix status:
487
484
endianness : {'<', '>'}
488
485
little / big endian code
@@ -496,12 +493,12 @@ def read_subheaders(fileobj, mlist, endianness):
496
493
dt = subhdr_dtype
497
494
if not endianness is native_code :
498
495
dt = dt .newbyteorder (endianness )
499
- for mat_id , sh_recno , sh_last_recno , mat_stat in mlist :
500
- if sh_recno == 0 :
496
+ for mat_id , sh_blkno , sh_last_blkno , mat_stat in mlist :
497
+ if sh_blkno == 0 :
501
498
break
502
- offset = (sh_recno - 1 ) * 512
499
+ offset = (sh_blkno - 1 ) * BLOCK_SIZE
503
500
fileobj .seek (offset )
504
- tmpdat = fileobj .read (512 )
501
+ tmpdat = fileobj .read (BLOCK_SIZE )
505
502
sh = np .ndarray (shape = (), dtype = dt , buffer = tmpdat )
506
503
subheaders .append (sh )
507
504
return subheaders
@@ -520,14 +517,14 @@ def __init__(self,fileobj, hdr):
520
517
Columns are:
521
518
522
519
* 0 - Matrix identifier.
523
- * 1 - subheader record number
524
- * 2 - Last record number of matrix data block.
520
+ * 1 - subheader block number
521
+ * 2 - Last block number of matrix data block.
525
522
* 3 - Matrix status:
526
523
* 1 - exists - rw
527
524
* 2 - exists - ro
528
525
* 3 - matrix deleted
529
526
530
- A record above is 512 bytes in the image data file
527
+ A block above is 512 bytes in the image data file
531
528
532
529
Parameters
533
530
-----------
@@ -631,7 +628,7 @@ def _get_data_dtype(self, frame):
631
628
632
629
def _get_frame_offset (self , frame = 0 ):
633
630
mlist = self ._mlist ._mlist
634
- offset = (mlist [frame ][1 ]) * 512
631
+ offset = (mlist [frame ][1 ]) * BLOCK_SIZE
635
632
return int (offset )
636
633
637
634
def _get_oriented_data (self , raw_data , orientation = None ):
0 commit comments