4343below). It's not clear what the licenses are for these files.
4444"""
4545
46+ from __future__ import annotations
47+
4648import warnings
4749from numbers import Integral
50+ from typing import TYPE_CHECKING
4851
4952import numpy as np
5053
5154from .arraywriters import make_array_writer
5255from .fileslice import canonical_slicers , predict_shape , slice2outax
53- from .spatialimages import SpatialHeader , SpatialImage
56+ from .spatialimages import Affine , AffT , SpatialHeader , SpatialImage
5457from .volumeutils import array_from_file , make_dt_codes , native_code , swapped_code
5558from .wrapstruct import WrapStruct
5659
60+ if TYPE_CHECKING :
61+ from collections .abc import Mapping
62+ from typing import Literal as L
63+
64+ import numpy .typing as npt
65+
66+ from .arrayproxy import ArrayLike
67+ from .filebasedimages import FileBasedHeader
68+ from .fileholders import FileMap
69+
5770BLOCK_SIZE = 512
5871
5972main_header_dtd = [
@@ -743,7 +756,7 @@ def __getitem__(self, sliceobj):
743756 return out_data
744757
745758
746- class EcatImage (SpatialImage ):
759+ class EcatImage (SpatialImage [ AffT ] ):
747760 """Class returns a list of Ecat images, with one image(hdr/data) per frame"""
748761
749762 header_class = EcatHeader
@@ -756,7 +769,16 @@ class EcatImage(SpatialImage):
756769
757770 ImageArrayProxy = EcatImageArrayProxy
758771
759- def __init__ (self , dataobj , affine , header , subheader , mlist , extra = None , file_map = None ):
772+ def __init__ (
773+ self ,
774+ dataobj : ArrayLike ,
775+ affine : AffT ,
776+ header : FileBasedHeader | Mapping | None ,
777+ subheader : EcatSubHeader ,
778+ mlist : npt .NDArray [np .integer ],
779+ extra : Mapping | None = None ,
780+ file_map : FileMap | None = None ,
781+ ) -> None :
760782 """Initialize Image
761783
762784 The image is a combination of
@@ -798,40 +820,38 @@ def __init__(self, dataobj, affine, header, subheader, mlist, extra=None, file_m
798820 >>> data4d.shape == (10, 10, 3, 1)
799821 True
800822 """
823+ super ().__init__ (
824+ dataobj = dataobj ,
825+ affine = affine ,
826+ header = header ,
827+ extra = extra ,
828+ file_map = file_map ,
829+ )
801830 self ._subheader = subheader
802831 self ._mlist = mlist
803- self ._dataobj = dataobj
804- if affine is not None :
805- # Check that affine is array-like 4,4. Maybe this is too strict at
806- # this abstract level, but so far I think all image formats we know
807- # do need 4,4.
808- affine = np .array (affine , dtype = np .float64 , copy = True )
809- if not affine .shape == (4 , 4 ):
810- raise ValueError ('Affine should be shape 4,4' )
811- self ._affine = affine
812- if extra is None :
813- extra = {}
814- self .extra = extra
815- self ._header = header
816- if file_map is None :
817- file_map = self .__class__ .make_file_map ()
818- self .file_map = file_map
819- self ._data_cache = None
820- self ._fdata_cache = None
832+
833+ # Override SpatialImage default, which attempts to set the
834+ # affine in the header.
835+ def update_header (self ) -> None :
836+ """Does nothing"""
821837
822838 @property
823- def affine (self ):
839+ def affine (self ) -> AffT :
824840 if not self ._subheader ._check_affines ():
825841 warnings .warn (
826842 'Affines different across frames, loading affine from FIRST frame' , UserWarning
827843 )
828844 return self ._affine
829845
830- def get_frame_affine (self , frame ) :
846+ def get_frame_affine (self , frame : int ) -> Affine :
831847 """returns 4X4 affine"""
832848 return self ._subheader .get_frame_affine (frame = frame )
833849
834- def get_frame (self , frame , orientation = None ):
850+ def get_frame (
851+ self ,
852+ frame : int ,
853+ orientation : L ['neurological' , 'radiological' ] | None = None ,
854+ ) -> np .ndarray :
835855 """
836856 Get full volume for a time frame
837857
@@ -847,16 +867,16 @@ def get_data_dtype(self, frame):
847867 return dt
848868
849869 @property
850- def shape (self ):
870+ def shape (self ) -> tuple [ int , int , int , int ] :
851871 x , y , z = self ._subheader .get_shape ()
852872 nframes = self ._subheader .get_nframes ()
853873 return (x , y , z , nframes )
854874
855- def get_mlist (self ):
875+ def get_mlist (self ) -> npt . NDArray [ np . integer ] :
856876 """get access to the mlist"""
857877 return self ._mlist
858878
859- def get_subheaders (self ):
879+ def get_subheaders (self ) -> EcatSubHeader :
860880 """get access to subheaders"""
861881 return self ._subheader
862882
0 commit comments