def rawToNifti(infile, sizefile=None, outfile=None, dimorder=None, diskorder='F', dtype=None, split4=False): """Converts a raw file to a NIfTI file. Arguments: infile: Filename of a raw file. sizefile: Filename of a size_info config file. If None, attempts to find this file in the same directory as infile. outfile: Filename (including .nii) of the NIfTI file to generate. If None, it will be generated from infile. dimorder: Four-character string that is a permutation of "XYZI", indicating the dimension order of the image in "infile". The purpose of this argument is to rearrange the order of the dimensions in the infile to match the NIfTI canonical order of (X, Y, Z, I), where I is the dimension along which multiple acquisitions are concatenated. The default value, None, is equivalent to "XYZI". Note that this argument will be overridden if the size_info file contains a "dimension_order" value. diskorder: A string, 'F' or 'C', representing the order in which the data values are stored in the raw file. dtype: The numpy dtype for the infile. If None, it is inferred from infile's extension. split4: If True, output numbered 3-D images from 4-D input. """ (raw, cfg) = readRawWithSizeInfo(infile, sizefile=sizefile, dtype=dtype, dimorder=dimorder, diskorder=diskorder, memorder='C') vox_sz = cfg['voxel_size_(mm)'] # Rearrange dimensions. try: dimorder = cfg['dimension_order'] except KeyError: if dimorder is None: dimorder = _miraw_helpers.DIM_DEFAULT_ORDER if not _miraw_helpers.isValidDimorder(dimorder): raise ValueError('"%s" is not a valid dimorder argument.'%repr(dimorder)) raw_transp = raw.transpose(_miraw_helpers.dimorderToReverseDimmap(dimorder)) if split4 and len(raw_transp.shape) == 4: raw_stack = [raw_transp[:,:,:,i] for i in range(raw_transp.shape[3])] else: raw_stack = [raw_transp] i = 0 for img in raw_stack: nii = nifti1.Nifti1Pair(img, np.diag(vox_sz + [0.0])) nii.get_header().set_xyzt_units('mm') outfname = outfile if outfname is None: outfname = os.path.splitext(infile)[0] + '.nii' if split4: outfname = os.path.splitext(outfname)[0] + ('_%03i.nii' % i) i += 1 nifti1.save(nii, outfname)
def undoDimOrderOnList(L, dimorder): """Permutes the values in L to restore them to a default dimorder. Arguments: L: A list of four values, corresponding (in order) to the dimensions of some dataset. dimorder: Four-character string that is a permutation of "XYZI", indicating the current dimension order of the dataset. Returns a permuted version of L, with values corresponding (respectively) to the X, Y, Z, and I. """ return [L[i] for i in _miraw_helpers.dimorderToReverseDimmap(dimorder)]
def undoDimOrder(img, dimorder): """Permutes the data dimensions of img, which currently has the given dimension order, to match the default "XYZI" dimension order. Arguments: img: numpy ndarray with four dimensions. dimorder: Four-character string that is a permutation of "XYZI", indicating the current dimension order of img. Returns new_img: new_img: numpy ndarray with four dimensions. The values in new_img will be rearranged so that the dimension order is XYZI. """ return img.transpose(_miraw_helpers.dimorderToReverseDimmap(dimorder))
def saveSizeInfo(f, img, vox_sz=(1,1,1), dimorder=None, size_cfg={}, infer_name=False): """Writes a size_info metadata file to disk for a given array. A size_info file stores image (array) dimensions for raw images, as well as voxel size and cropping information (indicating that the array is cropped from a larger volume). Note that size_info is designed for 3-D or 4-D arrays only, and stores the extents of the first three dimensions separately from that of the fourth. Arguments: f: An open file handle or a filename for the destination file. img: A numpy.ndarray. vox_sz: Optional array-like object with 2 or 3 entries. dimorder: Four-character string that is a permutation of "XYZI", indicating the dimension order of the image "img". The purpose of this argument is to map from the dimension extents represented in img.shape to the extents stored in the size_info file, which are always stored in a canonical "XYZI" order. Namely, if we create a 4-tuple "dimmap" by converting each character X->0, Y->1, Z->2, I->3, then sz[dimmap[i]] = img.shape[i] for i from 0 to 3, where sz is the volume size, in (X,Y,Z,I) order, that will be stored in the size_info. The default value, None, is equivalent to "XYZI". size_cfg: Optional dictionary of other config key-value pairs. The data stored in this dictionary override all values computed by or passed into this function, even if they're inconsistent with the size of the image. Be careful! This includes the "dimension_order" value, which overrides the dimorder argument above. infer_name: Optional boolean. If True, and f is a filename, then the file actually written will be in the same directory as f (or in f if f is a path ending with a slash), and named "size_info". If f is not a string, this option has no effect. """ # Deal with filenames and open a file for writing, if necessary. if isinstance(f, str): if infer_name: f = os.path.join(os.path.dirname(f), 'size_info') fid = open(f, 'w') close_after = True else: fid = f close_after = False # Set up dimension mapping. shape = list(img.shape) + [1]*4 try: dimorder = size_cfg['dimension_order'] except KeyError: if dimorder is None: dimorder = _miraw_helpers.DIM_DEFAULT_ORDER if not _miraw_helpers.isValidDimorder(dimorder): raise ValueError('"%s" is not a valid dimorder argument.' % repr(dimorder)) shape = np.take(shape, _miraw_helpers.dimorderToReverseDimmap(dimorder), axis=0).tolist() # Extract metadata from the arguments. base_keys = ['voxel_size_(mm)', 'full_image_size_(voxels)', 'low_end_crop_(voxels)', 'cropped_image_size_(voxels)', 'num_dwis', 'dimension_order'] auto_cfg = { base_keys[0] : vox_sz, base_keys[1] : shape[:3], base_keys[2] : [0, 0, 0], base_keys[3] : shape[:3], base_keys[4] : shape[3], base_keys[5] : dimorder } # Overwrite metadata with what the user gave us. for (k,v) in size_cfg.items(): auto_cfg[k] = v # Now write the key-value pairs and we're done! def spaceSepStr(a): if isinstance(a, list) or isinstance(a, tuple): return ' '.join([str(x) for x in a]) return str(a) for k in base_keys: fid.write(k + ': ' + spaceSepStr(auto_cfg[k]) + '\n') del(auto_cfg[k]) for (k, v) in auto_cfg.items(): fid.write(k + ': ' + spaceSepStr(v) + '\n') if close_after: fid.close()