@@ -569,6 +569,21 @@ def __init__(self, file_like, header, mmap=True, scaling='dv'):
569
569
self ._slice_scaling = header .get_data_scaling (scaling )
570
570
self ._rec_shape = header .get_rec_shape ()
571
571
572
+ try :
573
+ # store additional slice & volume label information
574
+ self ._dim_4_labels = header .sorted_labels (
575
+ sorted_indices = self ._slice_indices ,
576
+ collapse_slices = True )
577
+ self ._dim_3_4_labels = None
578
+ except :
579
+ # if non-unique slice orientations or image angulations, need to
580
+ # also keep labels for the 3rd (slice) dimension
581
+ self ._dim_4_labels = None
582
+ self ._dim_3_4_labels = header .sorted_labels (
583
+ sorted_indices = self ._slice_indices ,
584
+ collapse_slices = False )
585
+
586
+
572
587
@property
573
588
def shape (self ):
574
589
return self ._shape
@@ -1114,6 +1129,75 @@ def get_sorted_slice_indices(self):
1114
1129
n_used = np .prod (self .get_data_shape ()[2 :])
1115
1130
return sort_order [:n_used ]
1116
1131
1132
+ def sorted_labels (self , sorted_indices = None , collapse_slices = True ):
1133
+ """ return a dictionary of lists of the varying values in
1134
+ ``self.image_defs``. This is useful for custom data sorting. only
1135
+ keys that have more than 1 unique value across the dataset will exist
1136
+ in the returned `sort_info` dictionary.
1137
+
1138
+ Parameters
1139
+ ----------
1140
+ sorted_indices : array, optional
1141
+ sorted slice indices as returned by
1142
+ ``self.get_sorted_slice_indices``.
1143
+ collapse_slices : bool, optional
1144
+ if True, only return indices corresponding to the first slice
1145
+
1146
+ Returns
1147
+ -------
1148
+ sort_info : dict
1149
+ Each key corresponds to a dynamically varying sequence dimension.
1150
+ The ordering of values corresponds to that in sorted_indices.
1151
+ """
1152
+
1153
+ # define which keys to store sorting info for
1154
+ dynamic_keys = ['slice number' ,
1155
+ 'cardiac phase number' ,
1156
+ 'echo number' ,
1157
+ 'label type' ,
1158
+ 'image_type_mr' ,
1159
+ 'dynamic scan number' ,
1160
+ 'slice orientation' ,
1161
+ 'image_display_orientation' , # ????
1162
+ 'image angulation' ,
1163
+ 'scanning sequence' ,
1164
+ 'gradient orientation number' ,
1165
+ 'diffusion b value number' ]
1166
+
1167
+ if sorted_indices is None :
1168
+ sorted_indices = self .get_sorted_slice_indices ()
1169
+
1170
+ if collapse_slices :
1171
+ dynamic_keys .remove ('slice number' )
1172
+
1173
+ non_unique_keys = []
1174
+ for key in dynamic_keys :
1175
+ if len (np .unique (self .image_defs [key ])) > 1 :
1176
+ non_unique_keys .append (key )
1177
+
1178
+ if collapse_slices :
1179
+ if 'slice orientation' in non_unique_keys :
1180
+ raise ValueError ("for non-unique slice orientation, need "
1181
+ "collapse_slice=False" )
1182
+ if 'image angulation' in non_unique_keys :
1183
+ raise ValueError ("for non-unique image angulation, need "
1184
+ "collapse_slice=False" )
1185
+ if 'image image_display_orientation' in non_unique_keys : # ???
1186
+ raise ValueError ("for non-unique display orientation, need "
1187
+ "collapse_slice=False" )
1188
+ sl1_indices = self .image_defs ['slice number' ][sorted_indices ] == 1
1189
+
1190
+ sort_info = {}
1191
+ for key in non_unique_keys :
1192
+ if collapse_slices :
1193
+ sort_info [key ] = list (
1194
+ self .image_defs [key ][sorted_indices ][sl1_indices ])
1195
+ else :
1196
+ sort_info [key ] = list (
1197
+ self .image_defs [key ][sorted_indices ])
1198
+
1199
+ return sort_info
1200
+
1117
1201
1118
1202
class PARRECImage (SpatialImage ):
1119
1203
"""PAR/REC image"""
0 commit comments