-
Stamatios Sotiropoulos authoredStamatios Sotiropoulos authored
rubixvox.h 31.14 KiB
/* rubixvox.h: Classes utilized in RubiX */
/* Stam Sotiropoulos, FMRIB Analysis Group */
/* Copyright (C) 2012 University of Oxford */
/* CCOPYRIGHT */
#if !defined(rubixvox_h)
#define rubixvox_h
#include <iostream>
#include <fstream>
#include <iomanip>
#define WANT_STREAM
#define WANT_MATH
#include <string>
#include <math.h>
#include "miscmaths/miscmaths.h"
#include "miscmaths/miscprob.h"
#include "stdlib.h"
#include "utils/log.h"
using namespace std;
using namespace NEWMAT;
using namespace MISCMATHS;
namespace RUBIX{
const float maxfloat=1e10;
const float minfloat=1e-10;
const float maxlogfloat=23;
const float minlogfloat=-23;
//////////////////////////////////////////////////////////////////////
// RFibre: Models one anisotropic compartment in an HR voxel
//////////////////////////////////////////////////////////////////////
class RFibre{
float m_th; //Current/candidate MCMC state
float m_ph;
float m_f;
ColumnVector m_vec; //Holds the current/candidate orientation in cartesian coordinates
ColumnVector m_vec_old;
float m_th_prop; //Standard deviation for Gaussian proposal distributions of parameters
float m_ph_prop;
float m_f_prop;
float m_th_old; //Last accepted value. If a sample is rejected this value is restored
float m_ph_old;
float m_f_old;
float m_th_ph_prior; //Priors for the model parameters
float m_f_prior;
float m_th_ph_old_prior;
float m_f_old_prior;
float m_prior_en; //Joint Prior
float m_old_prior_en;
int m_th_acc;
int m_th_rej;
int m_ph_acc;
int m_ph_rej;
int m_f_acc;
int m_f_rej;
bool f_ard; //By default ARD is on, on the volume fraction f
ColumnVector m_SignalHR; //Vector that stores the predicted signal from the anisotropic compartment during the candidate/current MCMC state at High-Res measurement points
ColumnVector m_SignalHR_old;
ColumnVector m_SignalLR; //Vector that stores the predicted signal from the anisotropic compartment during the candidate/current MCMC state at Low-Res measurement points
ColumnVector m_SignalLR_old;
const Matrix& m_Orient_hyp_prior;//Matrix Nmodes x 5 that contains the hyperparameters for the orientation prior
//columns 1-3 contains the (x,y,z) coordinates for the mode, 4th column contains the invkappa value, 5th the Watson normalization constant
const float m_ardfudge;
const float& m_d;
const float& m_d_std;
const Matrix& m_bvecsHR; //bvecs at High-Res (3 x HR_NumPoints)
const Matrix& m_bvalsHR; //bvalues at High-Res (1 x HR_NumPoints)
const Matrix& m_bvecsLR; //bvecs at Low-Res (3 x LR_NumPoints)
const Matrix& m_bvalsLR; //bvalues at Low-Res (1 x HR_NumPoints)
const int m_modelnum; //1 for single-shell, 2 for multi-shell model
public:
//constructor
RFibre(const float th, const float ph,const float f, const Matrix& bvecsHR, const Matrix& bvalsHR,
const Matrix& bvecsLR, const Matrix& bvalsLR, const Matrix& Orient_hyp_prior,
const float& d, const float& d_std, const bool ard=true, const int modelnum=1,const float ardfudge=1):
m_th(th), m_ph(ph), m_f(f), f_ard(ard), m_Orient_hyp_prior(Orient_hyp_prior), m_ardfudge(ardfudge), m_d(d),
m_d_std(d_std),m_bvecsHR(bvecsHR), m_bvalsHR(bvalsHR), m_bvecsLR(bvecsLR), m_bvalsLR(bvalsLR), m_modelnum(modelnum){
m_th_old=m_th; m_ph_old=m_ph;
m_vec.ReSize(3);
m_vec<<sin(m_th)*cos(m_ph) <<sin(m_th)*sin(m_ph) <<cos(m_th);
m_vec_old=m_vec;
m_f_old=m_f;
m_th_prop=0.2; m_ph_prop=0.2; m_f_prop=m_f/5.0;
m_th_ph_prior=0; m_th_ph_old_prior=0;
m_f_prior=0; m_f_old_prior=0;
m_SignalHR.ReSize(m_bvecsHR.Ncols()); m_SignalHR=0; m_SignalHR_old=m_SignalHR;
m_SignalLR.ReSize(m_bvecsLR.Ncols()); m_SignalLR=0; m_SignalLR_old=m_SignalLR;
m_th_acc=0; m_th_rej=0;
m_ph_acc=0; m_ph_rej=0;
m_f_acc=0; m_f_rej=0;
}
~RFibre(){}
inline float get_th() const{ return m_th;}
inline float get_ph() const{ return m_ph;}
inline const ColumnVector& getVec() const { return m_vec; }
inline float get_f() const{ return m_f;}
//inline void set_th(const float th){ m_th=th; m_vec<<sin(m_th)*cos(m_ph) <<sin(m_th)*sin(m_ph) <<cos(m_th); }
//inline void set_ph(const float ph){ m_ph=ph; m_vec<<sin(m_th)*cos(m_ph) <<sin(m_th)*sin(m_ph) <<cos(m_th); }
//inline void set_f(const float f){ m_f=f; }
inline const ColumnVector& getSignalHR() const{ return m_SignalHR; }
inline const ColumnVector& getSignalLR() const{ return m_SignalLR; }
inline void restoreSignals() { m_SignalHR=m_SignalHR_old; m_SignalLR=m_SignalLR_old; }
inline float get_prior() const{ return m_prior_en;}
void initialise_energies(); //Initialize energies, signals
void update_proposals();
bool compute_th_ph_prior();
bool compute_f_prior();
void compute_prior();
void compute_signal(); //Compute model predicted signal, only due to the anisotropic compartment
void restore_th_ph_prior();
bool propose_th();
inline void accept_th(){ m_th_acc++; }
void reject_th();
bool propose_ph();
inline void accept_ph(){ m_ph_acc++; }
void reject_ph();
bool propose_f();
inline void accept_f(){ m_f_acc++; }
void reject_f();
void report() const;
RFibre& operator=(const RFibre& rhs){
m_th=rhs.m_th; m_ph=rhs.m_ph; m_f=rhs.m_f;
m_vec=rhs.m_vec; m_vec_old=rhs.m_vec_old;
m_th_prop=rhs.m_th_prop; m_ph_prop=rhs.m_ph_prop; m_f_prop=rhs.m_f_prop;
m_th_old=rhs.m_th_old; m_ph_old=rhs.m_ph_old; m_f_old=rhs.m_f_old;
m_th_ph_prior=rhs.m_th_ph_prior; m_f_prior=rhs.m_f_prior;
m_th_ph_old_prior=rhs.m_th_ph_old_prior; m_f_old_prior=rhs.m_f_old_prior;
m_prior_en=rhs.m_prior_en; m_old_prior_en=rhs.m_old_prior_en;
m_th_acc=rhs.m_th_acc; m_th_rej=rhs.m_th_rej;
m_ph_acc=rhs.m_ph_acc; m_ph_rej=rhs.m_ph_rej;
m_f_acc=rhs.m_f_acc; m_f_rej=rhs.m_f_rej;
f_ard=rhs.f_ard;
m_SignalHR=rhs.m_SignalHR; m_SignalHR_old=rhs.m_SignalHR_old;
m_SignalLR=rhs.m_SignalLR; m_SignalLR_old=rhs.m_SignalLR_old;
return *this;
}
};
//////////////////////////////
// HRvoxel //
//////////////////////////////
class HRvoxel{
vector<RFibre> m_fibres;
float m_d;
float m_d_old;
float m_d_prop;
float m_d_prior;
float m_d_old_prior;
float m_d_acc;
float m_d_rej;
float m_d_std;
float m_d_std_old;
float m_d_std_prop;
float m_d_std_prior;
float m_d_std_old_prior;
float m_d_std_acc;
float m_d_std_rej;
float m_S0;
float m_S0_old;
float m_S0_prop;
float m_S0_prior;
float m_S0_old_prior;
float m_S0_acc;
float m_S0_rej;
float m_tau; //Noise at a High-res voxel (precision)
float m_tau_old;
float m_tau_prop;
float m_tau_prior;
float m_tau_old_prior;
float m_tau_acc;
float m_tau_rej;
const float& m_mean_d; //hyperparameters for d prior
const float& m_stdev_d;
const float& m_mean_fsum; //hyperparameters for fsum prior
const float& m_stdev_fsum;
float m_fsum_prior;
float m_fsum_old_prior;
float m_prior_en; //Joint Prior
float m_old_prior_en;
ColumnVector m_iso_SignalHR; //Vector that stores the predicted signal from the isotropic compartment only
ColumnVector m_iso_SignalHR_old;
ColumnVector m_iso_SignalLR; //Vector that stores the predicted signal from the isotropic compartment only
ColumnVector m_iso_SignalLR_old;
ColumnVector m_SignalHR; //Vector that stores the total predicted signal from the specific voxel at High-Res measurement points
ColumnVector m_SignalHR_old;
ColumnVector m_SignalLR; //Vector that stores the total predicted signal from the specific voxel at Low-Res measurement points
ColumnVector m_SignalLR_old;
const Matrix& m_Orient_hyp_prior;//Matrix Nmodes x 5 that contains the hyperparameters for the orientation prior
const Matrix& m_bvecsHR; //bvecs at High-Res (3 x HR_NumPoints)
const Matrix& m_bvalsHR; //bvalues at High-Res (1 x HR_NumPoints)
const Matrix& m_bvecsLR; //bvecs at Low-Res (3 x LR_NumPoints)
const Matrix& m_bvalsLR; //bvalues at Low-Res (1 x HR_NumPoints)
const int m_modelnum; //1 for single-shell, 2 for multi-shell model
const int m_numfibres; //number of fibres in this HR voxel
const float m_ardfudge;
const bool m_fsumPrior_ON; //Flag that indicates whether a prior on the fsum will be imposed (based on the LRvox neighbourhood mean)
const bool m_dPrior_ON; //Flag that indicates whether a prior on diffusivity will be imposed (based on the LRvox neighbourhood mean)
const bool m_rician; //indicates whether Rician Noise model is used
//const ColumnVector& LRvox_inter; //array with indices on LR voxels intersected by this HR
public:
//Constructor
HRvoxel(const Matrix& bvecsHR, const Matrix& bHR,
const Matrix& bvecsLR, const Matrix& bLR,
const Matrix& Orient_hyp_prior,
const float& mean_d, const float& stdev_d, const float& mean_fsum, const float& stdev_fsum,
const int N, const int modelnum=1,const float ardfudge=1, const bool fsumPrior_ON=false, const bool dPrior_ON=false, const bool rician=false):
m_mean_d(mean_d), m_stdev_d(stdev_d), m_mean_fsum(mean_fsum), m_stdev_fsum(stdev_fsum),
m_Orient_hyp_prior(Orient_hyp_prior),
m_bvecsHR(bvecsHR), m_bvalsHR(bHR), m_bvecsLR(bvecsLR), m_bvalsLR(bLR), m_modelnum(modelnum), m_numfibres(N), m_ardfudge(ardfudge), m_fsumPrior_ON(fsumPrior_ON), m_dPrior_ON(dPrior_ON), m_rician(rician) {
//Initialize vectors that keep the signal from the isotropic compartment
m_iso_SignalHR.ReSize(m_bvecsHR.Ncols()); m_iso_SignalHR=0; m_iso_SignalHR_old=m_iso_SignalHR;
m_SignalHR.ReSize(m_bvecsHR.Ncols()); m_SignalHR=0; m_SignalHR_old=m_SignalHR;
m_iso_SignalLR.ReSize(m_bvecsLR.Ncols()); m_iso_SignalLR=0; m_iso_SignalLR_old=m_iso_SignalLR;
m_SignalLR.ReSize(m_bvecsLR.Ncols()); m_SignalLR=0; m_SignalLR_old=m_SignalLR;
m_d_acc=0; m_d_rej=0; m_d_prior=0; m_d_old_prior=0;
m_d_std_acc=0; m_d_std_rej=0; m_d_std_prior=0; m_d_std_old_prior=0;
m_S0_acc=0; m_S0_rej=0; m_S0_prior=0; m_S0_old_prior=0;
m_d=0; m_d_old=0; m_d_std=0; m_d_std_old=0; m_S0=0; m_S0_old=0;
m_tau_acc=0; m_tau_rej=0; m_tau_prior=0; m_tau_old_prior=0; m_tau=0; m_tau_old=0;
m_prior_en=0; m_old_prior_en=0;
m_fsum_prior=0; m_fsum_old_prior=0;
}
//Destructor
~HRvoxel(){}
const vector<RFibre>& fibres() const{ return m_fibres; }
void addfibre(const float th, const float ph, const float f,const bool use_ard=true) {
RFibre fib(th,ph,f,m_bvecsHR,m_bvalsHR,m_bvecsLR,m_bvalsLR,m_Orient_hyp_prior,m_d,m_d_std,use_ard,m_modelnum,m_ardfudge);
m_fibres.push_back(fib);
}
void initialise_energies_props(); //Initialize energies, signals and standard deviations for the proposal distributions
inline float get_d() const{ return m_d;}
inline void set_d(const float d){ m_d=d; }
inline float get_d_std() const{ return m_d_std; }
inline void set_d_std(const float d_std){ m_d_std=d_std; }
inline float get_S0() const{ return m_S0; }
inline void set_S0(const float S0){ m_S0=S0; }
inline float get_tau() const{ return m_tau; }
inline void set_tau(const float tau){ m_tau=tau; }
inline float get_prior() const { return m_prior_en; }
inline const ColumnVector& getSignalHR() const{ return m_SignalHR; }
inline const ColumnVector& getSignalLR() const{ return m_SignalLR; }
bool compute_d_prior();
bool compute_d_std_prior();
bool compute_S0_prior();
bool compute_tau_prior();
bool reject_f_sum(); //Check if sum of volume fractions is >1
void update_d_prior();
void restore_d_prior();
void compute_fsum_prior();
void update_fsum_prior();
void restore_fsum_prior();
void compute_prior(); //Compute Joint Prior energy
void compute_iso_signal(); //Compute the predicted signal from the isotropic compartment only
void compute_signal(); //Compute the total predicted signal
bool propose_d();
void accept_d(){ m_d_acc++; }
void reject_d();
bool propose_d_std();
void accept_d_std(){ m_d_std_acc++; }
void reject_d_std();
bool propose_S0();
void accept_S0(){ m_S0_acc++; }
void reject_S0();
bool propose_tau();
void accept_tau(){ m_tau_acc++; }
void reject_tau();
bool propose_th(int n){ return m_fibres[n].propose_th(); } //n is the fibre index from 0 to N-1
void accept_th(int n) { m_fibres[n].accept_th(); }
void reject_th(int n) { m_fibres[n].reject_th(); }
bool propose_ph(int n){ return m_fibres[n].propose_ph(); }
void accept_ph(int n) { m_fibres[n].accept_ph(); }
void reject_ph(int n) { m_fibres[n].reject_ph(); }
bool propose_f(int n) { return m_fibres[n].propose_f(); }
void accept_f(int n) { m_fibres[n].accept_f(); }
void reject_f(int n) { m_fibres[n].reject_f(); }
void restore_prior_totsignal();
void restore_prior();
void update_th_ph_prior(); //Used to update the conditional orientation prior when the prior parameters are jumped
void restore_th_ph_prior();
void update_proposals(); //Adapt standard deviation of proposal distributions during MCMC execution
void report() const;
HRvoxel& operator=(const HRvoxel& rhs){
m_fibres=rhs.m_fibres;
m_d=rhs.m_d; m_d_old=rhs.m_d_old; m_d_prop=rhs.m_d_prop;
m_d_prior=rhs.m_d_prior; m_d_old_prior=rhs.m_d_old_prior;
m_d_acc=rhs.m_d_acc; m_d_rej=rhs.m_d_rej;
m_d_std=rhs.m_d_std; m_d_std_old=rhs.m_d_std_old; m_d_std_prop=rhs.m_d_std_prop;
m_d_std_prior=rhs.m_d_std_prior; m_d_std_old_prior=rhs.m_d_std_old_prior;
m_d_std_acc=rhs.m_d_std_acc; m_d_std_rej=rhs.m_d_std_rej;
m_fsum_prior=rhs.m_fsum_prior; m_fsum_old_prior=rhs.m_fsum_old_prior;
m_S0=rhs.m_S0; m_S0_old=rhs.m_S0_old; m_S0_prop=rhs.m_S0_prop;
m_S0_prior=rhs.m_S0_prior; m_S0_old_prior=rhs.m_S0_old_prior;
m_S0_acc=rhs.m_S0_acc; m_S0_rej=rhs.m_S0_rej;
m_tau=rhs.m_tau; m_tau_old=rhs.m_tau_old; m_tau_prop=rhs.m_tau_prop;
m_tau_prior=rhs.m_tau_prior; m_tau_old_prior=rhs.m_tau_old_prior;
m_tau_acc=rhs.m_tau_acc; m_tau_rej=rhs.m_tau_rej;
m_prior_en=rhs.m_prior_en; m_old_prior_en=rhs.m_old_prior_en;
m_iso_SignalHR=rhs.m_iso_SignalHR; m_iso_SignalHR_old=rhs.m_iso_SignalHR_old;
m_iso_SignalLR=rhs.m_iso_SignalLR; m_iso_SignalLR_old=rhs.m_iso_SignalLR_old;
m_SignalHR=rhs.m_SignalHR; m_SignalHR_old=rhs.m_SignalHR_old;
m_SignalLR=rhs.m_SignalLR; m_SignalLR_old=rhs.m_SignalLR_old;
return *this;
}
};
/////////////////////////////////////////////////////////////////////////////
// Orient_Prior_Mode: Models a single mode of the orientation prior ///
// The orientation prior is a sum of Watson distributions centred ///
// around different modes ///
/////////////////////////////////////////////////////////////////////////////
class Orient_Prior_Mode{
float m_th;
float m_th_old;
float m_th_prop;
float m_th_prior;
float m_th_old_prior;
float m_th_acc;
float m_th_rej;
float m_ph;
float m_ph_old;
float m_ph_prop;
float m_ph_prior;
float m_ph_old_prior;
float m_ph_acc;
float m_ph_rej;
float m_invkappa; //Dispersion Index of a Watson distribution (1/kappa actually)
float m_invkappa_old;
float m_invkappa_prop;
float m_invkappa_prior;
float m_invkappa_old_prior;
float m_invkappa_acc;
float m_invkappa_rej;
float m_Watson_norm; //this is a function of current m_kappa
float m_Watson_norm_old;
ColumnVector m_vec;
ColumnVector m_vec_old;
float m_prior_en; //Joint HyperPrior
float m_old_prior_en;
const bool m_kappa_ard; //Flag for setting ARD on the dispersion index
public:
//Constructor
Orient_Prior_Mode(bool kappa_ard): m_kappa_ard(kappa_ard) {
m_th=M_PI/2; m_th_old=m_th;
m_ph=0; m_ph_old=m_ph;
m_vec.ReSize(3);
m_vec<<sin(m_th)*cos(m_ph) <<sin(m_th)*sin(m_ph) <<cos(m_th);
m_vec_old=m_vec;
m_invkappa=0.02; m_invkappa_old=m_invkappa;
m_Watson_norm=compute_Watson_norm(); m_Watson_norm_old=m_Watson_norm;
m_th_prop=0.2; m_ph_prop=0.2; m_invkappa_prop=0.2;
m_th_prior=0; m_th_old_prior=0;
m_ph_prior=0; m_ph_old_prior=0;
m_invkappa_prior=0; m_invkappa_old_prior=0;
m_prior_en=0; m_old_prior_en=0;
m_th_acc=0; m_th_rej=0;
m_ph_acc=0; m_ph_rej=0;
m_invkappa_acc=0; m_invkappa_rej=0;
}
//Destructor
~Orient_Prior_Mode(){}
inline float get_th() const{ return m_th;}
inline float get_ph() const{ return m_ph;}
inline float get_invkappa() const{ return m_invkappa;}
inline void set_th(const float th) { m_th=th; m_vec<< sin(m_th)*cos(m_ph) << sin(m_th)*sin(m_ph) << cos(m_th);}
inline void set_ph(const float ph) { m_ph=ph; m_vec<< sin(m_th)*cos(m_ph) << sin(m_th)*sin(m_ph) << cos(m_th);}
inline void set_invkappa(const float invkappa) { m_invkappa=invkappa; filter_invkappa(); m_Watson_norm=compute_Watson_norm(); }
void filter_invkappa(); //Filter out extreme values of invkappa to ensure calculations are numerically stable
inline float get_prior() const{ return m_prior_en;}
inline const ColumnVector& getVec() const { return m_vec; }
inline float get_Watson_norm() const{ return m_Watson_norm; }
float compute_Watson_norm();
void initialise_energies();
bool compute_th_prior();
bool compute_ph_prior();
bool compute_invkappa_prior();
void compute_prior(); //Compute Joint Prior energy
void update_proposals();
bool propose_th();
inline void accept_th(){ m_th_acc++; }
void reject_th();
bool propose_ph();
inline void accept_ph(){ m_ph_acc++; }
void reject_ph();
bool propose_invkappa();
inline void accept_invkappa(){ m_invkappa_acc++; }
void reject_invkappa();
Orient_Prior_Mode& operator=(const Orient_Prior_Mode& rhs){
m_th=rhs.m_th;
m_th_old=rhs.m_th_old;
m_th_prop=rhs.m_th_prop;
m_th_prior=rhs.m_th_prior; m_th_old_prior=rhs.m_th_old_prior;
m_th_acc=rhs.m_th_acc; m_th_rej=rhs.m_th_rej;
m_ph=rhs.m_ph; m_ph_old=rhs.m_ph_old; m_ph_prop=rhs.m_ph_prop;
m_ph_prior=rhs.m_ph_prior; m_ph_old_prior=rhs.m_ph_old_prior;
m_ph_acc=rhs.m_ph_acc; m_ph_rej=rhs.m_ph_rej;
m_invkappa=rhs.m_invkappa; m_invkappa_old=rhs.m_invkappa_old; m_invkappa_prop=rhs.m_invkappa_prop;
m_invkappa_prior=rhs.m_invkappa_prior; m_invkappa_old_prior=rhs.m_invkappa_old_prior;
m_invkappa_acc=rhs.m_invkappa_acc; m_invkappa_rej=rhs.m_invkappa_rej;
m_Watson_norm=rhs.m_Watson_norm; m_Watson_norm_old=rhs.m_Watson_norm_old;
m_vec=rhs.m_vec; m_vec_old=rhs.m_vec_old;
m_prior_en=rhs.m_prior_en; m_old_prior_en=rhs.m_old_prior_en;
return *this;
}
};
//////////////////////////////
// LRvoxel //
//////////////////////////////
class LRvoxel{
vector<HRvoxel> m_HRvoxels;
vector<Orient_Prior_Mode> m_PModes;
float m_tauLR; //models noise at Low-res
float m_tauLR_old;
float m_tauLR_prop;
float m_tauLR_prior;
float m_tauLR_old_prior;
float m_tauLR_acc;
float m_tauLR_rej;
float m_S0LR; //models S0 intensity at the Low-Res acquisition
float m_S0LR_old;
float m_S0LR_prop;
float m_S0LR_prior;
float m_S0LR_old_prior;
float m_S0LR_acc;
float m_S0LR_rej;
Matrix m_Orient_hyp_prior; //Matrix Nmodes x 5 that contains the hyperparameters for the orientation prior
//columns 1-3 contains the (x,y,z) coordinates for the mode, 4th column contains the invkappa value, 5th the Watson normalization constant
float m_mean_d; //models mean of d hyperprior for the High-Res voxels intersected by the LR_voxel
float m_mean_d_old;
float m_mean_d_prop;
float m_mean_d_prior;
float m_mean_d_old_prior;
float m_mean_d_acc;
float m_mean_d_rej;
float m_stdev_d; //models std_dev of d hyperprior for the High-Res voxels intersected by the LR_voxel
float m_stdev_d_old;
float m_stdev_d_prop;
float m_stdev_d_prior;
float m_stdev_d_old_prior;
float m_stdev_d_acc;
float m_stdev_d_rej;
float m_mean_fsum; //models mean of fsum hyperprior for the High-Res voxels intersected by the LR_voxel
float m_mean_fsum_old;
float m_mean_fsum_prop;
float m_mean_fsum_prior;
float m_mean_fsum_old_prior;
float m_mean_fsum_acc;
float m_mean_fsum_rej;
float m_stdev_fsum; //models std_dev of fsum hyperprior for the High-Res voxels intersected by the LR_voxel
float m_stdev_fsum_old;
float m_stdev_fsum_prop;
float m_stdev_fsum_prior;
float m_stdev_fsum_old_prior;
float m_stdev_fsum_acc;
float m_stdev_fsum_rej;
float m_prior_en; //Joint Prior Energy
float m_old_prior_en;
float m_likelihood_en; //Likelihood Energy
float m_old_likelihood_en;
float m_posterior_en; //Posterior Energy
float m_old_posterior_en;
ColumnVector m_logdataLR; //Log of Low-Res Data for the specific LR voxel (use it in Rician Energy)
vector<ColumnVector> m_logdataHR; //Log of High-Res Data for all contained HR voxels (use it in Rician Energy)
const ColumnVector& m_dataLR; //Low-Res Data for the specific LR voxel
const vector<ColumnVector>& m_dataHR; //High-Res Data for all contained HR voxels
const Matrix& m_bvecsHR; //bvecs at High-Res (3 x HR_NumPoints)
const Matrix& m_bvalsHR; //bvalues at High-Res (1 x HR_NumPoints)
const Matrix& m_bvecsLR; //bvecs at Low-Res (3 x LR_NumPoints)
const Matrix& m_bvalsLR; //bvalues at Low-Res (1 x HR_NumPoints)
const int m_modelnum; //1 for single-shell, 2 for multi-shell model
const int m_numfibres; //Number of fibres in each HR voxel
const int m_Nmodes; //Number of modes for the Orientation Prior
const float m_ardfudge;
const bool m_allard; //Flag for setting ARD on for all fibres in all HR voxels
const bool m_Noard; //Flag for setting ARD off for all fibres in all HR voxels
const bool m_kappa_ard; //Flag for setting ARD on the dispersion index
const bool m_fsumPrior_ON; //Flag for setting on a prior on fsums across intersected HR voxels
const bool m_dPrior_ON; //Flag for setting on a prior on the diffusivity across intersected HR voxels
const bool m_rician; //Flag for using a Rician noise model
const ColumnVector& m_HRweights;//Holds the volume fraction each HR voxel occupies out of the LR one
public:
//Constructor
LRvoxel(const Matrix& bvecsHR, const Matrix& bHR,
const Matrix& bvecsLR, const Matrix& bLR,
const ColumnVector& dataLR, const vector<ColumnVector>& dataHR, const int N, const int Nmodes, const ColumnVector& HRweights, const int modelnum=1, const float ardfudge=1, const bool allard=false, const bool Noard=false, const bool kappa_ard=false, const bool fsumPrior_ON=false, const bool dPrior_ON=false, const bool rician=false):
m_dataLR(dataLR), m_dataHR(dataHR),m_bvecsHR(bvecsHR), m_bvalsHR(bHR), m_bvecsLR(bvecsLR), m_bvalsLR(bLR),
m_modelnum(modelnum), m_numfibres(N), m_Nmodes(Nmodes), m_ardfudge(ardfudge), m_allard(allard), m_Noard(Noard), m_kappa_ard(kappa_ard), m_fsumPrior_ON(fsumPrior_ON), m_dPrior_ON(dPrior_ON), m_rician(rician), m_HRweights(HRweights) {
m_S0LR=0; m_S0LR_old=0; m_S0LR_prior=0; m_S0LR_old_prior=0; m_S0LR_acc=0; m_S0LR_rej=0; m_S0LR_prop=0.2;
m_tauLR=0; m_tauLR_old=0; m_tauLR_prior=0; m_tauLR_old_prior=0; m_tauLR_acc=0; m_tauLR_rej=0; m_tauLR_prop=0.2;
m_mean_d=0; m_mean_d_old=0; m_mean_d_prior=0; m_mean_d_old_prior=0; m_mean_d_acc=0; m_mean_d_rej=0; m_mean_d_prop=0.001;
m_stdev_d=0; m_stdev_d_old=0; m_stdev_d_prior=0; m_stdev_d_old_prior=0; m_stdev_d_acc=0; m_stdev_d_rej=0; m_stdev_d_prop=0.001;
m_mean_fsum=0; m_mean_fsum_old=0; m_mean_fsum_prior=0; m_mean_fsum_old_prior=0; m_mean_fsum_acc=0; m_mean_fsum_rej=0; m_mean_fsum_prop=0.1;
m_stdev_fsum=0; m_stdev_fsum_old=0; m_stdev_fsum_prior=0; m_stdev_fsum_old_prior=0; m_stdev_fsum_acc=0; m_stdev_fsum_rej=0; m_stdev_fsum_prop=0.1;
m_prior_en=0; m_old_prior_en=0;
m_likelihood_en=0; m_old_likelihood_en=0;
m_posterior_en=0; m_old_posterior_en=0;
for (int m=1; m<=m_Nmodes; m++){ //Add Modes for the orientation Prior
Orient_Prior_Mode pMod(m_kappa_ard);
m_PModes.push_back(pMod);
}
m_Orient_hyp_prior.ReSize(m_Nmodes,5);
for (unsigned int m=1; m<=m_dataHR.size(); m++){ //Add HRvoxel Objects
HRvoxel HRv(m_bvecsHR, m_bvalsHR, m_bvecsLR, m_bvalsLR, m_Orient_hyp_prior, m_mean_d, m_stdev_d, m_mean_fsum, m_stdev_fsum, m_numfibres, m_modelnum, m_ardfudge, m_fsumPrior_ON, m_dPrior_ON, m_rician);
m_HRvoxels.push_back(HRv);
}
// ofstream myfile; //Debugging code
//myfile.open("/Users/stam/Rubix_data/Energies.txt", ios::trunc);
//myfile.close();
if (m_rician){//Store the log of the data for energy calculations
m_logdataLR=dataLR; m_logdataHR=dataHR;
for (int m=1; m<=dataLR.Nrows(); m++){
if (dataLR(m)!=0)
m_logdataLR(m)=log(dataLR(m));
else
m_logdataLR(m)=minlogfloat;
}
for (unsigned int n=0; n<dataHR.size(); n++)
for (int m=1; m<=dataHR[n].Nrows(); m++){
if (dataHR[n](m)!=0)
m_logdataHR[n](m)=log(dataHR[n](m));
else
m_logdataHR[n](m)=minlogfloat;
}
}
}
//Destructor
~LRvoxel(){ }
const vector<HRvoxel>& HRvoxels() const {return m_HRvoxels;}
const vector<Orient_Prior_Mode>& PModes() const {return m_PModes;}
void update_Orient_hyp_prior(); //Update the matrix that keeps information on the orientation prior parameters
void update_Orient_hyp_prior(int M); //Update the entry only for a specific Mode 0<=M<N_modes
void set_HRparams(const int n, const float d, const float S0, const ColumnVector& th, const ColumnVector& ph, const ColumnVector& f); //Set params for a single HR voxel
void set_HRparams(const int n, const float d, const float d_std,const float S0, const ColumnVector& th, const ColumnVector& ph, const ColumnVector& f); //Set params for a single HR voxel
void set_Priorparams(const ColumnVector& th, const ColumnVector& ph, const ColumnVector& invkappa); //Set params for all modes of orientation priors
float get_S0LR() const { return m_S0LR; }
void set_S0LR(const float S0) { m_S0LR=S0; }
float get_tauLR() const { return m_tauLR; }
void set_tauLR(const float tau) { m_tauLR=tau; }
void set_tauHR(const int n, const float tau) { m_HRvoxels[n].set_tau(tau); }
float get_likelihood_energy() const { return m_likelihood_en; }
float get_prior_energy() const { return m_prior_en; }
void initialise_energies();
bool propose_S0LR();
void accept_S0LR(){ m_S0LR_acc++; }
void reject_S0LR();
bool compute_S0LR_prior();
bool propose_tauLR();
void accept_tauLR(){ m_tauLR_acc++; }
void reject_tauLR();
bool compute_tauLR_prior();
void compute_prior();
void compute_likelihood();
void compute_posterior();
bool test_energy() const;
void restore_energies();
void restore_Prior_Posterior();
void update_proposals();
void jump(); //Single MCMC iteration with all parameters jumped
bool propose_meand();
void accept_meand(){ m_mean_d_acc++; }
void reject_meand();
bool compute_meand_prior();
bool propose_stdevd();
void accept_stdevd(){ m_stdev_d_acc++; }
void reject_stdevd();
bool compute_stdevd_prior();
void set_meand(const float meand) { m_mean_d=meand; }
void set_stdevd(const float stdevd) { m_stdev_d=stdevd; }
float get_meand() const{ return m_mean_d;}
float get_stdevd() const{ return m_stdev_d;}
bool propose_mean_fsum();
void accept_mean_fsum(){ m_mean_fsum_acc++; }
void reject_mean_fsum();
bool compute_mean_fsum_prior();
bool propose_stdev_fsum();
void accept_stdev_fsum(){ m_stdev_fsum_acc++; }
void reject_stdev_fsum();
bool compute_stdev_fsum_prior();
void set_mean_fsum(const float fsum) { m_mean_fsum=fsum; }
void set_stdev_fsum(const float stdev_fsum) { m_stdev_fsum=stdev_fsum; }
float get_mean_fsum() const{ return m_mean_fsum;}
float get_stdev_fsum() const{ return m_stdev_fsum;}
LRvoxel& operator=(const LRvoxel& rhs){
m_HRvoxels=rhs.m_HRvoxels; m_PModes=rhs.m_PModes;
m_tauLR=rhs.m_tauLR; m_tauLR_old=rhs.m_tauLR_old;
m_tauLR_prop=rhs.m_tauLR_prop;
m_tauLR_prior=rhs.m_tauLR_prior; m_tauLR_old_prior=rhs.m_tauLR_old_prior;
m_tauLR_acc=rhs.m_tauLR_acc; m_tauLR_rej=rhs.m_tauLR_rej;
m_S0LR=rhs.m_S0LR; m_S0LR_old=rhs.m_S0LR_old;
m_S0LR_prop=rhs.m_S0LR_prop;
m_S0LR_prior=rhs.m_S0LR_prior; m_S0LR_old_prior=rhs.m_S0LR_old_prior;
m_S0LR_acc=rhs.m_S0LR_acc; m_S0LR_rej=rhs.m_S0LR_rej;
m_Orient_hyp_prior=rhs.m_Orient_hyp_prior;
m_prior_en=rhs.m_prior_en; m_old_prior_en=rhs.m_old_prior_en;
m_likelihood_en=rhs.m_likelihood_en; m_old_likelihood_en=rhs.m_old_likelihood_en;
m_posterior_en=rhs.m_posterior_en; m_old_posterior_en=rhs.m_old_posterior_en;
m_logdataLR=rhs.m_logdataLR; m_logdataHR=rhs.m_logdataHR;
m_mean_d=rhs.m_mean_d; m_mean_d_old=rhs.m_mean_d_old;
m_mean_d_prop=rhs.m_mean_d_prop;
m_mean_d_prior=rhs.m_mean_d_prior; m_mean_d_old_prior=rhs.m_mean_d_old_prior;
m_mean_d_acc=rhs.m_mean_d_acc; m_mean_d_rej=rhs.m_mean_d_rej;
m_stdev_d=rhs.m_stdev_d; m_stdev_d_old=rhs.m_stdev_d_old;
m_stdev_d_prop=rhs.m_stdev_d_prop;
m_stdev_d_prior=rhs.m_stdev_d_prior; m_stdev_d_old_prior=rhs.m_stdev_d_old_prior;
m_stdev_d_acc=rhs.m_stdev_d_acc; m_stdev_d_rej=rhs.m_stdev_d_rej;
m_mean_fsum=rhs.m_mean_fsum; m_mean_fsum_old=rhs.m_mean_fsum_old;
m_mean_fsum_prop=rhs.m_mean_fsum_prop;
m_mean_fsum_prior=rhs.m_mean_fsum_prior; m_mean_fsum_old_prior=rhs.m_mean_fsum_old_prior;
m_mean_fsum_acc=rhs.m_mean_fsum_acc; m_mean_fsum_rej=rhs.m_mean_fsum_rej;
m_stdev_fsum=rhs.m_stdev_fsum; m_stdev_fsum_old=rhs.m_stdev_fsum_old;
m_stdev_fsum_prop=rhs.m_stdev_fsum_prop;
m_stdev_fsum_prior=rhs.m_stdev_fsum_prior; m_stdev_fsum_old_prior=rhs.m_stdev_fsum_old_prior;
m_stdev_fsum_acc=rhs.m_stdev_fsum_acc; m_stdev_fsum_rej=rhs.m_stdev_fsum_rej;
return *this;
}
};
}
#endif