80
80
can be loaded with and without a default flip, so the saved zoom will not
81
81
constrain the affine.
82
82
'''
83
+ import sys
84
+
83
85
import numpy as np
84
86
85
- from .volumeutils import (native_code , swapped_code , make_dt_codes ,
86
- calculate_scale , allopen , shape_zoom_affine ,
87
- array_to_file , array_from_file , can_cast )
87
+ from .volumeutils import (native_code , swapped_code , make_dt_codes , allopen ,
88
+ shape_zoom_affine , array_from_file , seek_tell )
89
+ from . arraywriters import make_array_writer , get_slope_inter , WriterError
88
90
from .wrapstruct import WrapStruct
89
91
from .spatialimages import (HeaderDataError , HeaderTypeError ,
90
92
SpatialImage )
@@ -530,23 +532,23 @@ def data_to_fileobj(self, data, fileobj):
530
532
>>> data.astype(np.float64).tostring('F') == str_io.getvalue()
531
533
True
532
534
'''
533
- data = np .asarray (data )
534
- slope , inter , mn , mx = self .scaling_from_data (data )
535
+ data = np .asanyarray (data )
535
536
shape = self .get_data_shape ()
536
537
if data .shape != shape :
537
538
raise HeaderDataError ('Data should be shape (%s)' %
538
539
', ' .join (str (s ) for s in shape ))
539
- offset = self .get_data_offset ()
540
540
out_dtype = self .get_data_dtype ()
541
- array_to_file (data ,
542
- fileobj ,
543
- out_dtype ,
544
- offset ,
545
- inter ,
546
- slope ,
547
- mn ,
548
- mx )
549
- self .set_slope_inter (slope , inter )
541
+ try :
542
+ arr_writer = make_array_writer (data ,
543
+ out_dtype ,
544
+ self .has_data_intercept ,
545
+ self .has_data_slope )
546
+ except WriterError :
547
+ msg = sys .exc_info ()[1 ] # python 2 / 3 compatibility
548
+ raise HeaderTypeError (msg )
549
+ seek_tell (fileobj , self .get_data_offset ())
550
+ arr_writer .to_fileobj (fileobj )
551
+ self .set_slope_inter (* get_slope_inter (arr_writer ))
550
552
551
553
def get_data_dtype (self ):
552
554
''' Get numpy dtype for data
@@ -756,45 +758,6 @@ def set_slope_inter(self, slope, inter=None):
756
758
raise HeaderTypeError ('Cannot set slope != 1 or intercept != 0 '
757
759
'for Analyze headers' )
758
760
759
- def scaling_from_data (self , data ):
760
- ''' Calculate slope, intercept, min, max from data given header
761
-
762
- Check that the data can be sensibly adapted to this header data
763
- dtype. If the header type does support useful scaling to allow
764
- this, raise a HeaderTypeError.
765
-
766
- Parameters
767
- ----------
768
- data : array-like
769
- array of data for which to calculate scaling etc
770
-
771
- Returns
772
- -------
773
- divslope : None or scalar
774
- divisor for data, after subtracting intercept. If None, then
775
- there are no valid data
776
- intercept : None or scalar
777
- number to subtract from data before writing.
778
- mn : None or scalar
779
- data minimum to write, None means use data minimum
780
- mx : None or scalar
781
- data maximum to write, None means use data maximum
782
- '''
783
- data = np .asarray (data )
784
- out_dtype = self .get_data_dtype ()
785
- if not can_cast (data .dtype .type ,
786
- out_dtype .type ,
787
- self .has_data_intercept ,
788
- self .has_data_slope ):
789
- raise HeaderTypeError ('Cannot cast data to header dtype without'
790
- ' large potential loss in precision' )
791
- if not self .has_data_slope :
792
- return 1.0 , 0.0 , None , None
793
- return calculate_scale (
794
- data ,
795
- out_dtype ,
796
- self .has_data_intercept )
797
-
798
761
@classmethod
799
762
def _get_checks (klass ):
800
763
''' Return sequence of check functions for this class '''
@@ -967,41 +930,6 @@ def _write_header(self, header_file, header, slope, inter):
967
930
header .set_slope_inter (slope , inter )
968
931
header .write_to (header_file )
969
932
970
- def _write_image (self , image_file , data , header , slope , inter , mn , mx ):
971
- ''' Utility routine to write image
972
-
973
- Parameters
974
- ----------
975
- image_file : file-like
976
- file-like object implementing ``seek`` or ``tell``, and
977
- ``write``
978
- data : array-like
979
- array to write
980
- header : analyze-type header object
981
- header
982
- slope : None or float
983
- scale factor for `data` so that written data is ``data /
984
- slope + inter``. None means no valid data
985
- inter : float
986
- intercept (see above)
987
- mn : None or float
988
- minimum to scale data to. None means use data minimum
989
- max : None or float
990
- maximum to scale data to. None means use data maximum
991
-
992
- Returns
993
- -------
994
- None
995
- '''
996
- shape = header .get_data_shape ()
997
- if data .shape != shape :
998
- raise HeaderDataError ('Data should be shape (%s)' %
999
- ', ' .join (str (s ) for s in shape ))
1000
- offset = header .get_data_offset ()
1001
- out_dtype = header .get_data_dtype ()
1002
- array_to_file (data , image_file , out_dtype , offset ,
1003
- inter , slope , mn , mx )
1004
-
1005
933
def to_file_map (self , file_map = None ):
1006
934
''' Write image to `file_map` or contained ``self.file_map``
1007
935
@@ -1016,7 +944,11 @@ def to_file_map(self, file_map=None):
1016
944
data = self .get_data ()
1017
945
self .update_header ()
1018
946
hdr = self .get_header ()
1019
- slope , inter , mn , mx = hdr .scaling_from_data (data )
947
+ out_dtype = self .get_data_dtype ()
948
+ arr_writer = make_array_writer (data ,
949
+ out_dtype ,
950
+ hdr .has_data_intercept ,
951
+ hdr .has_data_slope )
1020
952
hdr_fh , img_fh = self ._get_fileholders (file_map )
1021
953
# Check if hdr and img refer to same file; this can happen with odd
1022
954
# analyze images but most often this is because it's a single nifti file
@@ -1026,8 +958,15 @@ def to_file_map(self, file_map=None):
1026
958
imgf = hdrf
1027
959
else :
1028
960
imgf = img_fh .get_prepare_fileobj (mode = 'wb' )
961
+ slope , inter = get_slope_inter (arr_writer )
1029
962
self ._write_header (hdrf , hdr , slope , inter )
1030
- self ._write_image (imgf , data , hdr , slope , inter , mn , mx )
963
+ # Write image
964
+ shape = hdr .get_data_shape ()
965
+ if data .shape != shape :
966
+ raise HeaderDataError ('Data should be shape (%s)' %
967
+ ', ' .join (str (s ) for s in shape ))
968
+ seek_tell (imgf , hdr .get_data_offset ())
969
+ arr_writer .to_fileobj (imgf )
1031
970
if hdr_fh .fileobj is None : # was filename
1032
971
hdrf .close ()
1033
972
if not hdr_img_same :
0 commit comments