b0Predictor.h 6.09 KB
Newer Older
wangkx1's avatar
init  
wangkx1 committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*! \file b0Predictor.h
    \brief Contains declaration of class for making silly (mean) predictions about b=0 data.

    \author Jesper Andersson
    \version 1.0b, Sep., 2012.
*/
// Declarations of class to make silly
// predictions about b0 scans.
//
// b0Predictor.h
//
// Jesper Andersson, FMRIB Image Analysis Group
//
// Copyright (C) 2011 University of Oxford
//

#ifndef b0Predictor_h
#define b0Predictor_h

#include <cstdlib>
#include <string>
#include <vector>
#include <cmath>
#include <memory>
#include "armawrap/newmat.h"
#include "newimage/newimageall.h"
#include "miscmaths/miscmaths.h"
#include "EddyHelperClasses.h"
#include "DWIPredictionMaker.h"

namespace EDDY {

/****************************************************************//**
*
* \brief Class for making silly (mean) predictions about b=0 data.
*
* Will make predictions about b=0 scans. Since we don't expect any
* variability in these scans the prediction will simply be the mean
* of all the scans in the prediction maker. It is there mainly so
* that the same code can be used for registration of
* diffusion-weighted and b=0 scans.
*
********************************************************************/
class b0Predictor : public DWIPredictionMaker
{
public:
  b0Predictor() EddyTry : _pop(true), _valid(false) {} EddyCatch
  ~b0Predictor() {}
  virtual NEWIMAGE::volume<float> Predict(unsigned int indx, bool exclude=false) const EddyTry { return(predict()); } EddyCatch
  virtual NEWIMAGE::volume<float> Predict(unsigned int indx, bool exclude=false) EddyTry { return(predict()); } EddyCatch
  virtual NEWIMAGE::volume<float> PredictCPU(unsigned int indx, bool exclude=false) EddyTry { return(predict()); } EddyCatch
  virtual std::vector<NEWIMAGE::volume<float> > Predict(const std::vector<unsigned int>& indicies, bool exclude=false);
  /// Returns input data for point given by indx
  virtual NEWIMAGE::volume<float> InputData(unsigned int indx) const;
  /// Returns input data for points given by indicies
  virtual std::vector<NEWIMAGE::volume<float> > InputData(const std::vector<unsigned int>& indicies) const;
  /// Returns variance of prediction for point given by indx.
  virtual double PredictionVariance(unsigned int indx, bool exclude=false) EddyTry { return(_mean.mean(_mask) / std::sqrt(double(_sptrs.size()))); } EddyCatch
  /// Returns measurement-error variance for point given by indx.
  virtual double ErrorVariance(unsigned int indx) const EddyTry { return(_mean.mean(_mask)); } EddyCatch
  virtual bool IsPopulated() const;                  // Returns true if all data present
  virtual bool IsValid() const { return(_valid); }   // Returns true if ready to make predictions
  virtual void SetNoOfScans(unsigned int n);
  virtual void SetScan(const NEWIMAGE::volume<float>& scan, // _May_ be thread safe if used "sensibly"
		       const DiffPara&                dp,
		       unsigned int                   indx,
		       unsigned int                   sess) { SetScan(scan,dp,indx); }
  virtual void SetScan(const NEWIMAGE::volume<float>& scan, // _May_ be thread safe if used "sensibly"
		       const DiffPara&                dp,
		       unsigned int                   indx);
  virtual unsigned int NoOfHyperPar() const { return(0); }
  virtual std::vector<double> GetHyperPar() const EddyTry { std::vector<double> rval; return(rval); } EddyCatch
  virtual void EvaluateModel(const NEWIMAGE::volume<float>& mask, float fwhm, bool verbose=false) EddyTry
  {
    if (!IsPopulated()) throw EddyException("b0Predictor::EvaluateModel: Not ready to evaluate model");
    if (!IsValid()) { _mask=mask; _mean=mean_vol(_mask); _var=variance_vol(_mean,_mask); }
  } EddyCatch
  virtual void EvaluateModel(const NEWIMAGE::volume<float>& mask, bool verbose=false) EddyTry { EvaluateModel(mask,0.0,verbose); } EddyCatch
  virtual void WriteImageData(const std::string& fname) const;
  virtual void WriteMetaData(const std::string& fname) const {}
  virtual void Write(const std::string& fname) const EddyTry { WriteImageData(fname); WriteMetaData(fname); } EddyCatch

private:
  std::vector<std::shared_ptr<NEWIMAGE::volume<float> > > _sptrs; // Pointers to the scans
  NEWIMAGE::volume<float>                                 _mean;  // Mean image
  NEWIMAGE::volume<float>                                 _var;   // Variance image
  NEWIMAGE::volume<float>                                 _mask;  // Mask indicating valid voxels
  mutable bool                                            _pop;   // Tells if all data is present
  bool                                                    _valid; // Tells if it is ready to make predictions

  const NEWIMAGE::volume<float>& predict() const EddyTry
  {
    if (!IsValid()) throw EddyException("b0Predictor::Predict: Not ready to make predictions");
    return(_mean);
  } EddyCatch

  NEWIMAGE::volume<float> mean_vol(const NEWIMAGE::volume<float>& mask) EddyTry
  {
    NEWIMAGE::volume<float> mvol = *_sptrs[0];
    mvol = 0.0;
    for (int k=0; k<_sptrs[0]->zsize(); k++) {
      for (int j=0; j<_sptrs[0]->ysize(); j++) {
	for (int i=0; i<_sptrs[0]->xsize(); i++) {
	  if (1) {
	    // if (mask(i,j,k)) { I removed masking 13/5-2016. J.A.
            float &v = mvol(i,j,k);
	    for (unsigned int s=0; s<_sptrs.size(); s++) {
              v += (*_sptrs[s])(i,j,k);
	    }
            v /= float(_sptrs.size());
	  }
	}
      }
    }
    _valid = true;
    return(mvol);
  } EddyCatch

  NEWIMAGE::volume<float> variance_vol(const NEWIMAGE::volume<float>& mean,
				       const NEWIMAGE::volume<float>& mask) EddyTry
  {
    NEWIMAGE::volume<float> vvol = *_sptrs[0];
    vvol = 0.0;
    if (_sptrs.size() > 1) {
      for (int k=0; k<_sptrs[0]->zsize(); k++) {
	for (int j=0; j<_sptrs[0]->ysize(); j++) {
	  for (int i=0; i<_sptrs[0]->xsize(); i++) {
	    if (1) {
	      // if (mask(i,j,k)) { I removed masking 13/5-2016. J.A.
	      float &v = vvol(i,j,k);
	      float mv = mean(i,j,k);
	      for (unsigned int s=0; s<_sptrs.size(); s++) {
		v += MISCMATHS::Sqr(((*_sptrs[s])(i,j,k) - mv));
	      }
	      v /= float(_sptrs.size()-1);
	    }
	  }
	}
      }
    }
    _valid = true;
    return(vvol);
  } EddyCatch
};

} // End namespace EDDY

#endif // End #ifndef b0Predictor_h