NPL
Neurological Programs and Libraries
mrimage.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2014 Micah C Chambers (micahc.vt@gmail.com)
3  *
4  * NPL is free software: you can redistribute it and/or modify it under the
5  * terms of the BSD 2-Clause License available in LICENSE or at
6  * http://opensource.org/licenses/BSD-2-Clause
7  *
8  * @file mrimage.h
9  * @brief This file contains the definition for MRImage and its derived types.
10  * The derived types are templated over dimensionality and pixel type.
11  ******************************************************************************/
12 
13 #ifndef NDIMAGE_H
14 #define NDIMAGE_H
15 
16 #include "npltypes.h"
17 #include "ndarray.h"
18 #include "nifti.h"
19 
20 #include "zlib.h"
21 
22 #include <string>
23 #include <iomanip>
24 #include <cassert>
25 #include <memory>
26 #include <map>
27 
28 namespace npl {
29 
30 using std::vector;
31 
34 
35 enum CoordinateT {NOFORM=0, QFORM=1, SFORM=2};
36 
38 
39 class MRImage;
40 
41 /*****************************************************************************
42  * Helper Function to Create MRImage's
43  ****************************************************************************/
59 ptr<MRImage> createMRImage(size_t ndim, const size_t* size, PixelT type);
60 
71 ptr<MRImage> createMRImage(const std::vector<size_t>& dim, PixelT type);
72 
85 ptr<MRImage> createMRImage(size_t ndim, const size_t* size, PixelT type,
86  void* ptr, std::function<void(void*)> deleter);
87 
100 ptr<MRImage> createMRImage(const std::vector<size_t>& dim, PixelT type,
101  void* ptr, std::function<void(void*)> deleter);
102 
111 std::ostream& operator<<(std::ostream &out, const MRImage& img);
112 
115 /******************************************************************************
116  * Classes.
117  ******************************************************************************/
118 
123 class MRImage : public virtual NDArray
124 {
125 public:
129 
130  /********************************************
131  * Orientation Functions/Variables
132  *******************************************/
133 
138  void orientDefault();
139 
145  bool isOriented() { return m_coordinate != NOFORM; };
146 
160  void setOrient(const VectorXd& neworig, const VectorXd& newspace,
161  const MatrixXd& newdir, bool reinit = true,
162  CoordinateT coord = QFORM);
163 
174  const double& direction(int64_t row, int64_t col) const;
175 
186  const double& invdirection(int64_t row, int64_t col) const;
187 
195  const MatrixXd& getDirection() const;
196 
211  void setDirection(const MatrixXd& newdir, bool reinit, CoordinateT coord = QFORM);
212 
221  double& origin(int64_t row);
222 
231  const double& origin(int64_t row) const;
232 
239  const VectorXd& getOrigin() const;
240 
252  void setOrigin(const VectorXd& neworigin, bool reinit);
253 
262  double& spacing(int64_t row);
263 
272  const double& spacing(int64_t row) const;
273 
280  const VectorXd& getSpacing() const;
281 
292  void setSpacing(const VectorXd& newspacing, bool reinit);
293 
294  /**********************************
295  * Orientation Transform Functions
296  *********************************/
297  /*
298  * @brief Converts an index in pixel space to RAS, physical/time coordinates.
299  * If len < dimensions, additional dimensions are assumed to be 0. If len >
300  * dimensions then additional values are ignored, and only the first DIM
301  * values will be transformed and written to ras.
302  *
303  * @param len Length of xyz/ras arrays.
304  * @param xyz Array in xyz... coordinates (maybe as long as you want).
305  * @param ras Corresponding coordinate
306  *
307  * @return 0
308  */
309  virtual int indexToPoint(size_t len, const int64_t* xyz, double* ras) const=0;
310 
323  virtual int indexToPoint(size_t len, const double* xyz, double* ras) const=0;
324 
337  virtual int pointToIndex(size_t len, const double* ras, double* xyz) const=0;
338 
351  virtual int pointToIndex(size_t len, const double* ras, int64_t* index) const=0;
352 
366  virtual int orientVector(size_t len, const double* xyz, double* ras) const=0;
367 
382  virtual int disOrientVector(size_t len, const double* ras, double* xyz) const=0;
383 
395  virtual bool pointInsideFOV(size_t len, const double* ras) const=0;
396 
409  virtual bool indexInsideFOV(size_t len, const double* xyz) const=0;
410 
422  virtual bool indexInsideFOV(size_t len, const int64_t* xyz) const=0;
423 
441  virtual bool matchingOrient(ptr<const MRImage> other, bool checkdim,
442  bool checksize, double tol = 0.01) const;
443 
456  virtual bool isIsotropic(bool only3d = true, double tol = 0.01) const;
457 
458  /********************************************
459  * Output Functions
460  *******************************************/
461 
470  virtual int write(std::string filename, double version = 1) const = 0;
471 
472  /********************************************
473  * Copying/Pointer Functions
474  *******************************************/
475 
482  return dPtrCast<MRImage>(shared_from_this());
483  };
484 
491  return dPtrCast<const MRImage>(shared_from_this());
492  };
493 
494 
501  virtual ptr<MRImage> cloneImage() const = 0;
502 
503 
509  virtual ptr<NDArray> copy() const = 0;
510 
516  virtual ptr<NDArray> createAnother() const = 0;
517 
529  virtual ptr<NDArray> createAnother(size_t newdims, const size_t* newsize,
530  PixelT newtype) const = 0;
531 
541  virtual ptr<NDArray> createAnother(PixelT newtype) const = 0;
542 
555  virtual ptr<NDArray> createAnother(size_t newdims,
556  const size_t* newsize) const = 0;
557 
558 
570  virtual ptr<NDArray> copyCast(size_t newdims, const size_t* newsize,
571  PixelT newtype) const = 0;
572 
582  virtual ptr<NDArray> copyCast(PixelT newtype) const = 0;
583 
595  virtual ptr<NDArray> copyCast(size_t newdims,
596  const size_t* newsize) const = 0;
597 
609  virtual ptr<NDArray> extractCast(size_t len, const int64_t* index,
610  const size_t* size) const = 0;
611 
622  virtual ptr<NDArray> extractCast(size_t len, const size_t* size) const = 0;
623 
636  virtual ptr<NDArray> extractCast(size_t len,
637  const int64_t* index, const size_t* size, PixelT newtype) const = 0;
638 
650  virtual ptr<NDArray> extractCast(size_t len, const size_t* size,
651  PixelT newtype) const = 0;
652 
653 
661  virtual void copyMetadata(ptr<const MRImage> src);
662 
663 
664  // virtual int unary(double(*func)(double,double)) const = 0;
665  // virtual int binOp(const MRImage* right, double(*func)(double,double), bool elevR) const = 0;
666 
667  /**********************************************************************
668  * Medical Image Specific
669  *********************************************************************/
670 
671  // < 0 indicate unset variables
676 
677  /*
678  * nifti specific stuff, eventually these should be moved to a nifti
679  * image subclass
680  */
681 
682  void updateSliceTiming(double duration, int start, int end, SliceOrderT order);
683 
684  // raw values for slice data, < 0 indicate unset
688 
689  // SEQ, RSEQ, ALT, RALT, ALT_SHFT, RALT_SHFT
690  // SEQ (sequential): slice_start .. slice_end
691  // RSEQ (reverse seq): slice_end .. slice_start
692  // ALT (alternated): slice_start, slice_start+2, .. slice_end|slice_end-1,
693  // slice_start+1 .. slice_end|slice_end-1
694  // RALT (reverse alt): slice_end, slice_end-2, .. slice_start|slice_start+1,
695  // slice_end-1 .. slice_start|slice_start+1
696  // ALT_SHFT (siemens alt):slice_start+1, slice_start+3, .. slice_end|slice_end-1,
697  // slice_start .. slice_end|slice_end-1
698  // RALT (reverse alt): slice_end-1, slice_end-3, .. slice_start|slice_start+1,
699  // slice_end-2 .. slice_start|slice_start+1
701 
702  // each slice is given its relative time, with 0 as the first
703  std::map<int64_t,double> m_slice_timing;
704 
705 protected:
706  virtual int writeNifti1Image(gzFile file) const = 0;
707  virtual int writeNifti2Image(gzFile file) const = 0;
708 
714  MatrixXd m_direction;
715 
719  MatrixXd m_inv_direction;
720 
726  VectorXd m_spacing;
727 
733  VectorXd m_origin;
734 
735  friend ptr<MRImage> readNiftiImage(gzFile file, bool verbose);
736 };
737 
747 template <size_t D, typename T>
748 class MRImageStore : public virtual NDArrayStore<D,T>, public virtual MRImage
749 {
750 
751 public:
752 
753  /*****************************************
754  * Constructors
755  ****************************************/
764  MRImageStore(std::initializer_list<size_t> a_args);
765 
774  MRImageStore(const std::vector<size_t>& a_args);
775 
785  MRImageStore(size_t len, const size_t* size);
786 
801  MRImageStore(size_t len, const size_t* size, T* ptr,
802  const std::function<void(void*)>& deleter);
803 
808  MRImageStore();
809 
810  /*************************************************************************
811  * Coordinate Transform Functions
812  ************************************************************************/
813 
826  virtual int indexToPoint(size_t len, const int64_t* xyz, double* ras) const;
827 
840  virtual int indexToPoint(size_t len, const double* xyz, double* ras) const;
841 
854  virtual int pointToIndex(size_t len, const double* ras, double* xyz) const;
855 
868  virtual int pointToIndex(size_t len, const double* ras, int64_t* index) const;
869 
883  virtual int orientVector(size_t len, const double* xyz, double* ras) const;
884 
899  virtual int disOrientVector(size_t len, const double* ras, double* xyz) const;
900 
912  virtual bool pointInsideFOV(size_t len, const double* ras) const;
913 
926  virtual bool indexInsideFOV(size_t len, const double* xyz) const;
927 
939  virtual bool indexInsideFOV(size_t len, const int64_t* xyz) const;
940 
950  std::string getUnits(size_t d) { return m_units[d]; };
951 
952  /********************************************
953  * Output Functions
954  *******************************************/
964  int write(std::string filename, double version) const;
965 
969  void printSelf();
970 
971  /********************************************
972  * Copying/Pointer Functions
973  *******************************************/
974 
980  virtual ptr<NDArray> copy() const;
981 
987  virtual ptr<NDArray> createAnother() const;
988 
1000  virtual ptr<NDArray> createAnother(size_t newdims, const size_t* newsize,
1001  PixelT newtype) const;
1002 
1012  virtual ptr<NDArray> createAnother(PixelT newtype) const;
1013 
1026  virtual ptr<NDArray> createAnother(size_t newdims,
1027  const size_t* newsize) const;
1028 
1040  virtual ptr<NDArray> copyCast(size_t newdims, const size_t* newsize,
1041  PixelT newtype) const;
1042 
1052  virtual ptr<NDArray> copyCast(PixelT newtype) const;
1053 
1065  virtual ptr<NDArray> copyCast(size_t newdims, const size_t* newsize) const;
1066 
1080  virtual ptr<NDArray> extractCast(size_t len, const int64_t* index,
1081  const size_t* size) const;
1082 
1096  virtual ptr<NDArray> extractCast(size_t len, const size_t* size) const;
1097 
1113  virtual ptr<NDArray> extractCast(size_t len,
1114  const int64_t* index, const size_t* size, PixelT newtype) const;
1115 
1130  virtual ptr<NDArray> extractCast(size_t len, const size_t* size,
1131  PixelT newtype) const;
1132 
1139  ptr<MRImage> cloneImage() const;
1140 
1141 protected:
1142 
1146  std::string m_units[D];
1147 
1148  int writeNifti1Image(gzFile file) const;
1149  int writeNifti2Image(gzFile file) const;
1150  int writeNifti1Header(gzFile file) const;
1151  int writeNifti2Header(gzFile file) const;
1152 // int writePixels(gzFile file) const;
1153  int writeJSON(gzFile file) const;
1154 };
1155 } // npl
1156 #endif
int writeJSON(gzFile file) const
void setOrigin(const VectorXd &neworigin, bool reinit)
Sets the origin vector. This is the physical point that corresponds to index 0. Note that min(current...
ptr< const MRImage > getConstPtr() const
Returns a constant pointer to self.
Definition: mrimage.h:490
Definition: accessors.h:29
const VectorXd & getSpacing() const
Returns const reference to the spacing vector. This is the physical distance between adjacent indexes...
CoordinateT m_coordinate
Definition: mrimage.h:675
ptr< MRImage > createMRImage(size_t ndim, const size_t *size, PixelT type)
Creates a new MRImage with dimensions set by ndim, and size set by size. Output pixel type is decided...
virtual int disOrientVector(size_t len, const double *ras, double *xyz) const =0
Convert a vector in index coordinates to a vector in ras coordinates. Vector is simply multiplied by ...
virtual ptr< NDArray > extractCast(size_t len, const int64_t *index, const size_t *size) const
Create a new array that is a copy of the input, possibly with new dimensions or size. The new array will have all overlapping pixels copied from the old array. The new array will have the same pixel type as the input array.
MRImageStore is a version of NDArray that has an orientation matrix. Right now it also has additional...
Definition: mrimage.h:748
virtual bool pointInsideFOV(size_t len, const double *ras) const =0
Returns true if the point is within the field of view of the image. Note, like all coordinates pass t...
void updateSliceTiming(double duration, int start, int end, SliceOrderT order)
virtual bool indexInsideFOV(size_t len, const double *xyz) const =0
Returns true if the constinuous index is within the field of view of the image. Note, like all coordinates pass to MRImage, if the array given differs from the dimensions of the image, then the result will either pad out zeros and ignore extra values in the input array.
int m_freqdim
Definition: mrimage.h:672
virtual bool pointInsideFOV(size_t len, const double *ras) const
Returns true if the point is within the field of view of the image. Note, like all coordinates pass t...
MatrixXd m_inv_direction
Inverse of Direction Matrix.
Definition: mrimage.h:719
const double & direction(int64_t row, int64_t col) const
Returns reference to a value in the direction matrix. Each row indicates the direction of the grid in...
CoordinateT
Definition: mrimage.h:35
virtual bool isIsotropic(bool only3d=true, double tol=0.01) const
Returns true if the image is isotropic (same spacing in all dimensions). This can be looseened to che...
virtual int orientVector(size_t len, const double *xyz, double *ras) const
Convert a vector in index coordinates to a vector in ras coordinates. Vector is simply multiplied by ...
virtual bool matchingOrient(ptr< const MRImage > other, bool checkdim, bool checksize, double tol=0.01) const
Returns true of the other image has matching orientation as this. If checksize = true, then it will also check the size of the two images and return true if both orientation and size match, and false if they don't.
SliceOrderT m_slice_order
Definition: mrimage.h:700
virtual int disOrientVector(size_t len, const double *ras, double *xyz) const
Convert a vector in index coordinates to a vector in ras coordinates. Vector is simply multiplied by ...
double m_slice_duration
Definition: mrimage.h:685
double & spacing(int64_t row)
Returns reference to a value in the spacing vector. This is the physical distance between adjacent in...
ptr< MRImage > cloneImage() const
Create an exact copy of the current image object, and return a pointer to it.
virtual bool indexInsideFOV(size_t len, const double *xyz) const
Returns true if the constinuous index is within the field of view of the image. Note, like all coordinates pass to MRImage, if the array given differs from the dimensions of the image, then the result will either pad out zeros and ignore extra values in the input array.
VectorXd m_spacing
Spacing vector. Indicates distance between adjacent pixels in each dimension. Note that you should no...
Definition: mrimage.h:726
Pure virtual interface to interact with an ND array.
Definition: ndarray.h:165
virtual int orientVector(size_t len, const double *xyz, double *ras) const =0
Convert a vector in index coordinates to a vector in ras coordinates. Vector is simply multiplied by ...
SliceOrderT
Definition: mrimage.h:32
int writeNifti1Header(gzFile file) const
MatrixXd m_direction
Direction Matrix. Each row indicates the direction of the grid in RAS coordinates. This is the rotation of the Index grid. Note that you should not set this directly,.
Definition: mrimage.h:714
virtual ptr< NDArray > copy() const =0
Performs a deep copy of the entire image and all metadata.
virtual int writeNifti2Image(gzFile file) const =0
int write(std::string filename, double version) const
Write out nifti image with the current images data.
BoundaryConditionT
Definition: mrimage.h:37
std::ostream & operator<<(std::ostream &os, const Matrix< D1, D2 > &b)
bool isOriented()
Returns true if the image has a valid orientation.
Definition: mrimage.h:145
VectorXd m_origin
Origin vector. Indicates the RAS coordinates of index [0,0,0,..] Note that you should not set this di...
Definition: mrimage.h:733
PixelT
Definition: ndarray.h:35
const MatrixXd & getDirection() const
Returns reference to the direction matrix. Each row indicates the direction of the grid in RAS coordi...
int writeNifti2Header(gzFile file) const
virtual int indexToPoint(size_t len, const int64_t *xyz, double *ras) const =0
const VectorXd & getOrigin() const
Returns const reference to the origin vector. This is the physical point that corresponds to index 0...
virtual ptr< NDArray > copyCast(size_t newdims, const size_t *newsize, PixelT newtype) const =0
Create a new image that is a copy of the input, possibly with new dimensions and pixeltype. The new image will have all overlapping pixels copied from the old image.
int m_phasedim
Definition: mrimage.h:673
virtual ptr< NDArray > copyCast(size_t newdims, const size_t *newsize, PixelT newtype) const
Create a new image that is a copy of the input, possibly with new dimensions and pixeltype. The new image will have all overlapping pixels copied from the old image.
int m_slice_start
Definition: mrimage.h:686
std::string m_units[D]
Vector of units for each dimension.
Definition: mrimage.h:1146
virtual int pointToIndex(size_t len, const double *ras, double *xyz) const
Converts a point in RAS coordinate system to index. If len < dimensions, additional dimensions are as...
virtual ptr< MRImage > cloneImage() const =0
Create a copy of this image. This is identical to copy() but will return a pointer to an image rather...
MRImage can basically be used like an NDArray, with the addition of orientation related additions...
Definition: mrimage.h:123
virtual int write(std::string filename, double version=1) const =0
Write the image to a nifti file.
void setDirection(const MatrixXd &newdir, bool reinit, CoordinateT coord=QFORM)
Updates orientation information. If reinit is given then it will first set direction to the identity...
MRImageStore()
Default constructor, uses identity for direction matrix, 1 for spacing and 0 for origin. Image size is 0.
void setSpacing(const VectorXd &newspacing, bool reinit)
Sets the spacing vector. This is the physical point that corresponds to index 0. Note that min(curren...
virtual int writeNifti1Image(gzFile file) const =0
virtual int indexToPoint(size_t len, const int64_t *xyz, double *ras) const
Converts an index in pixel space to RAS, physical/time coordinates. If len < dimensions, additional dimensions are assumed to be 0. If len > dimensions then additional values are ignored, and only the first DIM values will be transformed and written to ras.
std::string getUnits(size_t d)
Returns units of given dimension, note that this is prior to the direction matrix, so if there is oblique orientation you are really looking at a mix of units.
Definition: mrimage.h:950
std::shared_ptr< T > ptr
Make the shared_ptr name shorter...
Definition: npltypes.h:42
virtual int pointToIndex(size_t len, const double *ras, double *xyz) const =0
Converts a point in RAS coordinate system to index. If len < dimensions, additional dimensions are as...
void orientDefault()
Default orientation (dir=ident, space=1 and origin=0), also resizes them. So this could be called wit...
virtual ptr< NDArray > copy() const
Performs a deep copy of the entire image and all metadata.
const double & invdirection(int64_t row, int64_t col) const
Returns reference to a value in the inverse direction matrix. Each row indicates the direction of the...
virtual ptr< NDArray > createAnother() const =0
Creates an identical array, but does not initialize pixel values.
int m_slice_end
Definition: mrimage.h:687
friend ptr< MRImage > readNiftiImage(gzFile file, bool verbose)
double & origin(int64_t row)
Returns reference to a value in the origin vector. This is the physical point that corresponds to ind...
int writeNifti2Image(gzFile file) const
int writeNifti1Image(gzFile file) const
virtual ptr< NDArray > createAnother() const
Creates an identical array, but does not initialize pixel values.
virtual ptr< NDArray > extractCast(size_t len, const int64_t *index, const size_t *size) const =0
extracts a region of this image. Zeros in the size variable indicate dimension to be removed...
int m_slicedim
Definition: mrimage.h:674
void setOrient(const VectorXd &neworig, const VectorXd &newspace, const MatrixXd &newdir, bool reinit=true, CoordinateT coord=QFORM)
Update the orientation of the pixels in RAS space.
void printSelf()
Print information about the image.
virtual void copyMetadata(ptr< const MRImage > src)
Copies metadata from another image. This includes slice timing, anything read from nifti files...
std::map< int64_t, double > m_slice_timing
Definition: mrimage.h:703
Basic storage unity for ND array. Creates a big chunk of memory.
Definition: ndarray.h:452
ptr< MRImage > getPtr()
Returns a pointer to self.
Definition: mrimage.h:481