def to_files(self, files=None): ''' Write image to files passed, or self._files ''' if files is None: files = self._files if files is None: raise ValueError('Need files to write data') data = self.get_data() # Adapt header to possible two<->one file difference is_pair = files['header'] != files['image'] hdr = self.get_header().for_file_pair(is_pair) slope, inter, mn, mx = adapt_header(hdr, data) hdrf = allopen(files['header'], 'wb') hdr.write_to(hdrf) if is_pair: imgf = allopen(files['image'], 'wb') else: # single file for header and image imgf = hdrf # streams like bz2 do not allow seeks, even forward. We # check where to go, and write zeros up until the data part # of the file offset = hdr.get_data_offset() diff = offset-hdrf.tell() if diff > 0: hdrf.write('\x00' * diff) write_data(hdr, data, imgf, inter, slope, mn, mx) self._header = hdr self._files = files
def from_filename(klass, filename): ret = super(Spm99AnalyzeImage, klass).from_filename(filename) import scipy.io as sio matf = ret._files['mat'] try: matf = allopen(matf) except IOError: return ret mats = sio.loadmat(matf) if 'mat' in mats: # this overrides a 'M', and includes any flip mat = mats['mat'] if mat.ndim > 2: warnings.warn('More than one affine in "mat" matrix, ' 'using first') mat = mat[:,:,0] ret._affine = mat return ret elif 'M' in mats: # the 'M' matrix does not include flips hdr = ret._header if hdr.default_x_flip: ret._affine = np.dot(np.diag([-1,1,1,1]), mats['M']) else: ret._affine = mats['M'] else: raise ValueError('mat file found but no "mat" or "M" in it') return ret
def from_files(klass, files): fname = files['image'] header = klass._header_maker.from_fileobj(allopen(fname)) affine = header.get_best_affine() ret = klass(None, affine, header) ret._files = files return ret
def get_unscaled_data(self): """ Return image data without image scaling applied Summary: please use the ``get_data`` method instead of this method unless you are sure what you are doing, and that you will only be using image formats for which this method exists and returns sensible results. Use this method with care; the modified Analyze-type formats such as SPM formats, and nifti1, specify that the image data array, as they are expecting to return it, is given by the raw data on disk, multiplied by a scalefactor and maybe with the addition of a constant. This method returns the data on the disk, without these format-specific scalings applied. Please use this method only if you absolutely need the unscaled data, and the magnitude of the data, as given by the scalefactor, is not relevant to your application. The Analyze-type formats have a single scalefactor +/- offset per image on disk. If you do not care about the absolute values, and will be removing the mean from the data, then the unscaled values will have preserved intensity ratios compared to the mean-centered scaled data. However, this is not necessarily true of other formats with more complicated scaling - such as MINC. Note that - unlike the scaled ``get_data`` method, we do not cache the array, to minimize the memory taken by the object. """ if not self._files: return None try: fname = self._files['image'] except KeyError: return None return read_unscaled_data(self._header, allopen(fname))
def get_data(self): ''' Lazy load of data ''' if not self._data is None: return self._data if not self._files: return None try: fname = self._files['image'] except KeyError: return None self._data = read_data(self._header, allopen(fname)) return self._data
def to_files(self, files=None): super(Spm99AnalyzeImage, self).to_files(files) if self._affine is None: return import scipy.io as sio matfname = self._files['mat'] mfobj = allopen(matfname, 'wb') mat = self._affine hdr = self._header if hdr.default_x_flip: M = np.dot(np.diag([-1,1,1,1]), mat) else: M = mat # use matlab 4 format to allow gzipped write without error sio.savemat(mfobj, {'M': M, 'mat': mat}, format='4') mfobj.close()
def load(filename, *args, **kwargs): ''' Load file given filename, guessing at file type Parameters ---------- filename : string or file-like specification of filename or file to load *args **kwargs arguments to pass to image load function Returns ------- img : ``SpatialImage`` Image of guessed type ''' # Try and guess file type from filename if isinstance(filename, basestring): fname = filename for ending in ('.gz', '.bz2'): if filename.endswith(ending): fname = fname[:-len(ending)] break if fname.endswith('.nii'): return nifti1.load(filename, *args, **kwargs) if fname.endswith('.mnc'): return minc.load(filename, *args, **kwargs) # Not a string, or not recognized as nii or mnc try: files = nifti1.Nifti1Image.filespec_to_files(filename) except ValueError: raise RuntimeError('Cannot work out file type of "%s"' % filename) hdr = nifti1.Nifti1Header.from_fileobj( vu.allopen(files['header']), check=False) magic = hdr['magic'] if magic in ('ni1', 'n+1'): return nifti1.load(filename, *args, **kwargs) return spm2.load(filename, *args, **kwargs)
def get_unscaled_img(fname): ''' Function to get image, data without scalefactor applied If the image is of Analyze type, and is integer format, and has single scalefactor that is usually applied, then read the raw integer data from disk, rather than using the higher-level get_data method, that would apply the scalefactor. We do this because there seemed to be images for which the integer binning in the raw file data was needed for the histogram-like mask calculation in ``compute_mask_files``. By loading the image in this function we can guarantee that the image as loaded from disk is the source of the current image data. Parameters ---------- fname : str filename of image Returns ------- img : imageformats Image object arr : ndarray ''' img = load(fname) if isinstance(img, AnalyzeImage): dt = img.get_data_dtype() if dt.kind in ('i', 'u'): from nipy.io.imageformats.header_ufuncs import read_unscaled_data from nipy.io.imageformats.volumeutils import allopen # get where the image data is, given input filename ft = img.filespec_to_files(fname) hdr = img.get_header() # read unscaled data from disk return img, read_unscaled_data(hdr, allopen(ft['image'])) return img, img.get_data()