indii/fmri/hemodynamic/FlowBalloonModel.hpp

00001 #ifndef INDII_FMRI_HEMODYNAMIC_FLOWBALLOONMODEL_HPP
00002 #define INDII_FMRI_HEMODYNAMIC_FLOWBALLOONMODEL_HPP
00003 
00004 #include "BalloonModel.hpp"
00005 
00006 #include "indii/ml/aux/vector.hpp"
00007 
00008 namespace indii {
00009   namespace fmri {
00010     namespace hemodynamic {
00011 
00012 /**
00013  * Balloon %model driven by blood flow.
00014  *
00015  * @author Lawrence Murray <lawrence@indii.org>
00016  * @version $Rev: 285 $
00017  * @date $Date: 2007-07-20 17:25:40 +0100 (Fri, 20 Jul 2007) $
00018  *
00019  * This class implements the Balloon Model described by @ref
00020  * Buxton1998 "Buxton et al. (1998)". This system models a venous
00021  * compartment as a balloon, described by a volume and deoxyhemoglobin
00022  * (dHb) content. These combine to produce the Blood Oxygenation Level
00023  * Dependent (BOLD) signal.
00024  *
00025  * The %model is driven by blood flow into the venous
00026  * compartment. This causes the compartment to expand like a balloon,
00027  * increasing the pressure exerted by it and consequently the blood
00028  * flow out of the compartment. Concurrently, oxygen extraction, and
00029  * therefore the rate of dHb production, is more efficient at slower
00030  * flow rates. These simple interactions simulate a biologically
00031  * plausible BOLD signal.
00032  *
00033  * @section FlowBalloonModel_details Details
00034  *
00035  * The state variables \f$q\f$, representing normalised dHb content,
00036  * and \f$v\f$, representing normalised venous volume, are updated
00037  * according to the system of differential equations given by @ref
00038  * Buxton1998 "Buxton et al. (1998)":
00039  *
00040  * @anchor diffsystem
00041  * \f{eqnarray*}
00042  *   \frac{dq}{dt} &=& \frac{1}{\tau_0}\left[
00043  *     f_{in}(t)\frac{E(t)}{E_0} -
00044  *     f_{out}(v)\frac{q}{v}
00045  *     \right] \\
00046  *   \frac{dv}{dt} &=& \frac{1}{\tau_0}\left[
00047  *     f_{in}(t) - f_{out}(v)
00048  *     \right]
00049  * \f}
00050  *
00051  * Other symbols represent biophysical parameters and functions of the
00052  * system, handled using indii::ml::ode::ParameterCollection and
00053  * indii::ml::ode::FunctionCollection, with default values given in
00054  * FlowBalloonModelDefaults.
00055  *
00056  * Singularities are handled using limits. See
00057  * FlowBalloonModelDefaults::DQDT.
00058  *
00059  * @section FlowBalloonModel_usage Usage
00060  *
00061  * The basic usage idiom is as follows. Firstly create an instance of
00062  * FlowBalloonModel and set up the initial state:
00063  *
00064  * @code
00065  * FlowBalloonModel bm;
00066  * indii::ml::aux::vector y(bm.suggestInitialState());
00067  * @endcode
00068  *
00069  * The %model may then be simulated by solving the differential system
00070  * using indii::ml::ode::AdaptiveRungeKutta:
00071  *
00072  * @code
00073  * indii::ml::ode::AdaptiveRungeKutta solver(&bm, y);
00074  * double end = 60.0;
00075  * double t = 0.0;
00076  *
00077  * while (t < end) {
00078  *   t = solver.step(end);
00079  * }
00080  * @endcode
00081  *
00082  * In order for the %model to do something interesting, however, you
00083  * will want to at least override the default FlowBalloonModel::F_IN
00084  * function with your own custom function that controls flow. The
00085  * following function, for example, generates a flow of 2.0 for 1 s,
00086  * followed by a constant flow of 1.0:
00087  *
00088  * @code
00089  * double F_IN(double t, const double y[], void* o) {
00090  *   if (t < 1.0) {
00091  *     return 2.0;
00092  *   } else {
00093  *     return 1.0;
00094  *   }
00095  * }
00096  * @endcode
00097  *
00098  * Note the signature of this function, described by
00099  * indii::ml::ode::f_t. The %model can be made to use this function by
00100  * calling setFunction() before the first call to step():
00101  *
00102  * @code
00103  * bm.setFunction(FlowBalloonModel::F_IN, F_IN);
00104  * @endcode
00105  *
00106  * Other biophysical parameters and functions may be customised using
00107  * the setParameter() and setFunction() methods inherited from
00108  * indii::ml::ode::ParameterCollection and
00109  * indii::ml::ode::FunctionCollection.
00110  *
00111  * Finally, you will want to actually retrieve the state of the %model
00112  * after each call to step() using getVariable() or getState(). For
00113  * example, modifying the loop above:
00114  *
00115  * @code
00116  * while (t < end) {
00117  *   t = solver.step(end);
00118  *
00119  *   std::cout << t << ',';
00120  *   std::cout << solver.getVariable(FlowBalloonModel::Q) << ',';
00121  *   std::cout << solver.getVariable(FlowBalloonModel::V) << std::endl;
00122  * }
00123  * @endcode
00124  *
00125  * or:
00126  *
00127  * @code
00128  * while (t < end) {
00129  *   t = solver.step(end);
00130  *   y = solver.getState();
00131  *
00132  *   std::cout << t << ',';
00133  *   std::cout << y(FlowBalloonModel::Q) << ',';
00134  *   std::cout << y(FlowBalloonModel::V) << std::endl;
00135  * }
00136  * @endcode
00137  *
00138  * The values of biophysical functions, which are time dependent, may
00139  * be retrieved using getFunction() if they are of interest also.
00140  */
00141 class FlowBalloonModel : public BalloonModel {
00142 public:
00143   /**
00144    * State variable indices.
00145    */
00146   enum StateVariable {
00147     /**
00148      * \f$q = \frac{Q(t)}{Q_0}\f$; normalised dHb content of venous
00149      * compartment at the current time.
00150      */
00151     Q,
00152 
00153     /**
00154      * \f$v = \frac{V(t)}{V_0}\f$; normalised volume of the venous
00155      * compartment at the current time.
00156      */
00157     V
00158   };
00159 
00160   /**
00161    * Parameter indices.
00162    */
00163   enum BiophysicalParameter {
00164     /**
00165      * \f$V_0\f$; volume of the venous compartment at rest.
00166      */
00167     V_0,
00168   
00169     /**
00170      * \f$E_0\f$; oxygen extraction rate of the venous compartment at
00171      * rest.
00172      */
00173     E_0,
00174 
00175     /**
00176      * \f$\tau_0 = \frac{V_0}{F_0}\f$; mean transit time through the
00177      * venous compartment at rest.
00178      */
00179     TAU_0,
00180 
00181     /**
00182      * \f$\alpha\f$; Grubb's exponent.
00183      */
00184     ALPHA
00185   };
00186 
00187   /**
00188    * Function indices.
00189    */
00190   enum BiophysicalFunction {
00191     /**
00192      * \f$f_{in}(t) = \frac{F_{in}(t)}{F_0}\f$; normalised flow into
00193      * the venous compartment.
00194      */
00195     F_IN,
00196 
00197     /**
00198      * \f$f_{out}(t) = \frac{F_{out}(t)}{F_0}\f$; normalised flow out
00199      * of the venous compartment.
00200      */
00201     F_OUT,
00202 
00203     /**
00204      * \f$E(t)\f$; oxygen extraction rate of the venous compartment.
00205      */
00206     E
00207   };
00208 
00209   /**
00210    * Create new %model with the default biophysical parameters and
00211    * functions defined in FlowBalloonModelDefaults.
00212    */
00213   FlowBalloonModel();
00214   
00215   /**
00216    * Destructor.
00217    */
00218   virtual ~FlowBalloonModel();
00219 
00220   virtual indii::ml::aux::vector suggestInitialState();
00221 
00222   /**
00223    * @see indii::ml::ode::DifferentialModel
00224    */
00225   virtual void calculateDerivatives(double t, const double y[], double dydt[]);
00226 
00227 private:
00228   /**
00229    * Number of state variables.
00230    */
00231   static const unsigned int DIMENSIONS = 2;
00232 
00233   /**
00234    * Number of parameters.
00235    */
00236   static const unsigned int NUM_PARAMETERS = 4;
00237 
00238   /**
00239    * Number of functions.
00240    */
00241   static const unsigned int NUM_FUNCTIONS = 3;
00242 
00243 };
00244   
00245     }
00246   }
00247 }
00248 
00249 #endif

Generated on Tue Oct 9 22:02:07 2007 for fmrii fMRI Modelling Library by  doxygen 1.5.2