TPCCLIB
Loading...
Searching...
No Matches
libtpcmodel.h File Reference

Header file for libtpcmodel. More...

#include "tpcclibConfig.h"
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <math.h>
#include <float.h>
#include <sys/time.h>
#include <time.h>
#include "libtpcmisc.h"

Go to the source code of this file.

Data Structures

struct  MERTWI
 
struct  bobyqa_data
 
struct  TGO_POINT
 

Macros

#define MAX_PARAMETERS   50
 
#define MAX_PARAMS   MAX_PARAMETERS
 
#define TPCCLIB_MERTWI_NN   312
 
#define TPCCLIB_MERTWI_A   UINT64_C(0xB5026F5AA96619E9)
 
#define MTGA_BEST_MIN_NR   5
 
#define DEFAULT_SAO2   0.97
 
#define DEFAULT_P50HB   3.6
 
#define DEFAULT_P50MB   0.319
 
#define DEFAULT_NHB   2.7
 
#define DEFAULT_CHB   150.0
 
#define DEFAULT_CMB   4.7
 

Typedefs

typedef double(* bobyqa_func) (int n, const double *x, void *func_data)
 

Enumerations

enum  bobyqa_result {
  BOBYQA_INVALID_ARGS = -1 , BOBYQA_OUT_OF_MEMORY = -2 , BOBYQA_ROUNDOFF_LIMITED = -3 , BOBYQA_FAIL = -4 ,
  BOBYQA_SUCCESS = 0 , BOBYQA_MINF_MAX_REACHED = 1 , BOBYQA_FTOL_REACHED = 2 , BOBYQA_XTOL_REACHED = 3 ,
  BOBYQA_MAXEVAL_REACHED = 4 , BOBYQA_RELFTOL_REACHED = 5 , BOBYQA_ABSFTOL_REACHED = 6
}
 
enum  linefit_method { PEARSON , PERP , LLSQWT , MEDIAN }
 
enum  linefit_range { PRESET , EXCLUDE_BEGIN , EXCLUDE_END }
 

Functions

uint32_t mertwiSeed32 (void)
 Make uint32_t seed for pseudorandom number generators.
 
uint64_t mertwiSeed64 (void)
 Make uint64_t seed for pseudorandom number generators.
 
void mertwiInit (MERTWI *mt)
 
void mertwiInitWithSeed64 (MERTWI *mt, uint64_t seed)
 Initialize the state vector mt[] inside data struct for Mersenne Twister MT19937 pseudorandom number generator using given seed.
 
void mertwiInitByArray64 (MERTWI *mt, uint64_t init_key[], uint64_t key_length)
 Initialize the state vector mt[] inside data struct for Mersenne Twister MT19937 pseudorandom number generator using given array.
 
uint64_t mertwiRandomInt64 (MERTWI *mt)
 Generate a random number on [0, 2^64-1]-interval using Mersenne Twister MT19937.
 
int64_t mertwiRandomInt63 (MERTWI *mt)
 Generate a random number on [0, 2^63-1]-interval using Mersenne Twister MT19937.
 
double mertwiRandomDouble1 (MERTWI *mt)
 Generate a 64-bit double precision floating point pseudorandom number in the range of [0,1] with uniform distribution using Mersenne Twister MT19937.
 
double mertwiRandomDouble2 (MERTWI *mt)
 Generate a 64-bit double precision floating point pseudorandom number in the range of [0,1) with uniform distribution using Mersenne Twister MT19937.
 
double mertwiRandomDouble3 (MERTWI *mt)
 Generate a 64-bit double precision floating point pseudorandom number in the range of (0,1) with uniform distribution using Mersenne Twister MT19937.
 
double aicSS (double ss, const int n, const int k)
 
int parFreeNr (const int n, double *pLower, double *pUpper)
 Calculate the number of free parameters.
 
int aicWeights (double *aic, double *w, int n)
 
double aicWeightedAvg (double *w, double *p, int n)
 
double aicModel (double *w, int n)
 
bobyqa_result bobyqb (bobyqa_data *bdata)
 
bobyqa_result bobyqa (int n, int npt, double *x, const double *xl, const double *xu, const double *dx, const double rhoend, double xtol_rel, double minf_max, double ftol_rel, double ftol_abs, int maxeval, int *nevals, double *minf, double(*f)(int n, double *x, void *objf_data), void *objf_data, double *working_space, int verbose)
 
int bobyqa_minimize_single_parameter (bobyqa_data *bdata)
 
char * bobyqa_rc (bobyqa_result rc)
 
int fixed_params (int n, const double *lower, const double *upper, const double *delta)
 
int bobyqa_working_memory_size (int n, int fitted_n, int npt, bobyqa_data *bdata)
 
bobyqa_result bobyqa_set_memory (int n, int fitted_n, int npt, bobyqa_data *bdata, double *wm)
 
bobyqa_result bobyqa_free_memory (bobyqa_data *bdata)
 
bobyqa_result bobyqa_reset_memory (bobyqa_data *bdata)
 
void bobyqa_print (bobyqa_data *bdata, int sw, FILE *fp)
 
double bobyqa_x_funcval (bobyqa_data *bdata, double *x)
 
void bobyqa_xfull (bobyqa_data *bdata)
 
bobyqa_result bobyqa_set_optimization (int full_n, double *x, const double *dx, const double *xl, const double *xu, const double rhoend, double xtol_rel, double minf_max, double ftol_rel, double ftol_abs, int maxeval, double(*f)(int n, double *x, void *objf_data), void *objf_data, int verbose, bobyqa_data *bdata)
 
int bootstrap (int iterNr, double *cLim1, double *cLim2, double *SD, double *parameter, double *lowlim, double *uplim, int frameNr, double *origTac, double *fitTac, double *bsTAC, int parNr, double *weight, double(*objf)(int, double *, void *), char *status, int verbose)
 
int bvls (int key, const int m, const int n, double *a, double *b, double *bl, double *bu, double *x, double *w, double *act, double *zz, int *istate, int *iter, int verbose)
 Bounded-value least-squares method to solve the linear problem A x ~ b , subject to limit1 <= x <= limit2.
 
int llsqWght (int N, int M, double **A, double *a, double *b, double *weight)
 
int llsqWghtSquared (int N, int M, double **A, double *a, double *b, double *weight)
 
int modelCheckParameters (int par_nr, double *lower_p, double *upper_p, double *test_p, double *accept_p, double *penalty)
 
int modelCheckLimits (int par_nr, double *lower_p, double *upper_p, double *test_p)
 
int fitExpDecayNNLS (double *x, double *y, int n, double fittime, double kmin, double kmax, int pnr, double *a, double *k, int *fnr, int verbose)
 Estimate initial values for sum of exponentials to be fitted on decaying x,y-data.
 
unsigned int drandSeed (short int seed)
 Make and optionally set the seed for rand(), drand, drandRange, and drandGaussian().
 
double gaussdev ()
 
double gaussdev2 ()
 
void init_gaussdev ()
 
double drand ()
 
int rand_range (int nr, double *d, double low, double up, int type)
 
double householder_transform (double *v, int N)
 
int householder_hm (double tau, double *vector, double **matrix, int rowNr, int columnNr)
 
int householder_hv (double tau, int size, double *v, double *w)
 
double householder_norm (double *v, int size)
 
int interpolate (double *x, double *y, int nr, double *newx, double *newy, double *newyi, double *newyii, int newnr)
 Linear interpolation and integration.
 
int finterpolate (float *x, float *y, int nr, float *newx, float *newy, float *newyi, float *newyii, int newnr)
 float version of interpolate().
 
int integrate (double *x, double *y, int nr, double *yi)
 
int fintegrate (float *x, float *y, int nr, float *yi)
 float version of integrate().
 
int petintegrate (double *x1, double *x2, double *y, int nr, double *newyi, double *newyii)
 
int fpetintegrate (float *x1, float *x2, float *y, int nr, float *newyi, float *newyii)
 Calculates integrals of PET data at frame end times. Float version of petintegrate().
 
int interpolate4pet (double *x, double *y, int nr, double *newx1, double *newx2, double *newy, double *newyi, double *newyii, int newnr)
 Interpolate and integrate TAC to PET frames.
 
int finterpolate4pet (float *x, float *y, int nr, float *newx1, float *newx2, float *newy, float *newyi, float *newyii, int newnr)
 Interpolate and integrate TAC to PET frames. Float version of interpolate4pet().
 
int petintegral (double *x1, double *x2, double *y, int nr, double *ie, double *iie)
 Integrate PET TAC data to frame mid times.
 
int fpetintegral (float *x1, float *x2, float *y, int nr, float *ie, float *iie)
 Integrate PET TAC data to frame mid times. Float version of petintegral().
 
int petintegrate2fe (double *x1, double *x2, double *y, int nr, double *e, double *ie, double *iie)
 Integrate PET TAC data to frame end times.
 
int fpetintegrate2fe (float *x1, float *x2, float *y, int nr, float *e, float *ie, float *iie)
 Integrate PET TAC data to frame end times. Float version of petintegrate2fe().
 
int llsqwt (double *x, double *y, int n, double *wx, double *wy, double tol, double *w, double *ic, double *slope, double *nwss, double *sic, double *sslope, double *cx, double *cy)
 
int best_llsqwt (double *x, double *y, double *wx, double *wy, int nr, int min_nr, int mode, double *slope, double *ic, double *nwss, double *sslope, double *sic, double *cx, double *cy, int *bnr)
 
int llsqperp (double *x, double *y, int nr, double *slope, double *ic, double *ssd)
 
int llsqperp3 (double *x, double *y, int nr, double *slope, double *ic, double *ssd)
 
int quadratic (double a, double b, double c, double *m1, double *m2)
 
int medianline (double *x, double *y, int nr, double *slope, double *ic)
 
double least_median_of_squares (double *data, int n)
 Fit a constant (horisontal straight line) to the data by minimising the median of squared residuals.
 
int least_trimmed_square (double data[], long int n, double *mean, double *variance)
 
double d_kth_smallest (double *data, int n, int k)
 
double dmedian (double *data, int n)
 
double dmean (double *data, int n, double *sd)
 
double dmean_nan (double *data, int n, double *sd, int *vn)
 
double mEstim (double *data, int nr, int iterNr, double cutoff)
 
double huber (double x, double b)
 
int patlak_data (int data_nr, double *i, double *ii, double *c, double *x, double *y)
 
int logan_data (int data_nr, double *i, double *ii, double *c, double *ci, double k2, double *x, double *y)
 
int mtga_best_perp (double *x, double *y, int nr, double *slope, double *ic, double *ssd, int *fnr)
 
int nnls (double **a, int m, int n, double *b, double *x, double *rnorm, double *w, double *zz, int *index)
 
int nnlsWght (int N, int M, double **A, double *b, double *weight)
 
int nnlsWghtSquared (int N, int M, double **A, double *b, double *sweight)
 
double ndtr (double a)
 
double normal_pvalue_2 (double x)
 
double normal_pvalue_1 (double x)
 
int pearson (double *x, double *y, int nr, double *k, double *kSD, double *b, double *bSD, double *r, double *ySD)
 
int pearson2 (double *x, double *y, char *is, int nr, double *k, double *kSD, double *b, double *bSD, double *r, double *ySD)
 
int pearson3 (double *x, double *y, int nr, double *k, double *kSD, double *b, double *bSD, double *r, double *ySD)
 
int pearson4 (double *x, double *y, int nr, double start, double end, double *k, double *kSD, double *b, double *bSD, double *r, double *ySD)
 Calculate slope and intercept of a line and Pearson's correlation coefficient.
 
int best_pearson (double *x, double *y, int nr, int min_nr, int *first, int *last, double *k, double *kSD, double *b, double *bSD, double *r, double *ySD)
 
int mean (double *x, double *y, int nr, double *xmean, double *xsd, double *ymean, double *ysd)
 
int regr_line (double *x, double *y, int n, double *m, double *c)
 
int highest_slope (double *x, double *y, int n, int slope_n, double *m, double *c, double *xi, double *xh)
 
int highest_slope_after (double *x, double *y, int n, int slope_n, double x_start, double *m, double *c, double *xi, double *xh)
 
int powell (double *p, double *delta, int parNr, double ftol, int *iterNr, double *fret, double(*_fun)(int, double *, void *), void *fundata, int verbose)
 
int qrLSQ (double **mat, double *rhs, double *sol, const unsigned int rows, const unsigned int cols, double *r2)
 QR least-squares solving routine.
 
int qr (double **A, int m, int n, double *B, double *X, double *rnorm, double *tau, double *res, double **wws, double *ws)
 
int qr_decomp (double **a, int M, int N, double *tau, double **cchain, double *chain)
 
int qr_solve (double **QR, int M, int N, double *tau, double *b, double *x, double *residual, double *resNorm, double **cchain, double *chain)
 
int qr_weight (int N, int M, double **A, double *b, double *weight, double *ws)
 
int qrLH (const unsigned int m, const unsigned int n, double *a, double *b, double *x, double *r2)
 Solve over-determined least-squares problem A x ~ b using successive Householder rotations.
 
int runs_test (double *data1, double *data2, int N, double alpha, double *p)
 
int residuals (double *d1, double *d2, int Nr, int *Rnr, int *Nminus, int *Nplus)
 
int mrl_between_tacs (double y1[], double y2[], int n)
 
void random_shuffle (int *array, int n)
 
void randperm (int *array, int n, int a)
 
double simplex (double(*_fun)(double *), int parNr, double *par, double *delta, double maxerr, int maxiter, int verbose)
 
int simC3s (double *t, double *ca, int nr, double k1, double k2, double k3, double k4, double k5, double k6, double *ct, double *cta, double *ctb, double *ctc)
 
int simC3p (double *t, double *ca, int nr, double k1, double k2, double k3, double k4, double k5, double k6, double *ct, double *cta, double *ctb, double *ctc)
 
int simC3vs (double *t, double *ca, double *cb, int nr, double k1, double k2, double k3, double k4, double k5, double k6, double f, double vb, double fa, double *cpet, double *cta, double *ctb, double *ctc, double *ctab, double *ctvb)
 
int simC3vp (double *t, double *ca, double *cb, int nr, double k1, double k2, double k3, double k4, double k5, double k6, double f, double vb, double fa, double *cpet, double *cta, double *ctb, double *ctc, double *ctab, double *ctvb)
 
int simC2l (double *t, double *ca, int nr, double k1, double k2, double k3, double kLoss, double *ct, double *cta, double *ctb)
 
int simC2vl (double *t, double *ca, double *cb, int nr, double k1, double k2, double k3, double kL, double f, double vb, double fa, double *cpet, double *cta, double *ctb, double *ctab, double *ctvb)
 
int simC3vpKLoss (double *t, double *ca, double *cb, int nr, double k1, double k2, double k3, double k4, double k5, double k6, double kLoss, double f, double vb, double fa, double *cpet, double *cta, double *ctb, double *ctc, double *ctab, double *ctvb)
 
int simRTCM (double *t, double *cr, int nr, double R1, double k2, double k3, double k4, double *ct, double *cta, double *ctb)
 
int simSRTM (double *t, double *cr, int nr, double R1, double k2, double BP, double *ct)
 
int simTRTM (double *t, double *cr, int nr, double R1, double k2, double k3, double *ct)
 
int simHuangmet (double *t, double *ctot, int nr, double k01, double k12, double k21, double k03, double k34, double k43, double *c0, double *c1, double *c3)
 
int simTPCMOD0009c (double *t, double *ctot, int nr, double km, double k1m, double k2m, double k3m, double k4m, double *ca, double *cm)
 
int simMBF (double *t, double *ci, int nr, double k1, double k2, double Vfit, double *ct)
 
int simC1 (double *t, double *ca, int nr, double k1, double k2, double *ct)
 
int simC3DIvs (double *t, double *ca1, double *ca2, double *cb, int nr, double k1, double k2, double k3, double k4, double k5, double k6, double k1b, double k2b, double f, double vb, double fa, double *scpet, double *sct1, double *sct2, double *sct3, double *sct1b, double *sctab, double *sctvb)
 
int simC4DIvp (double *t, double *ca1, double *ca2, double *cb, int nr, double k1, double k2, double k3, double k4, double k5, double k6, double k7, double km, double k1b, double k2b, double f, double vb, double fa, double *scpet, double *sct1, double *sct2, double *sct3, double *sct1b, double *sctab, double *sctvb, int verbose)
 
int simC4DIvs (double *t, double *ca1, double *ca2, double *cb, int nr, double k1, double k2, double k3, double k4, double k5, double k6, double k7, double km, double k1b, double k2b, double f, double vb, double fa, double *scpet, double *sct1, double *sct2, double *sct3, double *sct1b, double *sctab, double *sctvb, int verbose)
 
int simDispersion (double *x, double *y, int n, double tau1, double tau2, double *tmp)
 
int simOxygen (double *t, double *ca1, double *ca2, double *ca1i, double *ca2i, const int n, const double k1a, const double k2a, const double km, const double k1b, const double k2b, const double vb, const double fa, double *scpet, double *sct1, double *sct2, double *sctab, double *sctvb1, double *sctvb2, double *scvb1, double *scvb2, const int verbose)
 
double mo2k1k2 (const double OER, const double SaO2, const double p50Hb, const double p50Mb, const double nHb, const double cHb, const double cMb, const int verbose)
 Calculates K1/k2 ratio for [O-15]O2 in muscle, based on OER.
 
double mo2pO2 (const double OER, const double K1k2, const double SaO2, const double p50Mb, const double cHb, const double cMb, const int verbose)
 
int tgo (double *lowlim, double *uplim, double(*objf)(int, double *, void *), void *objfData, int dim, int neighNr, double *fmin, double *gmin, int samNr, int tgoNr, int verbose)
 
void tgoRandomParameters (TGO_POINT *p, int parNr, int sNr, double *low, double *up)
 
void tgoRandomParametersST (TGO_POINT *p, int parNr, int sNr, double *low, double *up)
 
int nlopt1D (double(*_fun)(double, void *), void *_fundata, double x, double xl, double xu, double delta, double tol, const int maxeval, double *nx, double *nf, int verbose)
 

Variables

long int GAUSSDEV_SEED
 
int TGO_SQUARED_TRANSF
 
int TGO_LOCAL_INSIDE
 
int TGO_LOCAL_OPT
 

Detailed Description

Header file for libtpcmodel.

Author
Vesa Oikonen

Definition in file libtpcmodel.h.

Macro Definition Documentation

◆ DEFAULT_CHB

#define DEFAULT_CHB   150.0

Hemoglobin concentration in blood (mg/g)

Definition at line 962 of file libtpcmodel.h.

◆ DEFAULT_CMB

#define DEFAULT_CMB   4.7

Myoglobin concentration in muscle (mg/g)

Definition at line 964 of file libtpcmodel.h.

◆ DEFAULT_NHB

#define DEFAULT_NHB   2.7

Hill coefficient n for hemoglobin

Definition at line 960 of file libtpcmodel.h.

◆ DEFAULT_P50HB

#define DEFAULT_P50HB   3.6

Half-saturation pressure p50 (kPa) for hemoglobin

Definition at line 956 of file libtpcmodel.h.

◆ DEFAULT_P50MB

#define DEFAULT_P50MB   0.319

Half-saturation pressure p50 (kPa) p50 for myoglobin

Definition at line 958 of file libtpcmodel.h.

◆ DEFAULT_SAO2

#define DEFAULT_SAO2   0.97

Arterial oxygen saturation fraction

Definition at line 954 of file libtpcmodel.h.

◆ MAX_PARAMETERS

#define MAX_PARAMETERS   50

Max nr of parameters

Definition at line 31 of file libtpcmodel.h.

Referenced by powell().

◆ MAX_PARAMS

#define MAX_PARAMS   MAX_PARAMETERS

Max nr of parameters

Definition at line 35 of file libtpcmodel.h.

◆ MTGA_BEST_MIN_NR

#define MTGA_BEST_MIN_NR   5

Min nr of points in MTGA line fit

Definition at line 664 of file libtpcmodel.h.

Referenced by img_logan(), img_patlak(), and mtga_best_perp().

◆ TPCCLIB_MERTWI_A

#define TPCCLIB_MERTWI_A   UINT64_C(0xB5026F5AA96619E9)

Mersenne Twister required constant

Definition at line 43 of file libtpcmodel.h.

Referenced by mertwiInit(), and mertwiRandomInt64().

◆ TPCCLIB_MERTWI_NN

#define TPCCLIB_MERTWI_NN   312

Mersenne Twister state vector length

Definition at line 41 of file libtpcmodel.h.

Referenced by mertwiInit().

Typedef Documentation

◆ bobyqa_func

typedef double(* bobyqa_func) (int n, const double *x, void *func_data)

BOBYQA objective function

Definition at line 92 of file libtpcmodel.h.

Enumeration Type Documentation

◆ bobyqa_result

BOBYQA return codes

Definition at line 77 of file libtpcmodel.h.

77 {
78 BOBYQA_INVALID_ARGS = -1,
79 BOBYQA_OUT_OF_MEMORY = -2,
80 BOBYQA_ROUNDOFF_LIMITED = -3,
81 BOBYQA_FAIL = -4, /* generic fail code */
82 BOBYQA_SUCCESS = 0, /* generic success code */
83 BOBYQA_MINF_MAX_REACHED = 1,
84 BOBYQA_FTOL_REACHED = 2,
85 BOBYQA_XTOL_REACHED = 3,
86 BOBYQA_MAXEVAL_REACHED = 4,
87 BOBYQA_RELFTOL_REACHED = 5,
88 BOBYQA_ABSFTOL_REACHED = 6
bobyqa_result
Definition libtpcmodel.h:77

◆ linefit_method

MTGA line fit method

Enumerator
PEARSON 

Traditional line fit, same as Pearson's correlation coefficient

PERP 

Simple non-iterative perpendicular line fitting (Varga & Szabo, 2002)

LLSQWT 

Iterative method for linear least-squares fit with errors in both coordinates (York 1966, Lybanon 1984, Reed 1992).

MEDIAN 

Median-based distribution-free estimation of slope and intercept (Siegel, 1982); note that this is not LMS.

Definition at line 667 of file libtpcmodel.h.

667 {
668
669 PEARSON,
670
671 PERP,
673
674 LLSQWT,
676
677 MEDIAN
linefit_method
@ LLSQWT
@ PEARSON
@ PERP
@ MEDIAN

◆ linefit_range

MTGA line fit range

Definition at line 681 of file libtpcmodel.h.

681 {
682 PRESET, EXCLUDE_BEGIN, EXCLUDE_END
linefit_range

Function Documentation

◆ aicModel()

double aicModel ( double * w,
int n )
extern

Calculates a value describing the relative goodness of models, based on an array of model weights.

See also
aicSS, aicWeightedAvg, aicWeights
Returns
Returns the weighted average of model number.
Parameters
wArray of weights
nLength of array

Definition at line 132 of file aic.c.

137 {
138 int i;
139 double avg;
140
141 if(n<1 || w==NULL) avg=0.0;
142 else for(i=0, avg=0.0; i<n; i++) avg+=w[i]*(double)(i+1);
143 return(avg);
144}

◆ aicSS()

double aicSS ( double ss,
const int n,
const int k )
extern

Computation of AICc in the special case of sum-of-squares optimization from the SS, nr of fitted points and nr of fitted parameters.

If variance is different between the data points, weighted SS must be given.

See also
parFreeNr, dftWSampleNr, aicWeights, aicWeightedAvg
Returns
Returns the AIC value.
Parameters
ssSum-of-Squares of the fit
nSample size, i.e. nr of fitted data points
kNumber of fitted model parameters; AICc calculation is valid only when (n-k)>1.

Definition at line 20 of file aic.c.

27 {
28 if(!(ss>=0.0) || n<1 || k<0 || (n-k)<2) return(nan(""));
29
30 double aic=0.0, bias_adj, css;
31 int dr, dv;
32
33 dr=n-k-1; dv=2*k*(k+1);
34 if(dr>0) bias_adj=((double)dv)/((double)dr); else bias_adj=0.0;
35 if(ss<1.0e-50) css=1.0e-50; else css=ss; /* Because log(0) is an error */
36 if(n>0) aic= n*log(css/(double)n) + 2.0*(double)k + bias_adj;
37 return(aic);
38}

Referenced by imgNoiseTemplate().

◆ aicWeightedAvg()

double aicWeightedAvg ( double * w,
double * p,
int n )
extern

Computation of the Akaike weighted model parameter average. Requires arrays of AIC weight values, and corresponding parameter values.

See also
aicSS, aicModel, aicWeights
Returns
Returns the weighted average.
Parameters
wArray of weights
pArray of parameters
nLengths of arrays

Definition at line 108 of file aic.c.

115 {
116 int i;
117 double avg;
118
119 /* Check data */
120 if(n<1 || w==NULL || p==NULL) return(1);
121 for(i=0, avg=0.0; i<n; i++) avg+=w[i]*p[i];
122 return(avg);
123}

◆ aicWeights()

int aicWeights ( double * aic,
double * w,
int n )
extern

Computation of the Akaike weights for model averaging. Requires an array of AIC values, and an output array for weights.

See also
aicSS, aicWeightedAvg, aicModel
Returns
Returns 0, if OK.
Parameters
aicArray of AICs
wArray of weights (output)
nLengths of arrays

Definition at line 74 of file aic.c.

81 {
82 int i, mini;
83 double minaic, sume;
84
85 /* Check data */
86 if(n<1 || aic==NULL || w==NULL) return(1);
87 if(n==1) {w[0]=1.0; return(0);}
88 /* Find out which model gave the smallest AIC */
89 mini=0; for(i=1; i<n; i++) if(aic[i]<aic[mini]) mini=i;
90 minaic=aic[mini];
91 /* Compute relative weights for each model */
92 for(i=0, sume=0.0; i<n; i++) {
93 w[i]=exp(-0.5*(aic[i]-minaic));
94 sume+=w[i];
95 }
96 if(sume==0.0) return(2);
97 for(i=0; i<n; i++) w[i]/=sume;
98 return(0);
99}

◆ best_llsqwt()

int best_llsqwt ( double * x,
double * y,
double * wx,
double * wy,
int nr,
int min_nr,
int mode,
double * slope,
double * ic,
double * nwss,
double * sslope,
double * sic,
double * cx,
double * cy,
int * bnr )
extern

Finds the best least-squares line to (x,y)-data, leaving points out either from the beginning (mode=0) or from the end (mode=1).

See also
llsqwt, llsqperp, medianline
Returns
Returns 0, if ok.
Parameters
xPlot x axis values.
yPlot y axis values.
wxWeighting factors for x.
wyWeighting factors for y.
nrNr of plot data points.
min_nrMin nr of points to use in the fit; must be >=4.
modeLeave out points from beginning (0) or from end (1).
slopeSlope is returned in here.
icY axis intercept is returned in here.
nwsssqrt(WSS)/wsum is returned here.
sslopeExpected sd of slope at calculated points.
sicExpected sd of intercept at calculated points.
cxCalculated x data points.
cyCalculated y data points.
bnrNumber of points in the best fit (incl data with w=0).

Definition at line 294 of file llsqwt.c.

325 {
326 int from, to, ret, from_min, to_min;
327 double *w, lic, lslope, lnwss=1.0E+100, nwss_min=1.0E+100;
328
329 /* Check the data */
330 if(x==NULL || y==NULL || nr<min_nr || nr<2) return(1);
331 /* Check parameters */
332 if(min_nr<4 || (mode!=0 && mode!=1)) return(2);
333
334 /* Make room for work vector */
335 w=(double*)malloc(nr*sizeof(double)); if(w==NULL) return(3);
336
337 /* Search the plot range that gives the best nwss */
338 nwss_min=9.99E+99; from_min=to_min=-1;
339 if(mode==0) { /* Leave out plot data from the beginning */
340 for(from=0, to=nr-1; from<nr-min_nr; from++) {
341 ret=llsqwt(x+from, y+from, (to-from)+1, wx+from, wy+from, 1.0E-10, w,
342 &lic, &lslope, &lnwss, NULL, NULL, NULL, NULL);
343 /*lnwss/=(double)((to-from)+1);*/
344 if(0) printf(" range: %d-%d ; nwss=%g ; min=%g ; ret=%d\n", from, to, lnwss, nwss_min, ret);
345 if(ret==0 && lnwss<nwss_min) {nwss_min=lnwss; from_min=from; to_min=to;}
346 }
347 } else { /* Leave out plot data from the end */
348 for(from=0, to=min_nr-1; to<nr; to++) {
349 ret=llsqwt(x+from, y+from, (to-from)+1, wx+from, wy+from, 1.0E-10, w,
350 &lic, &lslope, &lnwss, NULL, NULL, NULL, NULL);
351 /*lnwss/=(double)((to-from)+1);*/
352 if(0) printf(" range: %d-%d ; nwss=%g ; min=%g ; ret=%d\n", from, to, lnwss, nwss_min, ret);
353 if(ret==0 && lnwss<nwss_min) {nwss_min=lnwss; from_min=from; to_min=to;}
354 }
355 }
356 if(from_min<0) {free(w); return(4);}
357
358 /* Run llsqwt() again with that range, now with better resolution */
359 /* and this time compute also SD's */
360 from=from_min; to=to_min;
361 ret=llsqwt(x+from, y+from, (to-from)+1, wx+from, wy+from, 1.0E-15, w,
362 ic, slope, nwss, sic, sslope, cx+from, cy+from);
363 free(w);
364 if(ret) return(5);
365 *bnr=(to-from)+1;
366
367 return(0);
368}
int llsqwt(double *x, double *y, int n, double *wx, double *wy, double tol, double *w, double *ic, double *slope, double *nwss, double *sic, double *sslope, double *cx, double *cy)
Definition llsqwt.c:48

◆ best_pearson()

int best_pearson ( double * x,
double * y,
int nr,
int min_nr,
int * first,
int * last,
double * k,
double * kSD,
double * b,
double * bSD,
double * r,
double * ySD )
extern

Find the best linear fit to double data (x[], y[]) with nr points.

Data may contain NaN's, which are not used.

See also
highest_slope, regr_line, pearson
Returns
Returns the nr of points actually used, or 0, in case of error.
Parameters
xData x values
yData y values
nrNumber of data sample values
min_nrMinimum nr of data points to use
firstIndex [0..last-2] of the first point to use initially, and after fitting
lastIndex [first+1..nr-1] of the last point to use initially, and after fitting
kslope
kSDS.D. of slope
by axis intercept
bSDS.D. of y axis intercept
rPearson's correlation coefficient, r
ySDResidual variance of y values

Definition at line 252 of file pearson.c.

277 {
278 int i, n, m, x1, x2, b1, b2, bm;
279 double *nx, *ny;
280 double tk, tkSD, tb, tbSD, tr, tySD;
281
282
283 if(0) {
284 fprintf(stdout, "best_pearson(x, y, %d, %d, %d, %d, k, kSD, b, bSD, r, ySD)\n",
285 nr, min_nr, *first, *last);
286 fflush(stdout);
287 }
288 /* Remove NaN's and those outside range first-last */
289 /* Allocate memory for new data pointers */
290 nx=(double*)calloc(nr, sizeof(double)); if(nx==NULL) return 0;
291 ny=(double*)calloc(nr, sizeof(double)); if(ny==NULL) {free((char*)nx); return 0;}
292 /* Copy data to pointers */
293 if(*last>nr-1) *last=nr-1;
294 if(*first<0) *first=0;
295 for(i=*first, n=0; i<=*last; i++)
296 if(!isnan(x[i]) && !isnan(y[i])) {nx[n]=x[i]; ny[n]=y[i]; n++;}
297
298 /* Check that we have enough points */
299 if(n<2 || n<min_nr) {free((char*)nx); free((char*)ny); return 0;}
300 if(n==min_nr) {
301 i=pearson(nx, ny, n, k, kSD, b, bSD, r, ySD);
302 free((char*)nx); free((char*)ny);
303 if(i) return 0; else return n;
304 }
305
306 /* OK, let's start */
307 *k=*kSD=*b=*bSD=*r=*ySD=0.; b1=b2=bm=0;
308 for(x1=0, m=n; n-x1>min_nr; x1++) {
309 /*printf("I x1=%i x2=%i m=%i n=%i\n", x1, x2, m, n);*/
310 for(x2=n-1, m=x2-x1+1; m>=min_nr; x2--, m--) {
311 if(pearson(nx+x1, ny+x1, m, &tk, &tkSD, &tb, &tbSD, &tr, &tySD))
312 continue;
313 if((tr>*r) ||
314 (tr==*r && m>bm) ||
315 (tr==*r && m==bm && x1>b1) ||
316 (tr==*r && m==bm && x1==b1 && tk>*k) ) {
317 bm=m; b1=x1; b2=x2;
318 *k=tk; *kSD=tkSD; *b=tb; *bSD=tbSD; *r=tr; *ySD=tySD;
319 }
320 /*printf("Fit range: %2i-%2i ; best fit: %2i-%2i\n", x1, x2, b1, b2);*/
321 }
322 }
323
324 /* Set first&last */
325 for(i=*first; i<=*last; i++)
326 if(x[i]==nx[b1] && y[i]==ny[b1]) {*first=i; break;}
327 for(i=*last; i>=*first; i--)
328 if(x[i]==nx[b2] && y[i]==ny[b2]) {*last=i; break;}
329 /*printf("FIRST=%i LAST=%i\n", *first, *last);*/
330
331 free((char*)nx); free((char*)ny);
332 return bm;
333}
int pearson(double *x, double *y, int nr, double *k, double *kSD, double *b, double *bSD, double *r, double *ySD)
Definition pearson.c:14

◆ bobyqa()

bobyqa_result bobyqa ( int n,
int npt,
double * x,
const double * xl,
const double * xu,
const double * dx,
const double rhoend,
double xtol_rel,
double minf_max,
double ftol_rel,
double ftol_abs,
int maxeval,
int * nevals,
double * minf,
double(* )(int n, double *x, void *objf_data),
void * objf_data,
double * working_space,
int verbose )
extern

BOBYQA is a derivative-free optimization code with constraints. This function interface is close to the one published by Powell.

Returns
Returns <0 in case of n error, >=0 when successful.
See also
simplex, powell, tgo, nlopt1D
Parameters
nN must be set to the number of variables (and length of arrays below)
nptNPT is the number of interpolation conditions. Its value must be in the interval [N+2,(N+1)(N+2)/2]. Choices that exceed 2*N+1 are not recommended. If set to zero, then bobyqa uses 2*N+1 as default. However, if very high precision is required, relatively high npt seems to be needed.
xInitial values of the variables must be set in X(1),X(2),...,X(N). They will be changed to the values that give the least calculated F.
xlLower bounds for X[]: For I=1,2,...,N, XL(I) and XU(I) must provide the lower and upper bounds, respectively, on X(I). The construction of quadratic models requires XL(I) to be strictly less than XU(I) for each I. Further, the contribution to a model from changes to the I-th variable is damaged severely by rounding errors if XU(I)-XL(I) is too small. If xl[i]==xu[i]==x[i], then parameter x[i] is fixed to x[i] and left out of actual bobyqa procedure; parameter(s) can also be fixed by setting dx[i]=0.
xuUpper bounds for X[]: For I=1,2,...,N, XL(I) and XU(I) must provide the lower and upper bounds, respectively, on X(I). The construction of quadratic models requires XL(I) to be strictly less than XU(I) for each I. Further, the contribution to a model from changes to the I-th variable is damaged severely by rounding errors if XU(I)-XL(I) is too small. If xl[i]==xu[i]==x[i], then parameter x[i] is fixed to x[i] and left out of actual bobyqa procedure; parameter(s) can also be fixed by setting dx[i]=0.
dxInitial step sizes. dx should be set to 1/10 of probable distance from initial guess where the final solution could be; set dx to zero for those parameters that are to be fixed to their initial value. Too high values may lead to error.
rhoendRhoend must be set to the final value of a trust region radius, as a (positive) fraction of dx values given above, for example 1.0E-06. Smaller value adds precision and increases calculation time. Enter <=0 to use default value, calculated using xtol_rel.
xtol_relRelative X tolerance
minf_maxStopping rule: maximal allowed function value; when reached, stops.
ftol_relStopping rule: relative tolerance to function value
ftol_absStopping rule: absolute tolerance to function value
maxevalStopping rule: max nr of function evaluations
nevalsNumber of function evaluations; this function will initialize this to zero, and in the end returns the number. Enter NULL if not needed.
minfPointer where minimized function value will be written
fObjective function has to be provided by the user. It must set F to the value of the objective function for the current values of the variables X(1),X(2),...,X(N), which are generated automatically in a way that satisfies the bounds given in XL and XU.
objf_dataPointer to data that is carried over to the function. It is not needed or used by bobyqa. Enter NULL if not needed.
working_spaceThe array W will be used for working space. Its length can be calculated using function bobyqa_working_memory_size(). Enter NULL to leave allocating to this function.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout

Definition at line 40 of file bobyqa.c.

111 {
112 int i, j;
113 int fixed_n, fitted_n;
114 bobyqa_data bdata;
115 bobyqa_result ret;
116
117
118 if(verbose>0) printf("in bobyqa()\n");
119 if(verbose>4) {
120 printf("original dx={%g", dx[0]);
121 for(j=1; j<n; j++) printf(", %g", dx[j]);
122 printf("}\n");
123 }
124
125 /* Check if any of parameters is fixed:
126 Only free parameters are given to Bobyqa for fitting, therefore
127 the number is needed in allocating and setting up memory.
128 BOBYQA requires that at least two parameters are fitted, but later
129 a simple 1-D method is used instead when necessary */
130 fixed_n=fixed_params(n, xl, xu, dx);
131 fitted_n=n-fixed_n;
132 if(verbose>1) {
133 printf("%d parameter(s) are fixed.\n", fixed_n); fflush(stdout);
134 }
135 if(fitted_n<1) {
136 if(verbose>0) fprintf(stderr, "Error: no free parameters.\n");
137 return BOBYQA_INVALID_ARGS;
138 }
139 if(fitted_n==1 && verbose>0)
140 fprintf(stderr, "Warning: only one free parameter.\n");
141
142 /* Set npt, if user did not do that */
143 if(npt<=0) npt=2*fitted_n+1;
144 /* Verify that NPT is in the required interval */
145 if(npt<fitted_n+2 || npt>(fitted_n+2)*(fitted_n+1)/2) {
146 if(verbose>0) {
147 printf("npt:=%d\n", npt);
148 fprintf(stderr, "Error: bad npt.\n");
149 }
150 return(BOBYQA_INVALID_ARGS);
151 }
152
153 /* Allocate double working_space, if not done by caller */
154 i=bobyqa_working_memory_size(n, fitted_n, npt, &bdata);
155 ret=bobyqa_set_memory(n, fitted_n, npt, &bdata, working_space);
156 if(ret!=BOBYQA_SUCCESS) return(BOBYQA_OUT_OF_MEMORY);
157
158 /* Copy BOBYQA parameters to bdata struct */
159 ret=bobyqa_set_optimization(n, x, dx, xl, xu, rhoend, xtol_rel,
160 minf_max, ftol_rel, ftol_abs, maxeval,
161 f, objf_data, verbose, &bdata);
162 if(ret!=BOBYQA_SUCCESS) {
163 bobyqa_free_memory(&bdata); return(BOBYQA_INVALID_ARGS);
164 }
165 if(verbose>2) bobyqa_print(&bdata, 4, stdout);
166
167
168 /* Call BOBYQB */
169 if(bdata.n>1) { // BOBYQA works only if at least 2 parameters are fitted
170 ret = bobyqb(&bdata);
171 if(bdata.verbose>1) printf("ret := %d\n", ret);
172 if(bdata.verbose>0) {
173 if(ret<0) printf("Error in bobyqb(): %s\n", bobyqa_rc(ret));
174 else printf("Return code of bobyqb(): %s\n", bobyqa_rc(ret));
175 }
176 } else { // Simple local 1-D minimization when necessary
178 if(bdata.verbose>1) printf("ret := %d\n", ret);
179 if(bdata.verbose>0 && ret<0)
180 printf("Error %d in 1-D optimization\n", ret);
181 }
182 /* Copy fitted parameters to full parameter list */
183 bobyqa_xfull(&bdata);
184 for(i=0; i<n; i++) x[i]=bdata.xfull[i];
185 if(nevals!=NULL) *nevals=bdata.nevals;
186 /* Copy min value to argument pointer */
187 *minf=bdata.minf;
188
189 /* Quit */
190 if(verbose>1) {
191 printf("prelim() called %d time(s)\n", bdata.prelim_nr);
192 printf("rescue() called %d time(s)\n", bdata.rescue_nr);
193 printf("altmov() called %d time(s)\n", bdata.altmov_nr);
194 printf("trsbox() called %d time(s)\n", bdata.trsbox_nr);
195 printf("update() called %d time(s)\n", bdata.update_nr);
196 }
197 bobyqa_free_memory(&bdata);
198
199 if(verbose>0) printf("out of bobyqa() with return code %d\n", ret);
200 return ret;
201} /* bobyqa() */
bobyqa_result bobyqb(bobyqa_data *bdata)
Definition bobyqa.c:1622
char * bobyqa_rc(bobyqa_result rc)
Definition bobyqa.c:381
void bobyqa_print(bobyqa_data *bdata, int sw, FILE *fp)
Definition bobyqa.c:640
bobyqa_result bobyqa_free_memory(bobyqa_data *bdata)
Definition bobyqa.c:592
bobyqa_result bobyqa_set_memory(int n, int fitted_n, int npt, bobyqa_data *bdata, double *wm)
Definition bobyqa.c:501
int bobyqa_working_memory_size(int n, int fitted_n, int npt, bobyqa_data *bdata)
Definition bobyqa.c:441
void bobyqa_xfull(bobyqa_data *bdata)
Definition bobyqa.c:769
bobyqa_result bobyqa_set_optimization(int full_n, double *x, const double *dx, const double *xl, const double *xu, const double rhoend, double xtol_rel, double minf_max, double ftol_rel, double ftol_abs, int maxeval, double(*f)(int n, double *x, void *objf_data), void *objf_data, int verbose, bobyqa_data *bdata)
Definition bobyqa.c:781
int bobyqa_minimize_single_parameter(bobyqa_data *bdata)
Definition bobyqa.c:210
int fixed_params(int n, const double *lower, const double *upper, const double *delta)
Definition bobyqa.c:418
double * xfull

Referenced by tgo().

◆ bobyqa_free_memory()

bobyqa_result bobyqa_free_memory ( bobyqa_data * bdata)
extern

Free the working memory and memory for data arrays and matrices in BOBYQA structure that was allocated by bobyqa_allocate_memory().

Returns
Returns BOBYQA_SUCCESS when successful.
Parameters
bdataPointer to bobyqa struct

Definition at line 592 of file bobyqa.c.

595 {
596 if(bdata==NULL) return BOBYQA_INVALID_ARGS;
597 /* Free double working memory, if it was allocated by bobyqa_set_memory() */
598 if(bdata->lwmptr!=NULL) free(bdata->lwmptr);
599 bdata->lwmptr=NULL;
600 /* Free integer working memory */
601 if(bdata->liwmptr!=NULL) free(bdata->liwmptr);
602 bdata->liwmptr=NULL;
603 return BOBYQA_SUCCESS;
604}
double * lwmptr

Referenced by bobyqa(), and bobyqa_set_memory().

◆ bobyqa_minimize_single_parameter()

int bobyqa_minimize_single_parameter ( bobyqa_data * bdata)
extern

Local one-dimensional minimization, meant to be called from bobyqa() which does not otherwise work with 1-D problems.

Returns
BOBYQA_SUCCESS, BOBYQA_INVALID_ARGS, etc.
See also
nlopt1D

Definition at line 210 of file bobyqa.c.

212 {
213 if(bdata->verbose>0) {printf("bobyqa_minimize_single_parameter()\n"); fflush(stdout);}
214
215 double p1=0, p2=0, p3=0, f1=0, f2=0, f3=0, begin, end;
216 double d, d2;
217 const double tau=0.1;
218 double p_min, f_min, bracket_ratio;
219
220 /* Check the input */
221 if(bdata->n!=1) return BOBYQA_INVALID_ARGS;
222 if(bdata->rhoend<=0.0) return BOBYQA_INVALID_ARGS;
223 if(bdata->rhoend>=bdata->rhobeg) return BOBYQA_INVALID_ARGS;
224 if(bdata->maxeval<2) return BOBYQA_INVALID_ARGS;
225
226 begin=bdata->xl[0];
227 end=bdata->xu[0];
228
229 /* Update the full parameter list for objf() */
230 bdata->nevals=0;
231 f2 = bdata->minf = bobyqa_x_funcval(bdata, bdata->x);
232 /* If parameter is fixed, then this was all that we can do */
233 if(bdata->xl[0]>=bdata->xu[0]) {
234 if(bdata->verbose>1) printf("Warning: the only parameter is fixed\n");
235 return BOBYQA_SUCCESS;
236 }
237
238 /* Find three bracketing points such that f1 > f2 < f3.
239 Do this by generating a sequence of points expanding away from 0.
240 Also note that, in the following code, it is always the
241 case that p1 < p2 < p3. */
242 p2=bdata->x[0];
243
244 /* Start by setting a starting set of 3 points that are inside the bounds */
245 p1=p2-bdata->rhobeg; if(p1>begin) p1=begin;
246 p3=p2+bdata->rhobeg; if(p3<end) p3=end;
247 /* Compute their function values */
248 bdata->x[0]=p1;
249 f1 = bdata->minf = bobyqa_x_funcval(bdata, bdata->x);
250 bdata->x[0]=p3;
251
252 f3 = bdata->minf = bobyqa_x_funcval(bdata, bdata->x);
253
254 if(p2==p1 || p2==p3) {
255 p2=0.5*(p1+p3);
256 bdata->x[0]=p2;
257 f2 = bdata->minf = bobyqa_x_funcval(bdata, bdata->x);
258 }
259
260 /* Now we have 3 points on the function.
261 Start looking for a bracketing set such that f1 > f2 < f3 is the case. */
262 double jump_size=bdata->rhobeg;
263 while(!(f1>f2 && f2<f3)) {
264 /* check for hitting max_iter */
265 if(bdata->verbose>5) printf(" bracketing: nevals=%d\n", bdata->nevals);
266 if(bdata->nevals >= bdata->maxeval) {
267 bdata->x[0]=p2; bdata->minf=f2; return BOBYQA_MAXEVAL_REACHED;
268 }
269 /* check if required tolerance was reached */
270 if((p3-p1)<bdata->rhoend) { //if (p3-p1 < eps)
271 if(bdata->verbose>1)
272 printf(" max tolerance was reached during bracketing\n");
273 if(f1<f2 && f1<f3) {
274 bdata->x[0]=p1; bdata->minf=f1; return BOBYQA_XTOL_REACHED;
275 }
276 if(f2<f1 && f2<f3) {
277 bdata->x[0]=p2; bdata->minf=f2; return BOBYQA_XTOL_REACHED;
278 }
279 bdata->x[0]=p3; bdata->minf=f3; return BOBYQA_XTOL_REACHED;
280 }
281 if(bdata->verbose>6) printf(" jump_size=%g\n", jump_size);
282 /* if f1 is small then take a step to the left */
283 if(f1<f3) {
284 /* check if the minimum is colliding against the bounds. If so then pick
285 a point between p1 and p2 in the hopes that shrinking the interval will
286 be a good thing to do. Or if p1 and p2 aren't differentiated then try
287 and get them to obtain different values. */
288 if(p1==begin || (f1==f2 && (end-begin)<jump_size )) {
289 p3=p2; f3=f2; p2=0.5*(p1+p2);
290 bdata->x[0]=p2;
291 f2 = bdata->minf = bobyqa_x_funcval(bdata, bdata->x);
292 } else {
293 /* pick a new point to the left of our current bracket */
294 p3=p2; f3=f2; p2=p1; f2=f1;
295 p1-=jump_size; if(p1<begin) p1=begin;
296 bdata->x[0]=p1;
297 f1 = bobyqa_x_funcval(bdata, bdata->x);
298 jump_size*=2.0;
299 }
300 } else { // otherwise f3 is small and we should take a step to the right
301 /* check if the minimum is colliding against the bounds. If so then pick
302 a point between p2 and p3 in the hopes that shrinking the interval will
303 be a good thing to do. Or if p2 and p3 aren't differentiated then
304 try and get them to obtain different values. */
305 if(p3==end || (f2==f3 && (end-begin)<jump_size)) {
306 p1=p2; f1=f2; p2=0.5*(p3+p2);
307 bdata->x[0]=p2;
308 f2 = bdata->minf = bobyqa_x_funcval(bdata, bdata->x);
309 } else {
310 /* pick a new point to the right of our current bracket */
311 p1=p2; f1=f2; p2=p3; f2=f3;
312 p3+=jump_size; if(p3>end) p3=end;
313 bdata->x[0]=p3;
314 f3 = bdata->minf = bobyqa_x_funcval(bdata, bdata->x);
315 jump_size*=2.0;
316 }
317 }
318 }
319 if(bdata->verbose>4) printf(" brackets ready\n");
320
321 /* Loop until we have done the max allowable number of iterations or
322 the bracketing window is smaller than eps.
323 Within this loop we maintain the invariant that: f1 > f2 < f3 and
324 p1 < p2 < p3. */
325 while((bdata->nevals<bdata->maxeval) && (p3-p1>bdata->rhoend)) {
326 if(bdata->verbose>5) printf(" main loop: nevals=%d\n", bdata->nevals);
327
328 //p_min = lagrange_poly_min_extrap(p1,p2,p3, f1,f2,f3);
329 d=f1*(p3*p3-p2*p2) + f2*(p1*p1-p3*p3) + f3*(p2*p2-p1*p1);
330 d2=2.0*(f1*(p3-p2) + f2*(p1-p3) + f3*(p2-p1));
331 if(d2==0.0 || !isfinite(d/=d2)) { // d=d/d2
332 p_min=p2;
333 } else {
334 if(p1<=d && d<=p3) {p_min=d;}
335 else {p_min=d; if(p1>p_min) p_min=p1; if(p3<p_min) p_min=p3;}
336 }
337
338 /* make sure p_min isn't too close to the three points we already have */
339 if(p_min<p2) {
340 d=(p2-p1)*tau;
341 if(fabs(p1-p_min)<d) p_min=p1+d;
342 else if(fabs(p2-p_min)<d) p_min=p2-d;
343 } else {
344 d=(p3-p2)*tau;
345 if(fabs(p2-p_min)<d) p_min=p2+d;
346 else if(fabs(p3-p_min)<d) p_min=p3-d;
347 }
348
349 /* make sure one side of the bracket isn't super huge compared to the other
350 side. If it is then contract it. */
351 bracket_ratio=fabs(p1-p2)/fabs(p2-p3);
352 if(!(bracket_ratio<100.0 && bracket_ratio>0.01)) {
353 /* Force p_min to be on a reasonable side. */
354 if(bracket_ratio>1.0 && p_min>p2) p_min=0.5*(p1+p2);
355 else if(p_min<p2) p_min=0.5*(p2+p3);
356 }
357
358 /* Compute function value at p_min */
359 bdata->x[0]=p_min;
360 f_min = bdata->minf = bobyqa_x_funcval(bdata, bdata->x);
361
362 /* Remove one of the endpoints of our bracket depending on where the new point falls */
363 if(p_min<p2) {
364 if(f1>f_min && f_min<f2) {p3=p2; f3=f2; p2=p_min; f2=f_min;}
365 else {p1=p_min; f1 = f_min;}
366 } else {
367 if(f2>f_min && f_min<f3) {p1=p2; f1=f2; p2=p_min; f2=f_min;}
368 else {p3=p_min; f3=f_min;}
369 }
370 }
371 bdata->x[0]=p2; bdata->minf=f2;
372 if(bdata->nevals>=bdata->maxeval) return BOBYQA_MAXEVAL_REACHED;
373 return BOBYQA_XTOL_REACHED;
374}
double bobyqa_x_funcval(bobyqa_data *bdata, double *x)
Definition bobyqa.c:751
double rhoend
double * xl
double rhobeg
double * x
double * xu

Referenced by bobyqa().

◆ bobyqa_print()

void bobyqa_print ( bobyqa_data * bdata,
int sw,
FILE * fp )
extern

For testing: print BOBYQA data struct variables to specified file pointer.

Parameters
bdataPointer to bobyqa structure.
swSwitch that tells what to print: 0=All; 1=parameters; 2=array sizes; 3=full parameter list; 4=fitted parameters, limits and deltas.
fpFile pointer where contents are printed; usually stdout.

Definition at line 640 of file bobyqa.c.

648 {
649 int i;
650
651 if(bdata==NULL) {
652 fprintf(fp, "bobyqa data struct not defined.\n");
653 return;
654 }
655
656 if(sw==0 || sw==1) {
657 fprintf(fp, "nfull=%d\n", bdata->nfull);
658 fprintf(fp, "n=%d\n", bdata->n);
659 fprintf(fp, "npt=%d\n", bdata->npt);
660 fprintf(fp, "ndim=%d\n", bdata->ndim);
661 }
662
663 if(sw==0 || sw==2) {
664 fprintf(fp, "nfull=%d\n", bdata->nfull);
665 fprintf(fp, "x_size=%d\n", bdata->x_size);
666 fprintf(fp, "xl_size=%d\n", bdata->xl_size);
667 fprintf(fp, "xu_size=%d\n", bdata->xu_size);
668 fprintf(fp, "xbase_size=%d\n", bdata->xbase_size);
669 fprintf(fp, "xpt_size=%d\n", bdata->xpt_size);
670 fprintf(fp, "fval_size=%d\n", bdata->fval_size);
671 fprintf(fp, "xopt_size=%d\n", bdata->xopt_size);
672 fprintf(fp, "gopt_size=%d\n", bdata->gopt_size);
673 fprintf(fp, "hq_size=%d\n", bdata->hq_size);
674 fprintf(fp, "pq_size=%d\n", bdata->pq_size);
675 fprintf(fp, "bmat_size=%d\n", bdata->bmat_size);
676 fprintf(fp, "zmat_size=%d\n", bdata->zmat_size);
677 fprintf(fp, "sl_size=%d\n", bdata->sl_size);
678 fprintf(fp, "su_size=%d\n", bdata->su_size);
679 fprintf(fp, "xnew_size=%d\n", bdata->xnew_size);
680 fprintf(fp, "xalt_size=%d\n", bdata->xalt_size);
681 fprintf(fp, "dtrial_size=%d\n", bdata->dtrial_size);
682 fprintf(fp, "vlag_size=%d\n", bdata->vlag_size);
683 fprintf(fp, "w2npt_size=%d\n", bdata->w2npt_size);
684 fprintf(fp, "wndim_size=%d\n", bdata->wndim_size);
685 fprintf(fp, "wn_size=%d\n", bdata->wn_size);
686 fprintf(fp, "gnew_size=%d\n", bdata->gnew_size);
687 fprintf(fp, "xbdi_size=%d\n", bdata->xbdi_size);
688 fprintf(fp, "s_size=%d\n", bdata->s_size);
689 fprintf(fp, "hs_size=%d\n", bdata->hs_size);
690 fprintf(fp, "hred_size=%d\n", bdata->hred_size);
691 fprintf(fp, "glag_size=%d\n", bdata->hred_size);
692 fprintf(fp, "hcol_size=%d\n", bdata->hcol_size);
693 fprintf(fp, "ccstep_size=%d\n", bdata->ccstep_size);
694 fprintf(fp, "xscale_size=%d\n", bdata->xscale_size);
695 }
696
697 if(sw==0 || sw==3) {
698 fprintf(fp, "full parameter list:\n");
699 for(i=0; i<bdata->nfull; i++) {
700 fprintf(fp, " xfull[%d] = %g\n", i, bdata->xfull[i]);
701 }
702 }
703
704 if(sw==0 || sw==4) {
705 fprintf(fp, "fitted parameter indices =");
706 for(i=0; i<bdata->n; i++) {
707 fprintf(fp, " xplace[%d] = %d\n", i, bdata->xplace[i]);
708 }
709 fprintf(fp, "fitted parameter list:\n");
710 for(i=0; i<bdata->n; i++) {
711 fprintf(fp, " x[%d] = %g\n", i, bdata->x[i]);
712 }
713 fprintf(fp, "lower limits:\n");
714 for(i=0; i<bdata->n; i++) {
715 fprintf(fp, " xl[%d] = %g\n", i, bdata->xl[i]);
716 }
717 fprintf(fp, "upper limits:\n");
718 for(i=0; i<bdata->n; i++) {
719 fprintf(fp, " xu[%d] = %g\n", i, bdata->xu[i]);
720 }
721 fprintf(fp, "rescaling factors:\n");
722 for(i=0; i<bdata->n; i++) {
723 fprintf(fp, " xscale[%d] = %g\n", i, bdata->xscale[i]);
724 }
725 fprintf(fp, "rhobeg=%g\n", bdata->rhobeg);
726 fprintf(fp, "rhoend=%g\n", bdata->rhoend);
727
728 fprintf(fp, "scaled lower bounds:\n");
729 for(i=0; i<bdata->n; i++) {
730 fprintf(fp, " sl[%d] = %g\n", i, bdata->sl[i]);
731 }
732 fprintf(fp, "scaled upper bounds:\n");
733 for(i=0; i<bdata->n; i++) {
734 fprintf(fp, " su[%d] = %g\n", i, bdata->su[i]);
735 }
736 }
737
738 return;
739}
double * su
double * xscale
double * sl

Referenced by bobyqa().

◆ bobyqa_rc()

char * bobyqa_rc ( bobyqa_result rc)
extern

Description of bobyqa return code as text string.

Returns
Returns text string describing the bobyqa return code.

Definition at line 381 of file bobyqa.c.

383 {
384 static char *bobyqa_msg[] = {
385 /* 0 */ "failure",
386 /* 1 */ "invalid argument",
387 /* 2 */ "out of memory",
388 /* 3 */ "round-off limited",
389 /* 4 */ "success",
390 /* 5 */ "requested function value reached",
391 /* 6 */ "function value tolerance reached",
392 /* 7 */ "relative function value tolerance reached",
393 /* 8 */ "absolute function value tolerance reached",
394 /* 9 */ "parameter tolerance reached",
395 /* 10 */ "maximum number of function evaluations reached",
396 0};
397 switch(rc) {
398 case BOBYQA_FAIL: return bobyqa_msg[0];
399 case BOBYQA_INVALID_ARGS: return bobyqa_msg[1];
400 case BOBYQA_OUT_OF_MEMORY: return bobyqa_msg[2];
401 case BOBYQA_ROUNDOFF_LIMITED: return bobyqa_msg[3];
402 case BOBYQA_SUCCESS: return bobyqa_msg[4];
403 case BOBYQA_MINF_MAX_REACHED: return bobyqa_msg[5];
404 case BOBYQA_FTOL_REACHED: return bobyqa_msg[6];
405 case BOBYQA_RELFTOL_REACHED: return bobyqa_msg[7];
406 case BOBYQA_ABSFTOL_REACHED: return bobyqa_msg[8];
407 case BOBYQA_XTOL_REACHED: return bobyqa_msg[9];
408 case BOBYQA_MAXEVAL_REACHED: return bobyqa_msg[10];
409 }
410 return bobyqa_msg[0];
411}

Referenced by bobyqa().

◆ bobyqa_reset_memory()

bobyqa_result bobyqa_reset_memory ( bobyqa_data * bdata)
extern

Initiate BOBYQA data struct variables before calling bobyqb(). Can be used to reset data variables before calling bobyqb() again with the same problem size, without need to call bobyqa_free_memory() and bobyqa_set_memory() first.

Returns
Returns BOBYQA_SUCCESS when successful.
Parameters
bdataPointer to bobyqa struct

Definition at line 614 of file bobyqa.c.

617 {
618
619 if(bdata==NULL) return BOBYQA_INVALID_ARGS;
620 if(bdata->npt<1 || bdata->n<1) return BOBYQA_INVALID_ARGS;
621
622 /* Initiate struct variables */
623 bdata->dsq=0.0;
624 bdata->xoptsq=0.0;
625 bdata->rc = BOBYQA_SUCCESS;
626 bdata->knew = 0;
627 bdata->scaden = 0.0;
628 bdata->biglsq = 0.0;
629 bdata->nptm = bdata->npt - (bdata->n+1);
630 bdata->nevals=0;
631 bdata->rescue_nr=bdata->altmov_nr=bdata->trsbox_nr=bdata->update_nr=0;
632 bdata->prelim_nr=0;
633
634 return BOBYQA_SUCCESS;
635}
double biglsq
double scaden
double xoptsq

Referenced by bobyqa_set_memory().

◆ bobyqa_set_memory()

bobyqa_result bobyqa_set_memory ( int n,
int fitted_n,
int npt,
bobyqa_data * bdata,
double * wm )
extern

Setup working memory and memory for data arrays and matrices in BOBYQA structure. Double memory is either allocated inside this function or preallocated memory can be given as argument.

Returns
Returns BOBYQA_SUCCESS when successful.
Parameters
nNumber of all model parameters.
fitted_nNumber of fitted (not fixed) model parameters.
nptNPT.
bdataPointer to bobyqa structure.
wmEnter pointer to preallocated working memory; NULL to allocate it here.

Definition at line 501 of file bobyqa.c.

512 {
513 int wmsize;
514 double *lwm, *wptr;
515 int *liwm;
516
517 if(n<1 || fitted_n<1 || npt<1 || bdata==NULL) return BOBYQA_INVALID_ARGS;
518
519 /* Determine the required size of working memory and set the sizes inside data struct */
520 wmsize=bobyqa_working_memory_size(n, fitted_n, npt, bdata);
521
522 /* If working memory for doubles is not preallocated, then allocate it */
523 if(wm!=NULL) {
524 lwm=wm; bdata->lwmptr=NULL;
525 } else {
526 /* Allocate working memory */
527 lwm=(double*)malloc(sizeof(double)*wmsize);
528 if(lwm==NULL) {
529 return(BOBYQA_OUT_OF_MEMORY);
530 }
531 bdata->lwmptr=lwm;
532 }
533 bdata->wmptr=lwm;
534
535 /* Working memory for integers is always allocated here */
536 liwm=(int*)malloc(sizeof(int)*fitted_n);
537 if(liwm==NULL) {
538 if(wm==NULL) bobyqa_free_memory(bdata);
539 return(BOBYQA_OUT_OF_MEMORY);
540 }
541 bdata->liwmptr=liwm;
542
543 /* Set data pointers inside bobyqa struct */
544 bdata->xplace=bdata->liwmptr;
545 wptr=bdata->wmptr;
546 bdata->xfull=wptr; wptr+=bdata->nfull;
547 bdata->x=wptr; wptr+=bdata->x_size;
548 bdata->xl=wptr; wptr+=bdata->xl_size;
549 bdata->xu=wptr; wptr+=bdata->xu_size;
550 bdata->xbase=wptr; wptr+=bdata->xbase_size;
551 bdata->xpt=wptr; wptr+=bdata->xpt_size;
552 bdata->fval=wptr; wptr+=bdata->fval_size;
553 bdata->xopt=wptr; wptr+=bdata->xopt_size;
554 bdata->gopt=wptr; wptr+=bdata->gopt_size;
555 bdata->hq=wptr; wptr+=bdata->hq_size;
556 bdata->pq=wptr; wptr+=bdata->pq_size;
557 bdata->bmat=wptr; wptr+=bdata->bmat_size;
558 bdata->zmat=wptr; wptr+=bdata->zmat_size;
559 bdata->sl=wptr; wptr+=bdata->sl_size;
560 bdata->su=wptr; wptr+=bdata->su_size;
561 bdata->xnew=wptr; wptr+=bdata->xnew_size;
562 bdata->xalt=wptr; wptr+=bdata->xalt_size;
563 bdata->dtrial=wptr; wptr+=bdata->dtrial_size;
564 bdata->vlag=wptr; wptr+=bdata->vlag_size;
565 bdata->w2npt=wptr; wptr+=bdata->w2npt_size;
566 bdata->wndim=wptr; wptr+=bdata->wndim_size;
567 bdata->wn=wptr; wptr+=bdata->wn_size;
568 bdata->gnew=wptr; wptr+=bdata->gnew_size;
569 bdata->xbdi=wptr; wptr+=bdata->xbdi_size;
570 bdata->s=wptr; wptr+=bdata->s_size;
571 bdata->hs=wptr; wptr+=bdata->hs_size;
572 bdata->hred=wptr; wptr+=bdata->hred_size;
573 bdata->glag=wptr; wptr+=bdata->glag_size;
574 bdata->hcol=wptr; wptr+=bdata->hcol_size;
575 bdata->ccstep=wptr; wptr+=bdata->ccstep_size;
576 bdata->xscale=wptr; wptr+=bdata->xscale_size;
577
578 /* Set struct contents */
579 bdata->n=fitted_n;
580 bdata->nfull=n;
581 bdata->npt=npt;
582 bdata->ndim = npt+fitted_n;
583 if(bobyqa_reset_memory(bdata)!=BOBYQA_SUCCESS) return BOBYQA_INVALID_ARGS;
584
585 return BOBYQA_SUCCESS;
586}
bobyqa_result bobyqa_reset_memory(bobyqa_data *bdata)
Definition bobyqa.c:614
double * hcol
double * xnew
double * dtrial
double * wmptr
double * hs
double * zmat
double * gopt
double * xbase
double * pq
double * xopt
double * fval
double * glag
double * w2npt
double * xbdi
double * bmat
double * wn
double * wndim
double * s
double * hred
double * gnew
double * vlag
double * xalt
double * hq
double * xpt
double * ccstep

Referenced by bobyqa().

◆ bobyqa_set_optimization()

bobyqa_result bobyqa_set_optimization ( int full_n,
double * x,
const double * dx,
const double * xl,
const double * xu,
const double rhoend,
double xtol_rel,
double minf_max,
double ftol_rel,
double ftol_abs,
int maxeval,
double(* )(int n, double *x, void *objf_data),
void * objf_data,
int verbose,
bobyqa_data * bdata )
extern

Set optimization parameters and limits in BOBYQA data struct.

Returns
Returns BOBYQA_SUCCESS when successful.
Parameters
full_nLength of full parameter list.
xPointer to array of full parameters.
dxPointer to array of initial step sizes (deltas).
xlPointer to array of lower limits.
xuPointer to array of upper limits.
rhoendRhoend; enter <=0 to use default value, calculated using xtol_rel.
xtol_relRelative X tolerance.
minf_maxStopping rule: maximal allowed function value; when reached, stops.
ftol_relStopping rule: relative tolerance to function value.
ftol_absStopping rule: absolute tolerance to function value.
maxevalStopping rule: max nr of function evaluations.
fPointer to object function
objf_dataPointer to data that is carried over to the object function. Enter NULL if not needed.
verboseVerbose level for all BOBYQA functions; if zero, then nothing is printed to stderr or stdout
bdataPointer to bobyqa structure.

Definition at line 781 of file bobyqa.c.

813 {
814 int i, j;
815 double d, dm;
816
817 if(bdata==NULL) return BOBYQA_INVALID_ARGS;
818 if(full_n!=bdata->nfull) return BOBYQA_INVALID_ARGS;
819 if(x==NULL || dx==NULL) return BOBYQA_INVALID_ARGS;
820 if(xl==NULL || xu==NULL) return BOBYQA_INVALID_ARGS;
821
822 /* Copy full parameter list */
823 for(i=0; i<full_n; i++) bdata->xfull[i]=x[i];
824
825 /* Make list of fitted parameters (those that are not fixed);
826 and internal list of their positions in full list;
827 and rescaling factor for each dimension based on initial step size
828 so that initial step size would be equal in all directions
829 */
830 for(i=j=0; i<full_n; i++) if(dx[i]!=0.0 && xu[i]>xl[i]) {
831 /* Positions in full list */
832 bdata->xplace[j]=i;
833 /* Set scaling factors */
834 bdata->xscale[j]=fabs(dx[i]);
835 /* Set initial scaled parameters */
836 bdata->x[j]=x[i]/bdata->xscale[j];
837 /* Set scaled limits */
838 bdata->xl[j]=xl[i]/bdata->xscale[j];
839 bdata->xu[j]=xu[i]/bdata->xscale[j];
840 j++; // index of fitted parameters
841 } // next parameter
842 /* check that nr of fitted parameters is the same that was used to
843 allocate memory in the data struct */
844 if(j!=bdata->n) return BOBYQA_INVALID_ARGS;
845
846 /* Initial step sizes are now internally scaled to 1, therefore: */
847 bdata->rhobeg = 1.0;
848 /* however, 2*rhobeg must be <= xu[]-xl[] */
849 j=0; dm=bdata->xu[j]-bdata->xl[j];
850 for(j=1; j<bdata->n; j++) {d=bdata->xu[j]-bdata->xl[j]; if(d<dm) dm=d;}
851 if(dm < 2.*bdata->rhobeg) {
852 if(dm>1.0E-20) {
853 /* Set smaller rhobeg to have sufficient space between the bounds */
854 bdata->rhobeg=0.5*dm;
855 } else {
856 /* Return from BOBYQA because one of the differences
857 XU(I)-XL(I)s is less than 2*RHOBEG, and very small, too. */
858 if(verbose>0) fprintf(stderr, "Error: stepsize<2*rhobeg\n");
859 printf("smallest stepsize=%g 2*rhobeg=%g\n", dm, 2.*bdata->rhobeg);
860 return(BOBYQA_INVALID_ARGS);
861 }
862 }
863
864 /* Set rhoend; if not given by caller, then compute rhoend from
865 optimization stop info */
866 if(rhoend>0.0) bdata->rhoend=rhoend;
867 else bdata->rhoend = xtol_rel * bdata->rhobeg;
868 if(!isfinite(bdata->rhoend)) bdata->rhoend=1.0E-14;
869
870 /* Return error if there is insufficient space between the bounds.
871 Modify the initial estimates X[], if necessary, in order to avoid
872 conflicts between the bounds and the construction of the first quadratic
873 model.
874 The lower and upper bounds (sl[], su[]) on moves from the updated X[]
875 are set now, in order to provide useful and exact information about
876 components of X[] that become within distance RHOBEG from their bounds. */
877 for(j=0; j<bdata->n; j++) {
878 d=bdata->xu[j]-bdata->xl[j];
879 /* Set sl and su */
880 bdata->sl[j]= bdata->xl[j]-bdata->x[j];
881 bdata->su[j] = bdata->xu[j]-bdata->x[j];
882 if(bdata->sl[j] >= -bdata->rhobeg) {
883 if(bdata->sl[j] >= 0.0) {
884 bdata->x[j]=bdata->xl[j];
885 bdata->sl[j]=0.0;
886 bdata->su[j]=d;
887 } else {
888 bdata->x[j]=bdata->xl[j]+bdata->rhobeg;
889 bdata->sl[j]=-bdata->rhobeg;
890 bdata->su[j]=fmax(bdata->xu[j]-bdata->x[j], bdata->rhobeg);
891 }
892 } else if(bdata->su[j] <= bdata->rhobeg) {
893 if(bdata->su[j] <= 0.0) {
894 bdata->x[j]=bdata->xu[j];
895 bdata->sl[j]=-d;
896 bdata->su[j]=0.0;
897 } else {
898 bdata->x[j]=bdata->xu[j]-bdata->rhobeg;
899 bdata->sl[j]=fmin(bdata->xl[j]-bdata->x[j], -bdata->rhobeg);
900 bdata->su[j]=bdata->rhobeg;
901 }
902 }
903 }
904
905 bdata->verbose=verbose;
906 bdata->minf_max=minf_max;
907 bdata->ftol_rel=ftol_rel;
908 bdata->ftol_abs=ftol_abs;
909 bdata->maxeval=maxeval;
910
911 bdata->objf=(bobyqa_func)f;
912 bdata->objf_data=objf_data;
913
914 return BOBYQA_SUCCESS;
915}
double(* bobyqa_func)(int n, const double *x, void *func_data)
Definition libtpcmodel.h:92
double ftol_abs
double minf_max
double ftol_rel
void * objf_data
bobyqa_func objf

Referenced by bobyqa().

◆ bobyqa_working_memory_size()

int bobyqa_working_memory_size ( int n,
int fitted_n,
int npt,
bobyqa_data * bdata )
extern

Calculate the required size of memory to allocate for bobyqa().

Returns
Returns the size of double array.
Parameters
nNumber of all model parameters
fitted_nNumber of fitted (not fixed) model parameters
nptNPT
bdataEnter pointer to bobyqa struct to set array sizes, otherwise enter NULL

Definition at line 441 of file bobyqa.c.

450 {
451 int i=0, s, np, ndim;
452
453 np=fitted_n+1; ndim=npt+fitted_n;
454
455 s=n; i+=s; if(bdata!=NULL) bdata->nfull=s;
456
457 s=fitted_n; i+=s; if(bdata!=NULL) bdata->x_size=s;
458 s=fitted_n; i+=s; if(bdata!=NULL) bdata->xl_size=s;
459 s=fitted_n; i+=s; if(bdata!=NULL) bdata->xu_size=s;
460 s=fitted_n; i+=s; if(bdata!=NULL) bdata->xbase_size=s;
461 s=fitted_n*npt; i+=s; if(bdata!=NULL) bdata->xpt_size=s;
462 s=npt; i+=s; if(bdata!=NULL) bdata->fval_size=s;
463 s=fitted_n; i+=s; if(bdata!=NULL) bdata->xopt_size=s;
464 s=fitted_n; i+=s; if(bdata!=NULL) bdata->gopt_size=s;
465 s=fitted_n*np/2; i+=s; if(bdata!=NULL) bdata->hq_size=s;
466 s=npt; i+=s; if(bdata!=NULL) bdata->pq_size=s;
467 s=ndim*fitted_n; i+=s; if(bdata!=NULL) bdata->bmat_size=s;
468 s=npt*(npt-np); i+=s; if(bdata!=NULL) bdata->zmat_size=s;
469 s=fitted_n; i+=s; if(bdata!=NULL) bdata->sl_size=s;
470 s=fitted_n; i+=s; if(bdata!=NULL) bdata->su_size=s;
471 s=fitted_n; i+=s; if(bdata!=NULL) bdata->xnew_size=s;
472 s=fitted_n; i+=s; if(bdata!=NULL) bdata->xalt_size=s;
473 s=fitted_n; i+=s; if(bdata!=NULL) bdata->dtrial_size=s;
474 s=ndim; i+=s; if(bdata!=NULL) bdata->vlag_size=s;
475
476 s=2*npt; i+=s; if(bdata!=NULL) bdata->w2npt_size=s;
477 s=ndim; i+=s; if(bdata!=NULL) bdata->wndim_size=s;
478 s=fitted_n; i+=s; if(bdata!=NULL) bdata->wn_size=s;
479 s=fitted_n; i+=s; if(bdata!=NULL) bdata->gnew_size=s;
480 s=fitted_n; i+=s; if(bdata!=NULL) bdata->xbdi_size=s;
481 s=fitted_n; i+=s; if(bdata!=NULL) bdata->s_size=s;
482 s=fitted_n; i+=s; if(bdata!=NULL) bdata->hs_size=s;
483 s=fitted_n; i+=s; if(bdata!=NULL) bdata->hred_size=s;
484 s=fitted_n; i+=s; if(bdata!=NULL) bdata->glag_size=s;
485 s=npt; i+=s; if(bdata!=NULL) bdata->hcol_size=s;
486 s=2*fitted_n; i+=s; if(bdata!=NULL) bdata->ccstep_size=s;
487
488 s=fitted_n; i+=s; if(bdata!=NULL) bdata->xscale_size=s;
489
490 //bobyqa_print(bdata, 2, stdout);
491 return(i);
492}

Referenced by bobyqa(), and bobyqa_set_memory().

◆ bobyqa_x_funcval()

double bobyqa_x_funcval ( bobyqa_data * bdata,
double * x )
extern

Calculate the objective function value with current scaled parameters values stored in specified array. This function back-scales the parameters to the full parameter list and calls the objective function with full set of parameters, that is, including also fixed parameters which are saved in bobyqa data struct. Also nevals is incremented.

Returns
Returns the value of objective function.

Definition at line 751 of file bobyqa.c.

754 {
755 int j;
756 double v;
757
758 for(j=0; j<bdata->n; j++) bdata->xfull[bdata->xplace[j]]=x[j]*bdata->xscale[j];
759 v = bdata->objf(bdata->nfull, bdata->xfull, bdata->objf_data);
760 bdata->nevals++;
761 return(v);
762}

Referenced by bobyqa_minimize_single_parameter(), bobyqa_prelim(), bobyqa_rescue(), and bobyqb_calc_with_xnew().

◆ bobyqa_xfull()

void bobyqa_xfull ( bobyqa_data * bdata)
extern

Add the fitted parameters (x[]) to the full parameter list (xfull[]). xfull[] will contain back-scaled parameter values. x[] is not modified.

Definition at line 769 of file bobyqa.c.

771 {
772 for(int j=0; j<bdata->n; j++)
773 bdata->xfull[bdata->xplace[j]]=bdata->x[j]*bdata->xscale[j];
774}

Referenced by bobyqa(), and bobyqb_xupdate().

◆ bobyqb()

bobyqa_result bobyqb ( bobyqa_data * bdata)
extern

bobyqb (called from bobyqa).

Returns
Returns <0 in case of n error, >0 when successful.
Parameters
bdataData struct for BOBYQA subroutines

Definition at line 1622 of file bobyqa.c.

1625 {
1626 if(bdata->verbose>2) {printf("bobyqb()\n"); fflush(stdout);}
1627
1628 int i, j, k;
1629 double curv;
1630 double bdtol;
1631 double errbig;
1632 double bdtest;
1633 double frhosq;
1634 bobyqa_result rc2;
1635 double d1;
1636
1637
1638 /* The call of PRELIM sets the elements of XBASE, XPT, FVAL, GOPT, HQ, PQ,
1639 BMAT and ZMAT for the first iteration, with the corresponding values of
1640 of NF and KOPT, which are the number of calls of objf() so far and the
1641 index of the interpolation point at the trust region centre. Then the
1642 initial XOPT is set too. The branch to label 720 occurs if MAXFUN is
1643 less than NPT. GOPT will be updated if KOPT is different from KBASE. */
1644 rc2 = bobyqa_prelim(bdata);
1645
1646 for(i=0, bdata->xoptsq=0.0; i<bdata->n; i++) {
1647 bdata->xopt[i] = bdata->xpt[bdata->kopt-1 +i*bdata->npt];
1648 bdata->xoptsq+=bdata->xopt[i]*bdata->xopt[i];
1649 }
1650 bdata->fsave = bdata->fval[0];
1651 if (rc2 != BOBYQA_SUCCESS) {
1652 bdata->rc = rc2;
1653 if(bdata->verbose>3) printf("prelim() was not successful\n");
1654 bobyqb_xupdate(bdata);
1655 return bdata->rc;
1656 }
1657 bdata->kbase = 1;
1658
1659 /* Complete the settings that are required for the iterative procedure. */
1660 bdata->rho=bdata->rhobeg;
1661 bdata->delta= bdata->rho;
1662 bdata->nresc= bdata->nevals;
1663 bdata->ntrits= 0;
1664 bdata->diffa=bdata->diffb=bdata->diffc= 0.0;
1665 bdata->ratio =0.0; //=1.0;
1666 bdata->itest= 0;
1667 bdata->nfsav= bdata->nevals;
1668
1669 /* Update GOPT if necessary before the first iteration and after each
1670 call of RESCUE that makes a call of objf(). */
1671 if (bdata->kopt != bdata->kbase) bobyqb_update_gopt(bdata);
1672
1673 do { // start main loop
1674 /* Generate the next point in the trust region that provides a small value
1675 of the quadratic model subject to the constraints on the variables.
1676 The int NTRITS is set to the number "trust region" iterations that
1677 have occurred since the last "alternative" iteration. If the length
1678 of XNEW-XOPT is less than 0.5*RHO, however, then there is a branch to
1679 label 650 or 680 with NTRITS=-1, instead of calculating F at XNEW. */
1680 bobyqa_trsbox(bdata);
1681 bdata->dnorm = fmin(bdata->delta, sqrt(bdata->dsq));
1682
1683#if(0) // original
1684 if(bdata->dnorm < 0.5 * bdata->rho) {
1685#else
1686 if(bdata->dnorm>0.0 && bdata->dnorm < 0.5 * bdata->rho) {
1687#endif
1688 if(bdata->verbose>10) {
1689 printf("ntrits set to -1; A\n");
1690 printf("bdata->dnorm=%.15E 0.5*bdata->rho=%.15E\n",
1691 bdata->dnorm, 0.5*bdata->rho);
1692 printf("delta=%.15E dsq=%.15E\n", bdata->delta, bdata->dsq);
1693 }
1694 bdata->ntrits = -1;
1695 d1=10.0*bdata->rho; bdata->distsq = d1*d1;
1696 if(bdata->nevals <= bdata->nfsav + 2) {
1697 if(bdata->verbose>10) {
1698 printf("nevals<=nfsav+2 (nevals=%d nfsav=%d)\n",
1699 bdata->nevals, bdata->nfsav);
1700 }
1701 } else {
1702
1703 /* The following choice between labels 650 and 680 depends on whether or
1704 not our work with the current RHO seems to be complete. Either RHO is
1705 decreased or termination occurs if the errors in the quadratic model
1706 at the last three interpolation points compare favourably with
1707 predictions of likely improvements to the model within distance
1708 0.5*RHO of XOPT. */
1709 d1 = fmax(bdata->diffa, bdata->diffb); errbig = fmax(d1, bdata->diffc);
1710 frhosq = bdata->rho * .125 * bdata->rho;
1711 if(bdata->_crvmin<=0.0 || errbig <= frhosq*bdata->_crvmin) {
1712 bdtest=bdtol= errbig/bdata->rho;
1713
1714 for(j=0; j<bdata->n; j++) {
1715 bdtest=bdtol;
1716 if(bdata->xnew[j]==bdata->sl[j]) bdtest=bdata->gnew[j];
1717 if(bdata->xnew[j]==bdata->su[j]) bdtest=-bdata->gnew[j];
1718 if(bdtest<bdtol) {
1719 curv=bdata->hq[(j+1 + (j+1)*(j+1))/2 - 1];
1720 for(k=0; k<bdata->npt; k++) {
1721 d1=bdata->xpt[k+j*bdata->npt]; curv+=bdata->pq[k]*(d1*d1);
1722 }
1723 bdtest += 0.5*curv*bdata->rho;
1724 if(bdtest < bdtol) break;
1725 }
1726 }
1727 if(bdtest>=bdtol) {
1728 /* The calculations with the current value of RHO are complete.
1729 Pick the next values of RHO and DELTA. */
1730 if (bdata->rho > bdata->rhoend) {
1731 bobyqb_next_rho_delta(bdata);
1732 continue;
1733 }
1734
1735 /* Return from the calculation, after another Newton-Raphson step,
1736 if it is too short to have been tried before. */
1737 if(bdata->ntrits != -1) {
1738 bobyqb_xupdate(bdata);
1739 return bdata->rc;
1740 }
1741 bdata->rc=bobyqb_calc_with_xnew(bdata);
1742 if(bdata->rc!=BOBYQA_SUCCESS) return bdata->rc;
1743 /* If a trust region step has provided a sufficient decrease in F,
1744 then branch for another trust region calculation.
1745 The case NTRITS=0 occurs when the new interpolation point was
1746 reached by an alternative step. */
1747 if (bdata->ntrits==0 || bdata->newf<=bdata->fopt+0.1*bdata->vquad) {
1748 continue;
1749 }
1750
1751 /* Alternatively, find out if the interpolation points are close
1752 enough to the best point so far. */
1753 d1=fmax(2.0*bdata->delta, 10.0*bdata->rho);
1754 bdata->distsq=d1*d1;
1755 }
1756 }
1757 }
1758
1759 } else {
1760
1761 bdata->ntrits++;
1762
1763 /* Severe cancellation is likely to occur if XOPT is too far from XBASE.
1764 If the following test holds, then XBASE is shifted so that XOPT becomes
1765 zero. The appropriate changes are made to BMAT and to the second
1766 derivatives of the current model, beginning with the changes to BMAT
1767 that do not depend on ZMAT.
1768 VLAG is used temporarily for working space */
1769 if(bdata->dsq <= bdata->xoptsq * .001) bobyqb_shift_xbase(bdata);
1770
1771 if (bdata->ntrits == 0) {
1772 bobyqa_altmov(bdata);
1773 for(i=0; i<bdata->n; i++) bdata->dtrial[i]=bdata->xnew[i]-bdata->xopt[i];
1774 }
1775
1776 i=bobyqb_part(bdata);
1777 if(i==-1) return bdata->rc;
1778 if(i==1) continue;
1779
1780 bdata->rc=bobyqb_calc_with_xnew(bdata);
1781 if(bdata->rc!=BOBYQA_SUCCESS) return bdata->rc;
1782
1783 /* If a trust region step has provided a sufficient decrease in F, then
1784 branch for another trust region calculation. The case NTRITS=0 occurs
1785 when the new interpolation point was reached by an alternative step. */
1786 if (bdata->ntrits==0 || bdata->newf <= bdata->fopt+0.1*bdata->vquad) {
1787 continue;
1788 }
1789
1790 /* Alternatively, find out if the interpolation points are close enough
1791 to the best point so far. */
1792 d1=fmax(2.0*bdata->delta, 10.0*bdata->rho);
1793 bdata->distsq=d1*d1;
1794
1795 }
1796 while(1) {
1797 /* Check if interpolation points are close enough, and update distsq
1798 if necessary */
1799 i=bobyqb_ip_dist(bdata);
1800
1801 /* If not close enough (KNEW is positive),
1802 then ALTMOV finds alternative new positions for
1803 the KNEW-th interpolation point within distance ADELT of XOPT. */
1804 if(i!=0) { // Tästä iffistä ei jatketa alle
1805 /* Find alternative new positions for the KNEWth interpolation point
1806 within distance ADELT of XOPT. */
1807 bobyqb_ip_alternative(bdata);
1808 i=bobyqb_part(bdata);
1809 if(i==-1) return bdata->rc;
1810 if(i==1) break;
1811
1812 bdata->rc=bobyqb_calc_with_xnew(bdata);
1813 if(bdata->rc!=BOBYQA_SUCCESS) return bdata->rc;
1814
1815 /* If a trust region step has provided a sufficient decrease in F, then
1816 branch for another trust region calculation. The case NTRITS=0 occurs
1817 when the new interpolation point was reached by an alternative step. */
1818 if (bdata->ntrits == 0 || bdata->newf <= bdata->fopt + 0.1*bdata->vquad) {
1819 break;
1820 }
1821
1822 /* Alternatively, find out if the interpolation points are close enough
1823 to the best point so far. */
1824 d1=fmax(2.0*bdata->delta, 10.0*bdata->rho);
1825 bdata->distsq=d1*d1;
1826
1827 continue;
1828 }
1829 /* Another trust region iteration, unless the calculations with the
1830 current RHO are complete. */
1831 if(bdata->ntrits != -1) {
1832 if(bdata->ratio>0.0 || fmax(bdata->delta, bdata->dnorm) > bdata->rho) {
1833 break;
1834 }
1835 }
1836
1837 /* The calculations with the current value of RHO are complete. Pick the
1838 next values of RHO and DELTA. */
1839 if (bdata->rho > bdata->rhoend) {
1840 bobyqb_next_rho_delta(bdata);
1841 break;
1842 }
1843
1844 /* Return from the calculation, after another Newton-Raphson step, if
1845 it is too short to have been tried before */
1846 if (bdata->ntrits == -1) {
1847 bdata->rc=bobyqb_calc_with_xnew(bdata);
1848 if(bdata->rc!=BOBYQA_SUCCESS) return bdata->rc;
1849 /* If a trust region step has provided a sufficient decrease in F, then
1850 branch for another trust region calculation. The case NTRITS=0 occurs
1851 when the new interpolation point was reached by an alternative step. */
1852 if (bdata->ntrits == 0 || bdata->newf <= bdata->fopt+0.1*bdata->vquad) {
1853 break;
1854 }
1855 /* Alternatively, find out if the interpolation points are close enough
1856 to the best point so far. */
1857 d1=fmax(2.0*bdata->delta, 10.0*bdata->rho);
1858 bdata->distsq=d1*d1;
1859
1860 continue;
1861 } else {
1862 bobyqb_xupdate(bdata);
1863 return bdata->rc;
1864 }
1865 }
1866 } while(1);
1867 // actually we should never reach this point
1868 return bdata->rc;
1869} /* bobyqb() */
bobyqa_result bobyqa_prelim(bobyqa_data *bdata)
Definition bobyqa.c:2135
void bobyqb_ip_alternative(bobyqa_data *bdata)
Definition bobyqa.c:1593
int bobyqb_ip_dist(bobyqa_data *bdata)
Definition bobyqa.c:1575
void bobyqb_update_gopt(bobyqa_data *bdata)
Definition bobyqa.c:945
void bobyqa_altmov(bobyqa_data *bdata)
Definition bobyqa.c:1875
int bobyqb_part(bobyqa_data *bdata)
Definition bobyqa.c:1449
void bobyqa_trsbox(bobyqa_data *bdata)
Definition bobyqa.c:2724
int bobyqb_calc_with_xnew(bobyqa_data *bdata)
Definition bobyqa.c:1093
void bobyqb_xupdate(bobyqa_data *bdata)
Definition bobyqa.c:921
void bobyqb_shift_xbase(bobyqa_data *bdata)
Definition bobyqa.c:973
void bobyqb_next_rho_delta(bobyqa_data *bdata)
Definition bobyqa.c:1383
double distsq

Referenced by bobyqa().

◆ bootstrap()

int bootstrap ( int iterNr,
double * cLim1,
double * cLim2,
double * SD,
double * parameter,
double * lowlim,
double * uplim,
int frameNr,
double * origTac,
double * fitTac,
double * bsTac,
int parNr,
double * weight,
double(* objf )(int, double *, void *),
char * status,
int verbose )
extern

Bootstrap method.

Original weights are assumed to be inversely proportional to variance. Square root is used, because bootstrap assumes them to be proportional to standard deviation. If only standard deviation is needed then cLim1 and cLim2 can be set to be NULL, and if only the confidence limits are wanted then SD can be set to be NULL. This function will not set seed for random number generator, therefore, make sure that it is set in your program, for example with srand(time(NULL));.

Returns
Return values:
  • 0, if ok.
  • 1 - 3 if some of the given parameters is not qualified.
  • 4, if Powell fails, and 5, if out of memory.
Parameters
iterNrBootstrap iteration number (>=100), set to zero to use the default (200).
cLim1Vector to put the lower confidence limits to; NULL if not needed.
cLim2Vector to put the upper confidence limits to; NULL if not needed.
SDVector to put the standard deviations to; NULL if not needed.
parameterBest parameter estimates (preserved by this function).
lowlimLower limits for the parameters.
uplimUpper limits for the parameters.
frameNrNr of samples in tissue TAC data.
origTacMeasured tissue TAC values (not modified; local copy is used).
fitTacBest fitted tissue TAC values (not modified; local copy is used).
bsTacPointer to (empty) tissue TAC vector, where bootstrapped TACs will be written in each bootstrap iteration, and which will be used by objective function to calculate WSS.
parNrNr of parameters.
weightsample weights.
objfThe object function.
statusPointer to a string (allocated for at least 64 chars) where error message or other execution status will be written; enter NULL, if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout.

Definition at line 55 of file bootstrap.c.

90 {
91
92 int ret, i, j, powellItNr, lowindex, upindex;
93 double fret=0.0, *parMean, *chainptr, *chain, **matrix, *delta, *bsFitTac;
94 double help, *error, *wError, *biasEst, *unbiasPar, *estInOrder;
95 char bserrmsg[64];
96
97 if(verbose>0)
98 printf("%s(%d, ..., %d, ..., %d, ..., %d)\n", __func__, iterNr, frameNr, parNr, verbose);
99
100 /* Checking the given parameters */
101 if(status!=0) strcpy(status, "");
102 if(iterNr<100) iterNr=200;
103 if(frameNr<1 || parNr<1 ) {
104 strcpy(bserrmsg, "either framenumber or parameternumber is negative");
105 if(verbose>0) fprintf(stderr, "Error: %s.\n", bserrmsg);
106 if(status!=0) strcpy(status, bserrmsg);
107 return(1);
108 }
109 if(bsTac==NULL || parameter==NULL || objf==NULL || origTac==NULL ||
110 fitTac==NULL)
111 {
112 strcpy(bserrmsg, "some of the given parameters are not pointing anywhere");
113 if(verbose>0) fprintf(stderr, "Error: %s.\n", bserrmsg);
114 if(status!=0) strcpy(status, bserrmsg);
115 return(2);
116 }
117 for(i=0; i<parNr; i++) {
118 if(lowlim[i]>uplim[i]) {
119 strcpy(bserrmsg, "given limit values are not qualified");
120 if(verbose>0) fprintf(stderr, "Error: %s.\n", bserrmsg);
121 if(status!=0) strcpy(status, bserrmsg);
122 return(3);
123 }
124 }
125
126 /* Allocating memory */
127 if(verbose>1) printf(" allocating memory\n");
128 bsFitTac=(double*)malloc(frameNr*sizeof(double));
129 bs_parameter=(double*)malloc(parNr*sizeof(double));
130 bs_weight=(double*)malloc(frameNr*sizeof(double));
131 delta=(double*)malloc(parNr*sizeof(double));
132 parMean=(double*)malloc(parNr*sizeof(double));
133 chain=(double*)malloc((iterNr*parNr)*sizeof(double));
134 matrix=(double**)malloc(parNr*sizeof(double*));
135 error=(double*)malloc(frameNr*sizeof(double));
136 wError=(double*)malloc(frameNr*sizeof(double));
137 biasEst=(double*)malloc(parNr*sizeof(double));
138 unbiasPar=(double*)malloc(parNr*sizeof(double));
139 if(bsFitTac==NULL || bs_parameter==NULL || bs_weight==NULL || delta==NULL ||
140 parMean==NULL || chain==NULL || matrix==NULL || error==NULL ||
141 wError==NULL || biasEst==NULL || unbiasPar==NULL) {
142 strcpy(bserrmsg, "out of memory");
143 if(verbose>0) fprintf(stderr, "Error: %s.\n", bserrmsg);
144 if(status!=0) strcpy(status, bserrmsg);
145 return(5);
146 }
147 for(i=0, chainptr=chain; i<parNr; i++) {
148 matrix[i]=(chainptr + i*iterNr);
149 }
150
151 bs_parNr=parNr;
152 bs_frameNr=frameNr;
153 bs_func=objf;
154 bs_lowlim=lowlim;
155 bs_uplim=uplim;
156 for(i=0; i<bs_parNr; i++) {
157 bs_parameter[i]=parameter[i];
158 }
159
160 /* copy data and check the weights */
161 /* calculate the errors and weighted errors */
162 if(verbose>2) printf(" calculating errors and weighted errors");
163 for(i=0; i<bs_frameNr; i++) {
164 bsFitTac[i]=fitTac[i];
165 if(weight[i]<=0.0) bs_weight[i]=1; else bs_weight[i]=weight[i];
166 error[i]=origTac[i]-bsFitTac[i];
167 wError[i]=error[i]/sqrt(bs_weight[i]);
168 }
169 if(verbose>3) {
170 printf(" weighted errors:\n ");
171 for(i=0; i<bs_frameNr; i++) printf("%g ", wError[i]);
172 printf("\n");
173 }
174
175 /*
176 * bootstrap iterations
177 */
178 if(verbose>1) printf(" bootstrap iterations\n");
179 if(verbose>4) printf("Bootstrap matrix:\n");
180 int powellfailNr=0;
181
182 for(i=0; i<iterNr; i++) {
183
184 /* sample a new error distribution (to the pointer error) */
185 for(j=0; j<bs_frameNr; j++) {
186 error[j]=wError[(int)((bs_frameNr)*(double)rand()/((double)(RAND_MAX)+1))];
187 bsTac[j]=bsFitTac[j]+bs_weight[j]*error[j];
188 }
189
190 /* Powell local search */
191 for(j=0; j<bs_parNr; j++) {
192 delta[j]=0.01*(bs_uplim[j]-bs_lowlim[j]);
193 bs_parameter[j]=parameter[j];
194 }
195 powellItNr=400;
196 ret=powell(bs_parameter, delta, bs_parNr, 0.00001, &powellItNr, &fret, bs_func, NULL, 0);
197 if(ret>1 && ret!=3) {
198 sprintf(bserrmsg, "error %d in powell()", ret);
199 if(verbose>0) fprintf(stderr, "Error: %s.\n", bserrmsg);
200 if(status!=0) strcpy(status, bserrmsg);
201 free(bsFitTac);
202 free(bs_parameter);
203 free(bs_weight);
204 free(delta);
205 free(parMean);
206 free(matrix);
207 free(chain);
208 free(error);
209 free(wError);
210 free(biasEst);
211 free(unbiasPar);
212 return(4);
213 }
214 if(ret==3) { // powell sometimes fails, do not worry if not too often
215 powellfailNr++;
216 }
217
218 for(j=0; j<bs_parNr; j++) {
219 matrix[j][i]=bs_parameter[j];
220 }
221 if(verbose>4) {
222 for(j=0; j<bs_parNr; j++) printf("%g ", bs_parameter[j]);
223 printf("\n");
224 }
225
226 } /* end of bootstrap iterations */
227 if(powellfailNr>(iterNr/3)) {
228 sprintf(bserrmsg, "error %d in powell()", ret);
229 if(verbose>0) fprintf(stderr, "Error: too often %s.\n", bserrmsg);
230 if(status!=0) strcpy(status, bserrmsg);
231 free(bsFitTac);
232 free(bs_parameter);
233 free(bs_weight);
234 free(delta);
235 free(parMean);
236 free(matrix);
237 free(chain);
238 free(error);
239 free(wError);
240 free(biasEst);
241 free(unbiasPar);
242 return(4);
243 }
244
245 /* Computing the mean of each parameter and estimates for bias */
246 if(verbose>1) printf(" computing parameter bias\n");
247 for(i=0; i<bs_parNr; i++) {
248 for(j=0, help=0.0; j<iterNr; j++) help+=matrix[i][j];
249 parMean[i]=help/(double)iterNr;
250 biasEst[i]=parMean[i]-parameter[i];
251 /*unbiasPar[i]=parameter[i]-biasEst[i];*/
252 if(verbose>1) {
253 printf("parMean[%d] := %g\n", i, parMean[i]);
254 printf("parameter[%d] := %g\n", i, parameter[i]);
255 printf("biasEst[%d] := %g\n", i, biasEst[i]);
256 }
257 }
258
259 /* Computing the standard deviation for each parameter estimate */
260 if(SD!=NULL) {
261 if(verbose>1) printf("Standard deviations:\n");
262 for(i=0; i<bs_parNr; i++) {
263 for(j=0, help=0; j<iterNr; j++) {
264 help+=(matrix[i][j]-parMean[i])*(matrix[i][j]-parMean[i])/(iterNr-1);
265 }
266 SD[i]=sqrt(help); if(verbose>1) printf(" %g\n", SD[i]);
267 }
268 }
269
270 if(cLim1!=NULL && cLim2!=NULL) {
271 if(verbose>1) printf("Confidence intervals:\n");
272 lowindex=(int)temp_roundf(0.025*iterNr);
273 upindex=(int)temp_roundf(0.975*iterNr)-1;
274 /* Computing the 95% confidence intervals for each parameter estimate */
275 for(i=0; i<bs_parNr; i++) {
276
277 /* Arrange estimate samples in ascending order */
278 estInOrder=matrix[i];
279 qsort(estInOrder, iterNr, sizeof(double), bootstrapQSort);
280
281 /* Get the indices within which 95% of samples lie in */
282 if(fabs(estInOrder[lowindex]-biasEst[i])<1e-99) cLim1[i]=0.0;
283 else cLim1[i]=estInOrder[lowindex]-biasEst[i];
284 if(fabs(estInOrder[upindex]-biasEst[i])<1e-99) cLim2[i]=0.0;
285 else cLim2[i]=estInOrder[upindex]-biasEst[i];
286 if(verbose>1) {
287 printf(" %g - %g\n", cLim1[i], cLim2[i]);
288 }
289 }
290 if(verbose>6) {
291 printf("Sorted matrix\n");
292 for(j=0; j<iterNr; j++) {
293 for(i=0; i<bs_parNr; i++) printf(" %12.3e", matrix[i][j]);
294 printf("\n");
295 }
296 printf("lowindex := %d\nupindex := %d\n", lowindex, upindex);
297 }
298 }
299
300 free(bsFitTac);
301 free(bs_parameter);
302 free(bs_weight);
303 free(delta);
304 free(parMean);
305 free(matrix);
306 free(chain);
307 free(error);
308 free(wError);
309 free(biasEst);
310 free(unbiasPar);
311
312 if(verbose>0) {printf(" end of bootstrap()\n");}
313 return(0);
314
315} /* end bootstrap() */
#define RAND_MAX
Definition gaussdev.c:13
int temp_roundf(float e)
Definition petc99.c:20
int powell(double *p, double *delta, int parNr, double ftol, int *iterNr, double *fret, double(*_fun)(int, double *, void *), void *fundata, int verbose)
Definition powell.c:43

◆ bvls()

int bvls ( int key,
const int m,
const int n,
double * a,
double * b,
double * bl,
double * bu,
double * x,
double * w,
double * act,
double * zz,
int * istate,
int * iter,
int verbose )
extern

Bounded-value least-squares method to solve the linear problem A x ~ b , subject to limit1 <= x <= limit2.

This routine is based on the text and Fortran code in C.L. Lawson and R.J. Hanson, Solving Least Squares Problems, Prentice-Hall, Englewood Cliffs, New Jersey, 1974, and Fortran codes by R.L. Parker and P.B. Stark, and by J. Burkardt.

See also
nnls, qrLH, llsqWghtSquared, llsqWght
Returns
Returns 0 when successful, -1 if iteration count exceeded the limit, 1 in case of invalid data or settings, and 2 if problem cannot be solved.
Parameters
keyEnter 0 to solve the problem from scratch, or <>0 to initialize the routine using caller's guess about which parameters are active within their bounds, which are at their lower bounds, and which at their upper bounds, as supplied in the array istate ('warm start'). When key <> 0, the routine initially sets the active components to the averages of their upper and lower bounds.
mNumber of samples in matrix A and the length of vector b.
nNumber of parameters in matrix A and the length of vector x. The n must not be > m unless at least n-m variables are non-active (set to their bounds)..
aPointer to matrix A; matrix must be given as an n*m array, containing n consecutive m-length vectors. Contents of A are modified in this routine.
bPointer to vector b of length m. Contents of b are modified in this routine.
blArray BL[0..n-1] of lower bounds for parameters.
buArray BU[0..n-1] of upper bounds for parameters.
xPointer to the result vector x of length n.
wPointer to an array of length n, which will be used as working memory, and the minimum 2-norm || a.x-b ||, (R^2), will be written in w[0].
actPointer to an array of length m*(n+2), or m*(m+2) if m<n, which will be used as working memory.
zzPointer to an array of length m, to be used as working memory.
istatePointer to an integer array of length n+1. If parameter key <>0, then the last position istate[n] must contain the total number of components at their bounds (nbound, the ‘bound variables’). The absolute values of the first nbound entries of istate[] are the indices of these ‘bound’ components of x[]. The sign of istate[0.. nbound-1] entries indicates whether x[|istate[i]|] is at its upper (positive) or lower (negative) bound. Entries istate[nbound..n-1] contain the indices of the active components.
iterNumber of performed iterations is returned in this variable. Maximum nr of iterations is set with this variable, or set it to 0 to use the default maximum, 3*n.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout

Definition at line 24 of file bvls.c.

72 {
73 if(verbose>0) {printf("bvls(%d, %d, %d, ...)\n", key, m, n); fflush(stdout);}
74 /* Check the input */
75 if(a==NULL || b==NULL || bl==NULL || bu==NULL || x==NULL || w==NULL ||
76 act==NULL || zz==NULL || istate==NULL || iter==NULL || n<1 || m<1)
77 {
78 if(verbose>0) fprintf(stderr, "Error: invalid input to BVLS.\n");
79 return(1);
80 }
81
82 int maxIter=*iter; if(maxIter<3) maxIter=3*n;
83 *iter=0;
84 const double eps=1.0E-13; // stopping rule
85
86 /* Step 1. Initialize everything -- active and bound sets, initial values, etc. */
87 if(verbose>1) {printf("step 1\n"); fflush(stdout);}
88
89 /* Set mm to the smaller of matrix dimensions n and m. */
90 int mm; if(m<n) mm=m; else mm=n;
91 int aindx=0; // one-based index of X[] that determined the alpha; zero means not set.
92 int aindxsign=0; // +1 if zz[aindx]> bu[aindx], -1 if zz[aindx]<bl[aindx]
93 /* istateFromStep5 is the one-based index of the parameter that most wants to be active;
94 zero value means its is currently not set. */
95 int istateFromStep5 = 0;
96
97 /* Check the consistency of given bounds bl[] and bu[]. */
98 {
99 double maxrange=0.0;
100 for(int ni=0; ni<n; ni++) {
101 double d=bu[ni]-bl[ni];
102 if(verbose>3) printf(" bounds[%d]: %g %g\n", 1+ni, bl[ni], bu[ni]);
103 if(d<0.0) {
104 if(verbose>0) fprintf(stderr, "Error: inconsistent bounds in BVLS.\n");
105 return(1);
106 }
107 maxrange=fmax(maxrange, d);
108 }
109 if(verbose>2) printf(" maxrange := %g\n", maxrange);
110 if(maxrange<1.0E-10) {
111 if(verbose>0) fprintf(stderr, "Error: no free variables in BVLS.\n");
112 return(1);
113 }
114 }
115
116 /* In a fresh initialization (key=0), bind all variables at their lower bounds.
117 If key<>0, use the supplied istate[] array to initialize the variables. */
118 int nbound, nact; // number of bound and active parameters, respectively.
119 if(key==0) {
120 nbound=n;
121 /* Write the indices; negative sign indicates lower limit */
122 /* Note that these indices must start from 1, because 0 can not have sign */
123 for(int ni=0; ni<nbound; ni++) istate[ni]=-(1+ni);
124 } else {
125 nbound=istate[n];
126 }
127 nact=n-nbound;
128 if(nact>mm) {
129 if(verbose>0) fprintf(stderr, "Error: too many active variables in BVLS starting solution.\n");
130 return(2);
131 }
132 for(int ni=0; ni<nbound; ni++) {
133 int i=abs(istate[ni])-1;
134 if(istate[ni]<0) x[i]=bl[i]; else x[i]=bu[i];
135 }
136
137 /* In a warm start (key<>0, and nbound<n) initialize the active variables to the mean of
138 their bounds. This is needed in case the initial QR results in active variables
139 out-of-bounds and Steps 8-11 get executed the first time through. */
140 for(int ni=nbound; ni<n; ni++) {
141 int i=abs(istate[ni])-1; // indices of active variables should not have signs, but let's be sure
142 x[i]=0.5*(bl[i]+bu[i]);
143 }
144
145 /* Compute bnorm, the norm of the data vector b, for reference. */
146 double bnorm=0.0;
147 for(int mi=0; mi<m; mi++) bnorm+=b[mi]*b[mi];
148 bnorm=sqrt(bnorm); if(verbose>2) printf(" initial_bnorm := %g\n", bnorm);
149
150
151 /*
152 * Main loop
153 */
154 int skipStep2=0;
155 double obj=0.0;
156 int iact=0; // The component x[iact] is the one that most wants to become active
157
158 for(*iter=1; *iter<=maxIter; ++(*iter)) {
159
160 if(verbose>1) {printf("iteration %d\n", *iter); fflush(stdout);}
161
162 if(!skipStep2) {
163 /* Step 2. */ if(verbose>1) {printf(" step 2\n"); fflush(stdout);}
164
165 /* Initialize the negative gradient vector w(*). */
166 for(int ni=0; ni<n; ni++) w[ni]=0.0;
167
168 /* Compute the residual vector b-a.x , the negative gradient vector w[*], and
169 the current objective value obj = || a.x - b ||.
170 The residual vector is stored in the mm+1'st column of act[*,*]. */
171 obj=0.0;
172 for(int mi=0; mi<m; mi++) {
173 double ri=b[mi];
174 for(int ni=0; ni<n; ni++) ri-=a[mi+ni*m]*x[ni];
175 obj+=ri*ri;
176 for(int ni=0; ni<n; ni++) w[ni]+=a[mi+ni*m]*ri;
177 act[mi+mm*m]=ri;
178 }
179 if(verbose>3) {printf(" obj := %g\n", obj); fflush(stdout);}
180
181 /* Converged? Stop if the misfit << || b ||, or if all components are active
182 (unless this is the first iteration from a 'warm start'). */
183 if((sqrt(obj)<=bnorm*eps) || ((*iter)>1 && nbound==0)) {
184 if(verbose>1) {printf("bvls converged.\n"); fflush(stdout);}
185 istate[n]=nbound;
186 w[0]=sqrt(obj);
187 return(0);
188 }
189
190 /* Add the contribution of the active components back into the residual. */
191 for(int ni=nbound; ni<n; ni++) {
192 int i=abs(istate[ni])-1;
193 for(int mi=0; mi<m; mi++) act[mi+mm*m] += a[mi+i*m]*x[i];
194 }
195 if(verbose>9) {
196 printf("Residual vector:\n");
197 for(int mi=0; mi<m; mi++) printf("\t%g", act[mi+mm*m]);
198 printf("\n");
199 }
200
201 }
202
203
204
205 /* The first iteration in a 'warm start' requires immediate QR in Step 6
206 but mostly we want go through Steps 3-5 first . */
207 if(key!=0 && (*iter)==1) {
208 if(verbose>1) printf(" 'warm start' requires immediate QR in Step 6\n");
209 } else {
210
211 int it; // variable indicating the element in istate that most wants to be active
212
213 do {
214 /* Steps 3, 4. */ if(verbose>1) {printf(" steps 3 and 4\n"); fflush(stdout);}
215 /* Find the bound element that most wants to be active. */
216 double worst=0.0;
217 it=1;
218 for(int ni=0; ni<nbound; ni++) {
219 int i=abs(istate[ni])-1;
220 double bad; if(istate[ni] < 0) bad=-w[i]; else bad=+w[i];
221 if(bad < worst) { it=ni+1; worst=bad; iact=i; }
222 }
223
224 /* Test whether the Kuhn-Tucker condition is met. */
225 if(worst>=0.0) {
226 if(verbose>1) {printf("Kuhn-Tucker condition is met.\n"); fflush(stdout);}
227 istate[n]=nbound;
228 w[0]=sqrt(obj);
229 return(0);
230 }
231
232 /* The component x[iact] is the one that most wants to become active.
233 If the last successful change in the active set was to move x[iact] to a bound,
234 don't let x[iact] in now: set the derivative of the misfit with respect to x[iact]
235 to zero and return to the Kuhn-Tucker test. */
236 if(iact==(aindx-1)) w[aindx-1]=0.0;
237 } while(iact==(aindx-1)); // Step 3 again
238
239 /* Step 5. */ if(verbose>1) {printf(" step 5\n"); fflush(stdout);}
240
241 /* Undo the effect of the new (potentially) active variable on the residual vector. */
242 if(istate[it-1]==0) { // remove this if never happening
243 if(verbose>0) fprintf(stderr, "Error: BVLS istate is zero!\n");
244 return(1);
245 }
246 {
247 double bnd;
248 if(istate[it-1]>0) bnd=bu[iact]; else bnd=bl[iact];
249 for(int mi=0; mi<m; mi++) act[mi+mm*m]+=bnd*a[mi+iact*m];
250 }
251
252 /* Set flag istateFromStep5, indicating that Step 6 was entered from Step 5.
253 This forms the basis of a test for instability: the gradient calculation shows that x[iact]
254 wants to join the active set; if QR puts x[iact] beyond the bound from which it came,
255 the gradient calculation was in error and the variable should not have been introduced. */
256 istateFromStep5=istate[it-1];
257
258 /* Swap the indices (in istate) of the new active variable and the rightmost bound variable;
259 `unbind' that location by decrementing nbound. */
260 istate[it-1]=istate[nbound-1];
261 nbound--; nact++;
262 istate[nbound]=1+iact;
263 if(mm<nact) {
264 if(verbose>0) fprintf(stderr, "Error: too many free variables in BVLS.\n");
265 return(2);
266 }
267
268 } // finalized steps 3-5
269
270 do {
271
272 skipStep2=0;
273
274 /* Step 6. */ if(verbose>1) {printf(" step 6\n"); fflush(stdout);}
275
276 /* Load array act with the appropriate columns of A for QR. For added stability, reverse
277 the column ordering so that the most recent addition to the active set is in the last
278 column. Also copy the residual vector from act[., mm] into act[., mm+1]. */
279 for(int mi=0; mi<m; mi++) {
280 act[mi+(mm+1)*m]=act[mi+mm*m]; // vector b for QR
281 for(int ni=nbound; ni<n; ni++) {
282 int i=abs(istate[ni])-1;
283 act[mi+(nact+nbound-ni-1)*m]=a[mi+i*m];
284 }
285 }
286 if(verbose>9) {
287 printf("Matrix A for QR:\n");
288 for(int ni=0; ni<nact; ni++) {
289 for(int mi=0; mi<m; mi++) printf("\t%g", act[mi+ni*nact]);
290 printf("\n");
291 }
292 printf("Vector B for QR:\n");
293 for(int mi=0; mi<m; mi++) printf("\t%g", act[(mm+1)*m + mi]);
294 printf("\n");
295 }
296
297 /* Test for linear dependence in QR, and for an instability that moves the variable
298 just introduced away from the feasible region (rather than into the region or
299 all the way through it). In either case, remove the latest vector introduced from
300 the active set and adjust the residual vector accordingly.
301 Set the gradient component (w[iact]) to zero and return to the Kuhn-Tucker test. */
302 double r2;
303 if(qrLH(m, nact, act, &act[(mm+1)*m], zz, &r2) !=0 ||
304 (istateFromStep5>0 && zz[nact-1]>bu[iact]) ||
305 (istateFromStep5<0 && zz[nact-1]<bl[iact]) )
306 {
307 nbound++;
308 if(bu[iact]>x[iact]) istate[nbound-1]=-istate[nbound-1];
309 nact--;
310 for(int mi=0; mi<m; mi++) act[mi+mm*m]-=x[iact]*a[mi+iact*m];
311 istateFromStep5 = 0; // not from step 5
312 w[iact]=0.0;
313 skipStep2=1; // we want to skip Step 2 and go directly to Step 3
314 if(verbose>3) {printf(" going from step 6 to step 3\n"); fflush(stdout);}
315 break; // go to step 3
316 }
317
318 /* If Step 6 was entered from Step 5 and we are here, a new variable has been successfully
319 introduced into the active set; the last variable that was fixed at a bound is again
320 permitted to become active. */
321 if(istateFromStep5!=0) aindx=0;
322 istateFromStep5=0;
323
324 /* Step 7. */ if(verbose>1) {printf(" step 7\n"); fflush(stdout);}
325 /* Check for strict feasibility of the new QR solution. */
326 int qr_solution_feasible=1;
327 int indexHolder=0;
328 if(verbose>8) printf(" nact=%d nbound=%d\n", nact, nbound);
329 for(int ni=0; ni<nact; ni++) {
330 indexHolder=ni; // Loop in step 8 will start from this
331 int i=abs(istate[ni+nbound])-1;
332 if(verbose>8) {
333 printf(" istate[%d]=%d\n", ni+nbound, 1+i);
334 printf(" zz[%d]=%g bl[%d]=%g bu[%d]=%g\n", nact-ni-1, zz[nact-ni-1], i, bl[i], i, bu[i]);
335 }
336 if(zz[nact-ni-1]<bl[i] || zz[nact-ni-1]>bu[i]) {
337 if(verbose>3) {printf(" new iterate is not feasible\n"); fflush(stdout);}
338 qr_solution_feasible=0; break; // go to Step 8
339 }
340 }
341 if(verbose>8) printf(" indexHolder=%d\n", indexHolder);
342 if(qr_solution_feasible) {
343 if(verbose>3) {printf(" new iterate is feasible\n"); fflush(stdout);}
344 for(int ni=0; ni<nact; ni++) {
345 int i=abs(istate[ni+nbound])-1;
346 x[i]=zz[nact-ni-1];
347 }
348 /* New iterate is feasible; back to the top. */
349 break; // Back to the start of the main loop
350 }
351
352 { // keep local variables alpha and alf local
353 double alpha=2.0;
354 /* Steps 8 and 9 */ if(verbose>1) {printf(" steps 8 and 9\n"); fflush(stdout);}
355 double alf=alpha;
356 for(int ni=indexHolder; ni<nact; ni++) {
357 int i=abs(istate[ni+nbound])-1;
358 if(zz[nact-ni-1] > bu[i]) alf=(bu[i]-x[i])/(zz[nact-ni-1]-x[i]);
359 if(zz[nact-ni-1] < bl[i]) alf=(bl[i]-x[i])/(zz[nact-ni-1]-x[i]);
360 if(alf<alpha) {
361 alpha=alf;
362 aindx=1+i;
363 if((zz[nact-ni-1]-bl[i])<0.0) aindxsign=-1; else aindxsign=+1;
364 }
365 }
366 /* Step 10 */ if(verbose>1) {printf(" step 10\n"); fflush(stdout);}
367 for(int ni=0; ni<nact; ni++) {
368 int i=abs(istate[ni+nbound])-1;
369 x[i]+=alpha*(zz[nact-ni-1]-x[i]);
370 }
371 }
372
373 /* Step 11 */ if(verbose>1) {printf(" step 11\n"); fflush(stdout);}
374 /* Move the variable that determined alpha to the appropriate bound
375 (aindx is its index; sj is + if zz[aindx]> bu[aindx], - if zz[aindx]<bl[aindx] ).
376 If any other component of x is infeasible at this stage, it must be due to round-off.
377 Bind every infeasible component and every component at a bound to the appropriate bound.
378 Correct the residual vector for any variables moved to bounds. Since at least one
379 variable is removed from the active set in this step, Loop B
380 (Steps 6-11) terminates after at most nact steps. */
381 {
382 int noldb=nbound;
383 for(int ni=0; ni<nact; ni++) {
384 int i=abs(istate[ni+noldb])-1;
385 if((bu[i]-x[i]<=0.0) || (i==(aindx-1) && aindxsign>0)) {
386 /* Move x[i] to its upper bound. */
387 x[i]=bu[i];
388 istate[ni+noldb]=istate[nbound]; istate[nbound]=+(1+i); nbound++;
389 for(int mi=0; mi<m; mi++) act[mi+mm*m]-=bu[i]*a[mi+i*m];
390 } else if( ((x[i]-bl[i])<=0.0) || (i==(aindx-1) && aindxsign<0)) {
391 /* Move x(j) to its lower bound. */
392 x[i]=bl[i];
393 istate[ni+noldb]=istate[nbound]; istate[nbound]=-(1+i); nbound++;
394 for(int mi=0; mi<m; mi++) act[mi+mm*m]-=bl[i]*a[mi+i*m];
395 }
396 }
397 nact=n-nbound;
398 }
399 /* If there are still active variables left, repeat the QR; if not, go back to step 6. */
400 } while(nact>0);
401
402 } // main loop
403
404 /* iterMax reached */
405 if(verbose>0) fprintf(stderr, "Error: BVLS fails to converge.\n");
406 return(-1);
407}
int qrLH(const unsigned int m, const unsigned int n, double *a, double *b, double *x, double *r2)
Solve over-determined least-squares problem A x ~ b using successive Householder rotations.
Definition qr.c:633

◆ d_kth_smallest()

double d_kth_smallest ( double * data,
int n,
int k )
extern

Returns the kth smallest value in data[0..n-1]. Array is partially sorted. Algorithm is based on the book Wirth N. Algorithms + data structures = programs. Englewood Cliffs, Prentice-Hall, 1976.

Returns
Returns the kth smallest value in data[0..n-1].
Parameters
dataPointer to data; array is partially sorted.
nLength of data array.
kkth smallest value will be returned.

Definition at line 15 of file median.c.

22 {
23 int i, j, l, m;
24 double x, s;
25
26 l=0; m=n-1;
27 while(l<m) {
28 x=data[k]; i=l; j=m;
29 do {
30 while(data[i]<x) i++;
31 while(x<data[j]) j--;
32 if(i<=j) {s=data[i]; data[i]=data[j]; data[j]=s; i++; j--;}
33 } while(i<=j);
34 if(j<k) l=i;
35 if(k<i) m=j;
36 }
37 return(data[k]);
38}

Referenced by dmedian().

◆ dmean()

double dmean ( double * data,
int n,
double * sd )
extern

Returns the mean in array data[0..n-1], and optionally calculates also the (sample) standard deviation of the mean.

See also
dmedian, mean, dmean_nan, fmean
Returns
Returns the mean in array data[0..n-1].
Parameters
dataPointer to data; data is not changed in any way.
nLength of data array.
sdPointer to variable where SD will be written; enter NULL if not needed.

Definition at line 73 of file median.c.

80 {
81 int i;
82 double sumsqr=0.0, sqrsum=0.0, avg;
83
84 if(n<1 || data==NULL) {if(sd!=NULL) *sd=0.0; return(0.0);}
85
86 for(i=0; i<n; i++) {sumsqr+=data[i]*data[i]; sqrsum+=data[i];}
87 avg=sqrsum/(double)n; if(sd==NULL) return(avg);
88 if(n==1) {
89 *sd=0.0;
90 } else {
91 sqrsum*=sqrsum;
92 *sd=sqrt( (sumsqr - sqrsum/(double)n) / (double)(n-1) );
93 }
94 return(avg);
95}

◆ dmean_nan()

double dmean_nan ( double * data,
int n,
double * sd,
int * vn )
extern

Returns the mean in array data[0..n-1], and optionally calculates also the standard deviation of the mean. Data may contain missing samples marked as NaNs.

See also
dmedian, mean, dmean
Returns
Returns the mean in array data[0..n-1].
Parameters
dataPointer to data; data is not changed in any way.
nLength of data array.
sdPointer to variable where SD will be written; enter NULL if not needed.
vnPointer to variable where number of valid (not NaN) samples will be written; enter NULL if not needed.

Definition at line 104 of file median.c.

114 {
115 int i, m;
116 double sumsqr=0.0, sqrsum=0.0, avg;
117
118 if(n<1 || data==NULL) {
119 if(sd!=NULL) *sd=0.0;
120 if(vn!=NULL) *vn=0;
121 return(0.0);
122 }
123 for(i=m=0; i<n; i++) if(!isnan(data[i])) m++;
124 if(vn!=NULL) *vn=m;
125 if(m<1) {
126 if(sd!=NULL) *sd=nan("");
127 return(nan(""));
128 }
129
130
131 for(i=0; i<n; i++) if(!isnan(data[i])) {
132 sumsqr+=data[i]*data[i]; sqrsum+=data[i];
133 }
134 avg=sqrsum/(double)m; if(sd==NULL) return(avg); // SD not requested
135 if(m==1) {
136 *sd=0.0;
137 } else {
138 sqrsum*=sqrsum;
139 *sd=sqrt( (sumsqr - sqrsum/(double)m) / (double)(m-1) );
140 }
141 return(avg);
142}

◆ dmedian()

double dmedian ( double * data,
int n )
extern

Returns the median in array data[0..n-1]. Array is partially sorted. Algorithm is based on the book Wirth N. Algorithms + data structures = programs. Englewood Cliffs, Prentice-Hall, 1976.

See also
dmean, mean, fmedian
Returns
Returns the median in array data[0..n-1].
Parameters
dataPointer to data; array is partially sorted.
nLength of data array.

Definition at line 48 of file median.c.

53 {
54 int k;
55 double d1, d2;
56
57 if(n<1) return(0.0);
58 if(n%2) {
59 k=(n-1)/2; return(d_kth_smallest(data, n, k));
60 } else {
61 k=n/2; d1=d_kth_smallest(data, n, k-1); d2=d_kth_smallest(data, n, k);
62 return(0.5*(d1+d2));
63 }
64}
double d_kth_smallest(double *data, int n, int k)
Definition median.c:15

Referenced by dftRobustMinMaxTAC(), least_trimmed_square(), and mEstim().

◆ drand()

double drand ( )
extern

Alternative function to rand() which returns a double precision floating point number in the range of [0,1].

Returns
Random value in the range [0,1].
See also
rand_range, gaussdev

Definition at line 142 of file gaussdev.c.

143{
144 double d, s;
145 s=1.0/(1.0+RAND_MAX);
146 do {
147 d = ( ( s*rand() + rand() )*s + rand() ) * s;
148 } while(d>=1.0);
149 return d;
150}

Referenced by gaussdev(), gaussdev2(), rand_range(), tgoRandomParameters(), and tgoRandomParametersST().

◆ drandSeed()

unsigned int drandSeed ( short int seed)
extern

Make and optionally set the seed for rand(), drand, drandRange, and drandGaussian().

Uses microseconds from the computer clock and process ID to reduce the chance of getting the same seed for simultaneously executing program threads and instances.

Returns
Returns the seed for srand().
Parameters
seedAlso sets seed with srand (1) or not (0)

Definition at line 63 of file gaussdev.c.

66 {
67 unsigned int li;
68#ifdef HAVE_TIMESPEC_GET
69 struct timespec ts;
70 timespec_get(&ts, TIME_UTC);
71 li=((ts.tv_sec % 10000)*523 ^ ts.tv_nsec*10) ^ ((getpid() % 1000)*983);
72#elif defined HAVE_CLOCK_GETTIME
73 struct timespec ts;
74 clock_gettime(CLOCK_REALTIME, &ts);
75 li=((ts.tv_sec % 10000)*523 ^ ts.tv_nsec*10) ^ ((getpid() % 1000)*983);
76#elif defined HAVE_GETTIMEOFDAY
77 struct timeval tv;
78 gettimeofday(&tv, 0);
79 li=((tv.tv_sec % 10000)*523 ^ tv.tv_usec*13) ^ ((getpid() % 1000)*983);
80#else
81 li=(unsigned int)time(NULL)+(unsigned int)getpid();
82#endif
83 li+=(unsigned int)rand();
84 if(seed) srand(li);
85 //printf("seed := %u\n", li); printf("RAND_MAX := %u\n", RAND_MAX);
86 return(li);
87}

Referenced by tgo().

◆ fintegrate()

int fintegrate ( float * x,
float * y,
int nr,
float * yi )
extern

float version of integrate().

Linear integration from time 0 to x[0..nr-1]. If x[0] is >0 and x[0]<=(x[1]-x[0]), then the beginning is interpolated from it to (0,0).

Returns
Returns 0 if OK, or 1, if error.
See also
integrate, fpetintegrate, finterpolate
Parameters
xOriginal x values; duplicates are not allowed, all must be >=0. Data must be sorted by ascending x
yOriginal y values
nrNr of values
yiArray for integrals

Definition at line 300 of file integr.c.

310 {
311 int j;
312
313 if(nr==1 || x[0]<=(x[1]-x[0])) yi[0]=0.5*y[0]*x[0];
314 else yi[0]=0; /*If the gap in the beginning is longer than time
315 between first and second time point */
316 for(j=1; j<nr; j++) yi[j]=yi[j-1]+0.5*(y[j]+y[j-1])*(x[j]-x[j-1]);
317
318 return 0;
319}

◆ finterpolate()

int finterpolate ( float * x,
float * y,
int nr,
float * newx,
float * newy,
float * newyi,
float * newyii,
int newnr )
extern

float version of interpolate().

It is assumed that both original and new interpolated data represent the actual values at specified time points (not from framed data). The integration is calculated dot-by-dot.

If NULL is specified for newy[], newyi[] and/or newyii[], their values are not calculated.

Original data and new x values must be sorted by ascending x. Subsequent x values can have equal values, enabling the use of step functions. Negative x (time) values can be processed. If necessary, the data is extrapolated assuming that: 1) y[inf]=y[nr-1] and 2) if x[0]>0, y[0]>0 and x[0]<=x[1]-x[0], then an imaginary line is drawn from (0,0) to (x[0],y[0]).

Returns
Non-zero in case of an error.
See also
interpolate, fintegrate
Parameters
xInput data x (time) values
yInput data y values
nrNumber of values in input data
newxOutput data x values
newyInterpolated (extrapolated) y values; NULL can be given if not needed
newyiIntegrals; NULL can be given if not needed
newyii2nd integrals; NULL can be given if not needed
newnrNr of values in output data

Definition at line 161 of file integr.c.

178 {
179 int i, j;
180 float ty, tyi, tyii;
181 float ox1, ox2, oy1, oy2, oi1, oi2, oii1, oii2, dt, ndt;
182 int verbose=0;
183
184 if(verbose>0) printf("in finterpolate()\n");
185 /* Check for data */
186 if(nr<1 || newnr<1) return 1;
187 /* Check that programmer understood that outp data must've been allocated */
188 if(newy==NULL && newyi==NULL && newyii==NULL) return 2;
189
190 /* Initiate first two input samples */
191 ox1=ox2=x[0];
192 oy1=oy2=y[0];
193 /* Extrapolate the initial phase with triangle... */
194 if(ox1>0.0) {
195 oy1=0.0;
196 /* unless:
197 -first input sample y<=0
198 -initial gap is longer than input TAC sampling frequency
199 */
200 if(y[0]>0.0 && (nr>1 && x[0]<=x[1]-x[0])) ox1=0.0;
201 }
202 /* Integrals too */
203 oi1=oii1=0.0;
204 oi2=oi1 + (ox2-ox1)*(oy1+oy2)/2.0;
205 oii2=oii1 + (ox2-ox1)*(oi1+oi2)/2.0;
206
207 /* Set interpolated data before input data (even imaginary) to zero */
208 j=0; while(j<newnr && newx[j]<ox1) {
209 ty=tyi=tyii=0.0;
210 if(newy!=NULL) newy[j]=ty;
211 if(newyi!=NULL) newyi[j]=tyi;
212 if(newyii!=NULL) newyii[j]=tyii;
213 j++;
214 }
215
216 /* Set interpolated data between ox1 and ox2 */
217 dt=ox2-ox1; if(dt>0.0) while(j<newnr && newx[j]<=ox2) {
218 ndt=newx[j]-ox1;
219 ty=((oy2-oy1)/dt)*ndt + oy1; if(newy!=NULL) newy[j]=ty;
220 tyi=oi1 + 0.5*(ty+oy1)*ndt; if(newyi!=NULL) newyi[j]=tyi;
221 if(newyii!=NULL) newyii[j]=tyii= oii1 + 0.5*(tyi+oi1)*ndt;
222 j++;
223 }
224
225 /* Go through input data, sample-by-sample */
226 for(i=0; i<nr && j<newnr; i++) {
227
228 ox1=ox2; oy1=oy2; oi1=oi2; oii1=oii2;
229 ox2=x[i]; oy2=y[i];
230 oi2=oi1 + (ox2-ox1)*(oy1+oy2)/2.0;
231 oii2=oii1 + (ox2-ox1)*(oi1+oi2)/2.0;
232
233 /* Calculate input sample distance */
234 dt=ox2-ox1; if(dt<0.0) return 3; else if(dt==0.0) continue;
235
236 /* Any need for interpolation between ox1 and ox2? */
237 while(j<newnr && newx[j]<=ox2) {
238 ndt=newx[j]-ox1;
239 ty=((oy2-oy1)/dt)*ndt + oy1; if(newy!=NULL) newy[j]=ty;
240 tyi=oi1 + 0.5*(ty+oy1)*ndt; if(newyi!=NULL) newyi[j]=tyi;
241 if(newyii!=NULL) newyii[j]=tyii= oii1 + 0.5*(tyi+oi1)*ndt;
242 j++;
243 }
244
245 } // next input sample
246
247 /* Set interpolated data after input data, assuming steady input */
248 while(j<newnr) {
249 ndt=newx[j]-ox2;
250 ty=oy2;
251 tyi=oi2 + oy2*ndt;
252 tyii=oii2 + 0.5*(tyi+oi2)*ndt;
253 if(newy!=NULL) newy[j]=ty;
254 if(newyi!=NULL) newyi[j]=tyi;
255 if(newyii!=NULL) newyii[j]=tyii;
256 j++;
257 }
258
259 if(verbose>0) printf("out finterpolate()\n");
260 return 0;
261}

Referenced by finterpolate4pet(), and imgTimeIntegral().

◆ finterpolate4pet()

int finterpolate4pet ( float * x,
float * y,
int nr,
float * newx1,
float * newx2,
float * newy,
float * newyi,
float * newyii,
int newnr )
extern

Interpolate and integrate TAC to PET frames. Float version of interpolate4pet().

It is assumed, that original data is not from framed data, but that the values represent the actual value at specified time point, which allows the integration to be calculated dot-by-dot.

If NULL is specified for *newy, *newyi and/or *newyii, their values are not calculated.

Original data and new x values must be sorted by ascending x. Subsequent x values can have equal values, enabling the use of step functions. PET frames can overlap, but interpolation may then be slower. Negative x (time) values can be processed. If necessary, the data is extrapolated assuming that 1) y[inf]=y[nr-1] and 2) if x[0]>0 and y[0]>0 and x[0]>x[1]-x[0], then an imaginary line is drawn from (0,0) to (x[0],y[0]).

Returns
Non-zero in case of an error.
See also
fpetintegral, interpolate4pet, fintegrate
Parameters
xTimes of original data
yValues of original data
nrNumber of original data values
newx1PET frame start times; frames may overlap
newx2PET frame end times; frames may overlap
newyMean value during PET frame, or NULL if not needed; calculation may be faster if newyi is calculated too
newyiIntegral at frame mid time, or NULL if not needed
newyii2nd integral at frame mid time, or NULL if not needed
newnrNumber of PET frames

Definition at line 646 of file integr.c.

666 {
667 int ret, fi, overlap=0, zeroframe=0;
668 float petx[3], pety[3], petyi[3], petyii[3], fdur;
669 int verbose=0;
670
671 if(verbose>0) printf("in finterpolate4pet()\n");
672
673 /* Check for data */
674 if(nr<1 || newnr<1) return 1;
675 /* Check that programmer understood that outp data must've been allocated */
676 if(newy==NULL && newyi==NULL && newyii==NULL) return 2;
677 /* Check that input data is not totally outside the input data */
678 if(newx2[newnr-1]<=x[0] || newx1[0]>=x[nr-1]) return 3;
679
680 /* Check frame lengths, also for overlap and zero length frames */
681 for(fi=0; fi<newnr; fi++) {
682 /* Calculate frame length */
683 fdur=newx2[fi]-newx1[fi];
684 /* If frame length is <0, that is an error */
685 if(fdur<0.0) return 4;
686 if(fdur==0.0) zeroframe++;
687 /* Overlap? */
688 if(fi>0 && newx2[fi-1]>newx1[fi]) overlap++;
689 }
690 if(verbose>1) {
691 printf("overlap := %d\n", overlap);
692 printf("zeroframe := %d\n", zeroframe);
693 }
694
695 /* Interpolate and integrate one frame at a time, if there is:
696 -overlap in frames
697 -frames of zero length
698 -only few interpolated frames
699 -if only integrals are needed
700 -if neither of integrals is needed, then there is no temp memory to
701 do otherwise
702 */
703 if(overlap>0 || zeroframe>0 || newnr<=3 || newy==NULL || (newyi==NULL && newyii==NULL) ) {
704
705 if(verbose>1) printf("frame-by-frame interpolation/integration\n");
706 for(fi=0; fi<newnr; fi++) {
707 /* Set frame start, middle and end times */
708 petx[0]=newx1[fi]; petx[2]=newx2[fi]; petx[1]=0.5*(petx[0]+petx[2]);
709 /* Calculate frame length */
710 fdur=petx[2]-petx[0];
711 /* If frame length is <0, that is an error */
712 if(fdur<0.0) return 4;
713 /* If frame length is 0, then use direct interpolation */
714 if(fdur==0.0) {
715 ret=finterpolate(x, y, nr, petx, pety, petyi, petyii, 1);
716 if(ret) return 10+ret;
717 if(newy!=NULL) newy[fi]=petyi[0];
718 if(newyi!=NULL) newyi[fi]=petyi[0];
719 if(newyii!=NULL) newyii[fi]=petyii[0];
720 continue;
721 }
722 /* Calculate integrals at frame start, middle, and end */
723 ret=finterpolate(x, y, nr, petx, NULL, petyi, petyii, 3);
724 if(ret) return 20+ret;
725 /* Set output integrals, if required */
726 if(newyi!=NULL) newyi[fi]=petyi[1];
727 if(newyii!=NULL) newyii[fi]=petyii[1];
728 /* Calculate frame mean, if required */
729 if(newy!=NULL) newy[fi]=(petyi[2]-petyi[0])/fdur;
730 } // next frame
731
732 } else {
733
734 if(verbose>1) printf("all-frames-at-once interpolation/integration\n");
735 /* Set temp array */
736 float *tp; if(newyii!=NULL) tp=newyii; else tp=newyi;
737 /* Integrate at frame start times */
738 ret=finterpolate(x, y, nr, newx1, NULL, tp, NULL, newnr);
739 if(ret) return 10+ret;
740 /* Integrate at frame end times */
741 ret=finterpolate(x, y, nr, newx2, NULL, newy, NULL, newnr);
742 if(ret) return 10+ret;
743 /* Calculate average frame value */
744 for(fi=0; fi<newnr; fi++)
745 newy[fi]=(newy[fi]-tp[fi])/(newx2[fi]-newx1[fi]);
746 /* Calculate integrals */
747 if(newyi!=NULL || newyii!=NULL) {
748 for(fi=0; fi<newnr; fi++) newx1[fi]+=0.5*(newx2[fi]-newx1[fi]);
749 ret=finterpolate(x, y, nr, newx1, NULL, newyi, newyii, newnr);
750 if(ret) return 10+ret;
751 for(fi=0; fi<newnr; fi++) newx1[fi]-=(newx2[fi]-newx1[fi]);
752 }
753
754 }
755
756 if(verbose>0) printf("out finterpolate4pet()\n");
757 return 0;
758}
int finterpolate(float *x, float *y, int nr, float *newx, float *newy, float *newyi, float *newyii, int newnr)
float version of interpolate().
Definition integr.c:161

◆ fitExpDecayNNLS()

int fitExpDecayNNLS ( double * x,
double * y,
int n,
double fittime,
double kmin,
double kmax,
int pnr,
double * a,
double * k,
int * fnr,
int verbose )
extern

Estimate initial values for sum of exponentials to be fitted on decaying x,y-data.

Returns
0 when successful, otherwise <>0.
Parameters
xPointer to array of x values; must not contain NaNs; data is not changed; samples must be sorted by increasing x.
yPointer to array of y values; must not contain NaNs; data is not changed.
nNr of x and y samples (x and y array lengths); data is not changed.
fittimeFittime is usually set to <=0 or a very high value to start the search for the best line fit from the last x,y sample towards the first sample; However, to exclude the end phase you may want to set fittime to include only certain time range from the beginning.
kminMinimum eigenvalue, must be >0; for example, 1.0E-06.
kmaxMaximum eigenvalue; for example, 1.0E+03.
pnrMax number of exp functions to save; length of a[] and k[] arrays.
aPointer to an array of length pnr where exp function coefficients will be written; enter NULL if not needed.
kPointer to an array of length pnr where exp function eigenvalues will be written; enter NULL if not needed.
fnrThe number of fitted exponentials will be written in here; note that this number may be higher than pnr; enter NULL if not needed.
verboseVerbose level; if zero, then nothing is printed to stderr or stdout

Definition at line 100 of file constraints.c.

130 {
131 if(verbose>0)
132 printf("fitExpDecayNNLS(x, y, %d, %g, %g, %g, ...)\n", n, fittime, kmin, kmax);
133 if(n<3) return(1);
134 if(fittime>0.0) {
135 while(x[n-1]>fittime && n>0) n--;
136 if(verbose>1) printf(" n := %d\n", n);
137 }
138 if(kmin<1.0E-100) kmin=1.0E-100;
139 if(kmax<=kmin) return(1);
140
141 /* Allocate memory for NNLS */
142 int NNLS_N=100;
143 int nn, mm, nnls_n, nnls_m, nnls_index[NNLS_N];
144 double *nnls_a[NNLS_N], *nnls_b, *nnls_zz, nnls_x[NNLS_N], *nnls_mat,
145 nnls_wp[NNLS_N], *dptr, nnls_rnorm;
146
147 nnls_n=NNLS_N;
148 nnls_m=n;
149 nnls_mat=(double*)malloc(((nnls_n+2)*nnls_m)*sizeof(double));
150 if(nnls_mat==NULL) return(2);
151 for(nn=0, dptr=nnls_mat; nn<nnls_n; nn++) {nnls_a[nn]=dptr; dptr+=nnls_m;}
152 nnls_b=dptr; dptr+=nnls_m; nnls_zz=dptr;
153
154 /* Set exponent function decay parameters */
155 double epar[NNLS_N];
156 {
157 double elnmin, elnmax;
158 elnmin=log(kmin); elnmax=log(kmax);
159 //double elnmin=-12.5, elnmax=6.7;
160 double d, r;
161 r=elnmax-elnmin;
162 d=r/(double)(NNLS_N-1);
163 for(nn=0; nn<nnls_n; nn++) epar[nn]=-exp(elnmin+(double)nn*d);
164 }
165
166 /* Fill NNLS matrix */
167 for(mm=0; mm<nnls_m; mm++) {
168 nnls_b[mm]=y[mm];
169 }
170 for(nn=0; nn<nnls_n; nn++)
171 for(mm=0; mm<nnls_m; mm++)
172 nnls_a[nn][mm]=exp(epar[nn]*x[mm]);
173
174 /* NNLS */
175 int ret;
176 ret=nnls(nnls_a, nnls_m, nnls_n, nnls_b, nnls_x, &nnls_rnorm,
177 nnls_wp, nnls_zz, nnls_index);
178 if(ret>1) {
179 if(verbose>0) fprintf(stderr, "Error: NNLS solution not possible.\n");
180 free(nnls_mat);
181 return(3);
182 } else if(ret==1) {
183 if(verbose>0) fprintf(stderr, "Warning: max iteration count exceeded in NNLS.\n");
184 }
185 if(verbose>2) {
186 printf("NNLS results:\n");
187 for(nn=0; nn<nnls_n; nn++)
188 printf("\t%e\t%g\t%g\n", epar[nn], nnls_x[nn], nnls_wp[nn]);
189 }
190 if(verbose>1) {
191 printf("Reasonable NNLS results:\n");
192 for(nn=0; nn<nnls_n; nn++)
193 if(nnls_wp[nn]==0.0) printf("\t%e\t%g\n", epar[nn], nnls_x[nn]);
194 }
195
196 /* Reset exponent function decay parameters with the clusters found above */
197 {
198 if(verbose>1) printf("Cluster means:\n");
199 int i, j, nr;
200 double ev;
201 i=j=0;
202 while(1) {
203 /* jump over functions with wp<0 */
204 while(i<nnls_n && nnls_wp[i]<0.0) i++;
205 if(i==nnls_n) break;
206 /* calculate mean of this cluster */
207 nr=0; ev=0.0;
208 while(i<nnls_n && nnls_wp[i]==0.0) {nr++; ev+=epar[i]; i++;}
209 ev/=(double)nr;
210 if(verbose>1) printf("mean_e := %e\n", ev);
211 epar[j++]=ev;
212 }
213 nnls_n=j;
214 }
215
216 /* Fill NNLS matrix with these functions */
217 for(mm=0; mm<nnls_m; mm++) {
218 nnls_b[mm]=y[mm];
219 }
220 for(nn=0; nn<nnls_n; nn++)
221 for(mm=0; mm<nnls_m; mm++)
222 nnls_a[nn][mm]=exp(epar[nn]*x[mm]);
223
224 /* NNLS */
225 ret=nnls(nnls_a, nnls_m, nnls_n, nnls_b, nnls_x, &nnls_rnorm,
226 nnls_wp, nnls_zz, nnls_index);
227 if(ret>1) {
228 if(verbose>0) fprintf(stderr, "Error: NNLS solution not possible.\n");
229 free(nnls_mat);
230 return(3);
231 } else if(ret==1) {
232 if(verbose>0) fprintf(stderr, "Warning: max iteration count exceeded in NNLS.\n");
233 }
234 if(verbose>1) {
235 printf("NNLS results:\n");
236 for(nn=0; nn<nnls_n; nn++)
237 printf("\t%e\t%g\t%g\n", epar[nn], nnls_x[nn], nnls_wp[nn]);
238 }
239
240 /* Return the results */
241 int nr=0;
242 for(nn=0; nn<nnls_n; nn++) {
243 if(nnls_wp[nn]<0.0) continue;
244 if(nr>=pnr) {nr++; continue;}
245 if(a!=NULL) a[nr]=nnls_x[nn];
246 if(k!=NULL) k[nr]=epar[nn];
247 nr++;
248 }
249 if(fnr!=NULL) *fnr=nr;
250
251 free(nnls_mat);
252 return(0);
253}
int nnls(double **a, int m, int n, double *b, double *x, double *rnorm, double *w, double *zz, int *index)
Definition nnls.c:38

◆ fixed_params()

int fixed_params ( int n,
const double * lower,
const double * upper,
const double * delta )
extern

Determine how many of model parameters are fixed.

Returns
Returns the nr of fixed parameters.
Parameters
nTotal nr of parameters
lowerList of lower parameter limits
upperList of upper parameter limits
deltaList of parameter deltas; enter NULL if not available

Definition at line 418 of file bobyqa.c.

427 {
428 int i, fixed_n=0;
429 for(i=0; i<n; i++) {
430 if(upper[i]<=lower[i]) {fixed_n++; continue;}
431 if(delta!=NULL && delta[i]==0.0) fixed_n++;
432 }
433 return(fixed_n);
434}

Referenced by bobyqa().

◆ fpetintegral()

int fpetintegral ( float * x1,
float * x2,
float * y,
int nr,
float * ie,
float * iie )
extern

Integrate PET TAC data to frame mid times. Float version of petintegral().

Any of output arrays may be set to NULL if that is not needed. Frames must be in ascending time order. Gaps and small overlap are allowed. If x1[0]>0 and x1[0]<=x2[0]-x1[0], then an imaginary line is drawn from (0,0) to (x[0],y[0]).

Returns
Returns 0 if ok.
See also
petintegral, finterpolate4pet
Parameters
x1frame start times
x2frame end times
yavg value during frame
nrnumber of frames
ieintegrals at frame mid time
iie2nd integrals at frame mid time

Definition at line 838 of file integr.c.

851 {
852 int i;
853 float x, last_x, last_x2, last_y, last_integral, box_integral, half_integral;
854 float gap_integral, integral, integral2, frame_len, xdist, s;
855
856 /* Check for data */
857 if(nr<1 || nr<1) return(1);
858 /* Check that programmer understood that output must've been allocated */
859 if(ie==NULL && iie==NULL) return(2);
860
861 /* Initiate values to zero */
862 last_x=last_x2=last_y=last_integral=0.0;
863 box_integral=gap_integral=integral=integral2=frame_len=0.0;
864
865 for(i=0; i<nr; i++) {
866 frame_len=x2[i]-x1[i]; if(frame_len<0.0) return(5);
867 x=0.5*(x1[i]+x2[i]); xdist=x-last_x; if(last_x>0.0 && xdist<=0.0) return(6);
868 if(x<0) {
869 if(ie!=NULL) ie[i]=integral;
870 if(iie!=NULL) iie[i]=integral2;
871 continue;
872 }
873 s=(y[i]-last_y)/xdist; /* slope */
874 /*If there is a big gap in the beginning it is eliminated */
875 if(i==0)if(x1[0]>x2[0]-x1[0]){last_x2=last_x=x1[0];}
876 /*Integral of a possible gap between frames*/
877 gap_integral=(x1[i]-last_x2)*(last_y+s*((last_x2+x1[i])/2.0-last_x));
878 /*Integral from the beginning of the frame i to the middle of the frame */
879 half_integral=(x-x1[i])*(last_y+s*((x1[i]+x)/2.0-last_x));
880 integral=box_integral+gap_integral+half_integral;
881 /* half_integral is not added to box because it is more accurate to
882 sum integrals of full frames */
883 box_integral+=gap_integral+frame_len*y[i];
884 integral2+=xdist*(integral+last_integral)*0.5;
885 if(ie!=NULL) ie[i]=integral;
886 if(iie!=NULL) iie[i]=integral2;
887 last_x=x; last_x2=x2[i];
888 last_y=y[i]; last_integral=integral;
889 }
890
891 return(0);
892}

Referenced by img_logan(), and img_patlak().

◆ fpetintegrate()

int fpetintegrate ( float * x1,
float * x2,
float * y,
int nr,
float * newyi,
float * newyii )
extern

Calculates integrals of PET data at frame end times. Float version of petintegrate().

Data does not have to be continuous, but it must be increasing in time. For faster performance in repetitive calls, allocate memory for integral[] even if it is not needed. If x1[0] is >0 AND x1[0] is <=(x2[0]-x1[0]), then the beginning is interpolated from (0, 0) to (x1[0], y1[0]*x1[0]/x) where x is midtime of the first frame.

Returns
Returns 0 if ok.
See also
petintegrate, finterpolate, fintegrate, finterpolate4pet, fpetintegrate2fe
Parameters
x1Array of frame start times
x2Array of frame end times
yArray of y values (avg during each frame)
nrNr of frames
newyiOutput: integral values at frame end times, or NULL
newyiiOutput: 2nd integral values at frame end times, or NULL

Definition at line 418 of file integr.c.

431 {
432 int i, allocated=0;
433 float *ti, x, a;
434
435
436 /* Check that data is increasing in time and is not (much) overlapping */
437 if(nr<1 || x1[0]<0) return 1;
438 for(i=0; i<nr; i++) if(x2[i]<x1[i]) return 2;
439 for(i=1; i<nr; i++) if(x1[i]<=x1[i-1]) return 3;
440
441 /* Allocate memory for temp data, if necessary */
442 if(newyi==NULL) {
443 allocated=1;
444 ti=(float*)malloc(nr*sizeof(float)); if(ti==NULL) return 4;
445 } else
446 ti=newyi;
447
448 /* Calculate the integral at the end of first frame */
449 ti[0]=(x2[0]-x1[0])*y[0];
450 /* If frame does not start at 0 time, add the area in the beginning */
451 /* But only if the gap in the beginning is less than the lenght of the
452 first frame */
453 if(x1[0]>0) {
454 if(x1[0]<=x2[0]-x1[0]) {
455 x=(x1[0]+x2[0])/2.0;
456 a=(x1[0]*(y[0]/x)*x1[0])/2.0;
457 ti[0]+=a;
458 }
459 }
460
461 /* Calculate integrals at the ends of following frames */
462 for(i=1; i<nr; i++) {
463 /* Add the area of this frame to the previous integral */
464 a=(x2[i]-x1[i])*y[i]; ti[i]=ti[i-1]+a;
465 /* Check whether frames are contiguous */
466 if(x1[i]==x2[i-1]) continue;
467 /* When not, calculate the area of an imaginary frame */
468 x=(x1[i]+x2[i-1])/2.0;
469 a=(x1[i]-x2[i-1])*
470 (y[i]-(y[i]-y[i-1])*(x2[i]+x1[i]-2.0*x)/(x2[i]+x1[i]-x2[i-1]-x1[i-1]));
471 ti[i]+=a;
472 }
473
474 /* Copy integrals to output if required */
475 if(allocated) for(i=0; i<nr; i++) newyi[i]=ti[i];
476
477 /* Calculate 2nd integrals if required */
478 if(newyii!=NULL) {
479 newyii[0]=x2[0]*ti[0]/2.0;
480 for(i=1; i<nr; i++)
481 newyii[i]=newyii[i-1]+(x2[i]-x2[i-1])*(ti[i-1]+ti[i])/2.0;
482 }
483
484 /* Free memory */
485 if(allocated) free((char*)ti);
486
487 return 0;
488}

◆ fpetintegrate2fe()

int fpetintegrate2fe ( float * x1,
float * x2,
float * y,
int nr,
float * e,
float * ie,
float * iie )
extern

Integrate PET TAC data to frame end times. Float version of petintegrate2fe().

Any of output arrays may be set to NULL if that is not needed. Frames must be in ascending time order. Gaps and small overlap are allowed. If x1[0]>0 and x1[0]<=x2[0]-x1[0], then an imaginary line is drawn from (0,0) to (x[0],y[0]).

Returns
Returns 0 if ok.
See also
petintegrate2fe
Parameters
x1frame start times
x2frame end times
yavg value during frame
nrnumber of frames
evalues at frame end time
ieintegrals at frame end time
iie2nd integrals at frame end time

Definition at line 974 of file integr.c.

989 {
990 int i;
991 float x, last_x, last_x2, last_y, last_integral;
992 float value, integral, integral2, frame_len, xdist, s;
993
994 /* Check for data */
995 if(nr<1 || nr<1) return(1);
996 /* Check that programmer understood that output must've been allocated */
997 if(e==NULL && ie==NULL && iie==NULL) return(2);
998
999 /* Initiate values to zero */
1000 last_x=last_x2=last_y=last_integral=value=integral=integral2=frame_len=s=0.0;
1001
1002 for(i=0; i<nr; i++) {
1003 frame_len=x2[i]-x1[i]; if(frame_len<0.0) return(5);
1004 x=0.5*(x1[i]+x2[i]); xdist=x-last_x; if(last_x>0.0 && xdist<=0.0) return(6);
1005 if(x<0) {
1006 if(e!=NULL) e[i]=value;
1007 if(ie!=NULL) ie[i]=integral;
1008 if(iie!=NULL) iie[i]=integral2;
1009 continue;
1010 }
1011 s=(y[i]-last_y)/xdist; /* slope between x[i-1] and x[i] */
1012 /* If there is a big gap in the beginning, it is eliminated */
1013 if(i==0 && x1[0]>x2[0]-x1[0]) {last_x2=last_x=x1[0];}
1014 integral+=(x1[i]-last_x2)*(last_y+s*((last_x2+x1[i])/2.0-last_x)); /*gap*/
1015 integral+=frame_len*y[i];
1016 integral2+=(x2[i]-last_x2)*(integral+last_integral)*0.5;
1017 if(e!=NULL && i>0) {
1018 value=last_y+s*(last_x2-last_x); /* value at previous frame end */
1019 e[i-1]=value;
1020 }
1021 if(ie!=NULL) ie[i]=integral;
1022 if(iie!=NULL) iie[i]=integral2;
1023 last_x=x; last_x2=x2[i]; last_y=y[i]; last_integral=integral;
1024 }
1025 if(e!=NULL) {
1026 value=last_y+s*(last_x2-last_x); /* Value for the last frame */
1027 e[i-1]=value;
1028 }
1029
1030 return(0);
1031}

◆ gaussdev()

double gaussdev ( )
extern

Applies the polar form of Box-Müller transform to produce pseudo-random numbers with Gaussian (normal) distribution which has a zero mean and standard deviation of one. Box GEP, Muller ME. A note on the generation of random normal deviates. Annals of Mathematical Statistics, Volume 29, Issue 2, 1958, 610-611. Available from JSTOR https://www.jstor.org/

Returns
Returns the pseudo-random number.
See also
gaussdev2, drand

Definition at line 30 of file gaussdev.c.

31{
32 static int ready=0, first=1;
33 static double dev;
34 double fac, rsq, a, b;
35 if(first) {first=0; init_gaussdev();}
36
37 /* If we don't have deviate already, then we'll have to make one */
38 if(!ready) {
39 do {
40 //a = 2.*(double)rand()/(double)RAND_MAX - 1.0;
41 //b = 2.*(double)rand()/(double)RAND_MAX - 1.0;
42 a = 2.*drand() - 1.0;
43 b = 2.*drand() - 1.0;
44 rsq = a*a + b*b;
45 } while (rsq>=1.0 || rsq==0.0);
46
47 fac = sqrt(-2.0*log(rsq)/rsq);
48 dev=a*fac; ready=1;
49 return(b*fac);
50 } else { /* dev is ready so return it */
51 ready=0;
52 return(dev);
53 }
54}
double drand()
Definition gaussdev.c:142
void init_gaussdev()
Definition gaussdev.c:92

◆ gaussdev2()

double gaussdev2 ( )
extern

Applies the polar form of Box-Müller transform to produce pseudo-random numbers with Gaussian (normal) distribution which has a zero mean and standard deviation of one. This function does never set seed, like gaussdev() does, therefore set seed for random number generator before first calling this routine, for example with srand(time(NULL));

Box GEP, Muller ME. A note on the generation of random normal deviates. Annals of Mathematical Statistics, Volume 29, Issue 2, 1958, 610-611. Available from JSTOR https://www.jstor.org/

Returns
Returns the pseudo-random number.
See also
gaussdev, drand

Definition at line 112 of file gaussdev.c.

113{
114 static int ready=0;
115 static double dev;
116 double fac, rsq, a, b;
117
118 /* If we don't have deviate already, then we'll have to make one */
119 if(!ready) {
120 do {
121 a = 2.*drand() - 1.0;
122 b = 2.*drand() - 1.0;
123 rsq = a*a + b*b;
124 } while (rsq>=1.0 || rsq==0.0);
125
126 fac = sqrt(-2.0*log(rsq)/rsq);
127 dev=a*fac; ready=1;
128 return(b*fac);
129 } else { /* dev is ready so return it */
130 ready=0;
131 return(dev);
132 }
133}

◆ highest_slope()

int highest_slope ( double * x,
double * y,
int n,
int slope_n,
double * m,
double * c,
double * xi,
double * xh )
extern

Finds the regression line with the highest slope for x,y data.

See also
highest_slope_after, regr_line, best_pearson
Returns
Return 0 if ok.
Parameters
xAn array of x axis values
yAn array of y axis values
nThe number of values in x and y arrays
slope_nThe number of samples used to fit the line
mPointer where calculated slope is written; NULL if not needed
cPointer where calculated y axis intercept is written; NULL if not needed
xiPointer where calculated x axis intercept is written; NULL if not needed
xhPointer where the place (x) of the highest slope is written; NULL if not needed

Definition at line 424 of file pearson.c.

442 {
443 int i, ret, i_at_max=0;
444 double slope, ic, max_slope, ic_at_max=0.0;
445
446 /* Check the data */
447 if(x==NULL || y==NULL) return(1);
448 if(n<2) return(2);
449 if(slope_n>n) return(3);
450
451 /* Compute */
452 max_slope=-1.0E200;
453 for(i=0; i<=n-slope_n; i++) {
454 ret=regr_line(x+i, y+i, slope_n, &slope, &ic); if(ret) continue;
455 if(slope>max_slope) {max_slope=slope; ic_at_max=ic; i_at_max=i;}
456 } /* next slope */
457 if(max_slope==-1.0E200) return(10);
458 if(m!=NULL) *m=max_slope;
459 if(c!=NULL) *c=ic_at_max;
460 if(xi!=NULL) {if(max_slope!=0.0) *xi=-ic_at_max/max_slope; else *xi=0.0;}
461 if(xh!=NULL) {
462 *xh=0.0; for(i=i_at_max; i<i_at_max+slope_n; i++) *xh+=x[i];
463 *xh/=(double)slope_n;
464 }
465
466 return(0);
467}
int regr_line(double *x, double *y, int n, double *m, double *c)
Definition pearson.c:387

Referenced by dftFixPeak().

◆ highest_slope_after()

int highest_slope_after ( double * x,
double * y,
int n,
int slope_n,
double x_start,
double * m,
double * c,
double * xi,
double * xh )
extern

Finds the regression line with the highest slope for x,y data after specified x.

See also
highest_slope, regr_line
Returns
Return 0 if ok.
Parameters
xAn array of x axis values.
yAn array of y axis values.
nThe number of values in x and y arrays.
slope_nThe number of samples used to fit the line.
x_startEstimation start x value, samples with smaller x are ignored; can usually be set to zero.
mPointer where calculated slope is written; NULL if not needed.
cPointer where calculated y axis intercept is written; NULL if not needed.
xiPointer where calculated x axis intercept is written; NULL if not needed.
xhPointer where the place (x) of the highest slope is written; NULL if not needed.

Definition at line 475 of file pearson.c.

495 {
496 int i, ret, i_at_max=0;
497 double slope, ic, max_slope, ic_at_max=0.0;
498
499 /* Check the data */
500 if(x==NULL || y==NULL) return(1);
501 if(n<2) return(2);
502 if(slope_n>n) return(3);
503
504 /* Compute */
505 max_slope=-1.0E200;
506 for(i=0; i<=n-slope_n; i++) if(x[i]>=x_start) {
507 ret=regr_line(x+i, y+i, slope_n, &slope, &ic); if(ret) continue;
508 if(slope>max_slope) {max_slope=slope; ic_at_max=ic; i_at_max=i;}
509 } /* next slope */
510 if(max_slope==-1.0E200) return(10);
511 if(m!=NULL) *m=max_slope;
512 if(c!=NULL) *c=ic_at_max;
513 if(xi!=NULL) {if(max_slope!=0.0) *xi=-ic_at_max/max_slope; else *xi=0.0;}
514 if(xh!=NULL) {
515 *xh=0.0; for(i=i_at_max; i<i_at_max+slope_n; i++) *xh+=x[i];
516 *xh/=(double)slope_n;
517 }
518
519 return(0);
520}

◆ householder_hm()

int householder_hm ( double tau,
double * vector,
double ** matrix,
int rowNr,
int columnNr )
extern

Applies a householder transformation defined by vector "vector" and scalar tau to the left-hand side of the matrix. (I - tau vector vector^T)*matrix The result of the transform is stored in matrix.

Returns
Returns 0 if ok.
Parameters
tauCoefficient defining householder transform.
vectorVector defining householder transform (of size rowNr).
matrixthe matrix that is to be transformed.
rowNrNr of rows in matrix.
columnNrNr of columns in matrix.

Definition at line 68 of file hholder.c.

79 {
80 int i, j;
81 double wj;
82
83 if(tau==0.0) return(0); // success
84 if(rowNr<1 || columnNr<1) return(1);
85 for(j=0; j<columnNr; j++) {
86 /* Compute wj = vk Akj */
87 wj=matrix[0][j];
88 for(i=1; i<rowNr; i++) /* note, computed for v(0) = 1 above */
89 wj += vector[i]*matrix[i][j];
90 /* Aij = Aij - tau vi wj */
91 /* i = 0 */
92 matrix[0][j]-=tau*wj;
93 /* i = 1 .. M-1 */
94 for(i=1; i<rowNr; i++) matrix[i][j]-=tau*vector[i]*wj;
95 }
96 return(0);
97}

Referenced by qr_decomp().

◆ householder_hv()

int householder_hv ( double tau,
int size,
double * v,
double * w )
extern

Applies a householder transformation defined by vector v and coefficient tau to vector w w = (I - tau v v^T) w.

Returns
Returns 0 if ok.
Parameters
tauCoefficient defining householder transform.
sizeSize of vectors v and w.
vVector v.
wVector w.

Definition at line 107 of file hholder.c.

116 {
117 int i;
118 double d;
119
120 if(tau==0) return(0); // success
121 if(size<1) return(1);
122 /* d = v'w */
123 d=w[0]; for(i=1; i<size; i++) d+=v[i]*w[i];
124 /* w = w - tau (v) (v'w) */
125 w[0]-=tau*d;
126 for(i=1; i<size; i++) w[i]-=tau*v[i]*d;
127 return(0);
128}

Referenced by qr_solve().

◆ householder_norm()

double householder_norm ( double * v,
int size )
extern

Calculates the euclidean norm of vector v[].

Returns
Returns the euclidean norm of a vector.
Parameters
vVector v
sizeSize of vector v[]

Definition at line 136 of file hholder.c.

141 {
142 double help;
143 int i;
144
145 for(i=0, help=0; i<size; i++) help+=v[i]*v[i];
146 return sqrt(help);
147}

◆ householder_transform()

double householder_transform ( double * v,
int N )
extern

This function prepares a Householder transformation P = I - tau h h^T which can be used to zero all the elements of the input vector except the first one that will get value beta. On output the elements 1 - size-1 of the vector h are stored in locations vector[1] - vector[size-1] of the input vector and value of beta is stored in location vector[0].

Returns
The scalar tau is returned.
Parameters
vThe N-vector to be transformed.
Nsize of the vector.

Definition at line 23 of file hholder.c.

28 {
29 double vnorm, alpha, beta, tau;
30
31 if(N<1) return 0.0; // tau = 0
32 /* Euclidean norm of the vector starting from the second value */
33 vnorm=0.0; for(int n=1; n<N; n++) vnorm+=v[n]*v[n];
34 vnorm=sqrt(vnorm); if(isnan(vnorm) || vnorm==0.0) return 0.0; // tau = 0
35
36 /* Computing the coefficient tau */
37 alpha=v[0];
38 beta= - (alpha >= 0.0 ? +1.0 : -1.0) * hypot(alpha, vnorm);
39 tau=(beta-alpha)/beta ;
40
41 /* Scale the Householder vector so that the first element will be 1.
42 * (Scaling is also affecting the coefficient tau).
43 * Without scaling, the first element would have value (alpha - beta). */
44 {
45 double s=alpha-beta;
46 if(fabs(s)>DBL_MIN) {
47 v[0]=beta;
48 for(int n=1; n<N; n++) v[n]*=(1.0/s);
49 } else {
50 v[0]=beta;
51 for(int n=1; n<N; n++) v[n]*=(doubleMachEps()/s);
52 for(int n=1; n<N; n++) v[n]*=(1.0/doubleMachEps());
53 }
54 }
55
56 return tau;
57}
double doubleMachEps()
Definition doubleutil.c:83

Referenced by qr_decomp().

◆ huber()

double huber ( double x,
double b )
extern

Hubers function.

Returns
Returns x if |x|<b, and b otherwise.
Parameters
xparameter x
bcutoff point

Definition at line 53 of file mestim.c.

58 {
59 double help;
60
61 if(x<-b) help=-b; else help=x;
62 if(help<b) {return help;} else {return b;}
63}

Referenced by mEstim().

◆ init_gaussdev()

void init_gaussdev ( )
extern

Initiate random number generator for gaussdev()

Definition at line 92 of file gaussdev.c.

93{
94 if(GAUSSDEV_SEED<1L) GAUSSDEV_SEED=893165470L;
95 srand(GAUSSDEV_SEED);
96}
long int GAUSSDEV_SEED
Definition gaussdev.c:7

Referenced by gaussdev().

◆ integrate()

int integrate ( double * x,
double * y,
int nr,
double * yi )
extern

Linear integration from time 0 to x[0..nr-1]. If x[0] is >0 and x[0]<=(x[1]-x[0]), then the beginning is interpolated from it to (0,0).

Returns
Returns 0 if OK, or 1, if error.
See also
fintegrate, petintegrate, interpolate
Parameters
xOriginal x values; duplicates are not allowed, all must be >=0. Data must be sorted by ascending x
yOriginal y values
nrNr of values
yiArray for integrals

Definition at line 271 of file integr.c.

281 {
282 int j;
283
284 if(nr==1 || x[0]<=(x[1]-x[0])) yi[0]=0.5*y[0]*x[0];
285 else yi[0]=0; /*If the gap in the beginning is longer than time
286 between first and second time point */
287 for(j=1; j<nr; j++) yi[j]=yi[j-1]+0.5*(y[j]+y[j-1])*(x[j]-x[j-1]);
288
289 return 0;
290}

Referenced by dftReadReference().

◆ interpolate()

int interpolate ( double * x,
double * y,
int nr,
double * newx,
double * newy,
double * newyi,
double * newyii,
int newnr )
extern

Linear interpolation and integration.

It is assumed that both original and new interpolated data represent the actual values at specified time points (not from framed data). The integration is calculated dot-by-dot.

If NULL is specified for newy[], newyi[] and/or newyii[], their values are not calculated.

Original data and new x values must be sorted by ascending x. Subsequent x values can have equal values, enabling the use of step functions. Negative x (time) values can be processed. If necessary, the data is extrapolated assuming that: 1) y[inf]=y[nr-1] and 2) if x[0]>0, y[0]>0 and x[0]<=x[1]-x[0], then an imaginary line is drawn from (0,0) to (x[0],y[0]).

Returns
Non-zero in case of an error.
See also
finterpolate, integrate, petintegrate, petintegral, dftTimeIntegral
Parameters
xInput data x (time) values
yInput data y values
nrNumber of values in input data
newxOutput data x values
newyInterpolated (extrapolated) y values; NULL can be given if not needed
newyiIntegrals; NULL can be given if not needed
newyii2nd integrals; NULL can be given if not needed
newnrNr of values in output data

Definition at line 28 of file integr.c.

45 {
46 int i, j;
47 double ty, tyi, tyii;
48 double ox1, ox2, oy1, oy2, oi1, oi2, oii1, oii2, dt, ndt;
49 int verbose=0;
50
51 if(verbose>0) printf("in interpolate()\n");
52 /* Check for data */
53 if(nr<1 || newnr<1) return 1;
54 /* Check that programmer understood that outp data must've been allocated */
55 if(newy==NULL && newyi==NULL && newyii==NULL) return 2;
56
57 /* Initiate first two input samples */
58 ox1=ox2=x[0];
59 oy1=oy2=y[0];
60 /* Extrapolate the initial phase with triangle... */
61 if(ox1>0.0) {
62 oy1=0.0;
63 /* unless:
64 -first input sample y<=0
65 -initial gap is longer than input TAC sampling frequency
66 */
67 if(y[0]>0.0 && (nr>1 && x[0]<=x[1]-x[0])) ox1=0.0;
68 }
69 /* Integrals too */
70 oi1=oii1=0.0;
71 oi2=oi1 + (ox2-ox1)*(oy1+oy2)/2.0;
72 oii2=oii1 + (ox2-ox1)*(oi1+oi2)/2.0;
73 if(verbose>2) {
74 printf("ox1=%g oy1=%g oi1=%g oii1=%g\n", ox1, oy1, oi1, oii1);
75 printf("ox2=%g oy2=%g oi2=%g oii2=%g\n", ox2, oy2, oi2, oii2);
76 }
77
78 /* Set interpolated data before input data (even imaginary) to zero */
79 j=0; while(j<newnr && newx[j]<ox1) {
80 ty=tyi=tyii=0.0; if(verbose>4) printf(" ndt=%g\n", ox1-newx[j]);
81 if(verbose>4) printf(" j=%d newx=%g ty=%g tyi=%g tyii=%g\n", j, newx[j], ty, tyi, tyii);
82 if(newy!=NULL) newy[j]=ty;
83 if(newyi!=NULL) newyi[j]=tyi;
84 if(newyii!=NULL) newyii[j]=tyii;
85 j++;
86 }
87
88 /* Set interpolated data between ox1 and ox2 */
89 dt=ox2-ox1; if(dt>0.0) while(j<newnr && newx[j]<=ox2) {
90 ndt=newx[j]-ox1; if(verbose>4) printf(" ndt=%g\n", ndt);
91 ty=((oy2-oy1)/dt)*ndt + oy1; if(newy!=NULL) newy[j]=ty;
92 tyi=oi1 + 0.5*(ty+oy1)*ndt; if(newyi!=NULL) newyi[j]=tyi;
93 if(newyii!=NULL) newyii[j]=tyii= oii1 + 0.5*(tyi+oi1)*ndt;
94 if(verbose>4) printf(" j=%d newx=%g ty=%g tyi=%g\n", j, newx[j], ty, tyi);
95 j++;
96 }
97
98 /* Go through input data, sample-by-sample */
99 for(i=0; i<nr && j<newnr; i++) {
100
101 ox1=ox2; oy1=oy2; oi1=oi2; oii1=oii2;
102 ox2=x[i]; oy2=y[i];
103 oi2=oi1 + (ox2-ox1)*(oy1+oy2)/2.0;
104 oii2=oii1 + (ox2-ox1)*(oi1+oi2)/2.0;
105 if(verbose>>3) {
106 printf("ox1=%g oy1=%g oi1=%g oii1=%g\n", ox1, oy1, oi1, oii1);
107 printf("ox2=%g oy2=%g oi2=%g oii2=%g\n", ox2, oy2, oi2, oii2);
108 }
109
110 /* Calculate input sample distance */
111 dt=ox2-ox1; if(dt<0.0) return 3; else if(dt==0.0) continue;
112
113 /* Any need for interpolation between ox1 and ox2? */
114 while(j<newnr && newx[j]<=ox2) {
115 ndt=newx[j]-ox1;
116 ty=((oy2-oy1)/dt)*ndt + oy1; if(newy!=NULL) newy[j]=ty;
117 tyi=oi1 + 0.5*(ty+oy1)*ndt; if(newyi!=NULL) newyi[j]=tyi;
118 if(newyii!=NULL) newyii[j]=tyii= oii1 + 0.5*(tyi+oi1)*ndt;
119 if(verbose>5) printf(" j=%d newx=%g ty=%g tyi=%g\n", j, newx[j], ty, tyi);
120 j++;
121 }
122
123 } // next input sample
124
125 /* Set interpolated data after input data, assuming steady input */
126 while(j<newnr) {
127 ndt=newx[j]-ox2;
128 ty=oy2;
129 tyi=oi2 + oy2*ndt;
130 tyii=oii2 + 0.5*(tyi+oi2)*ndt;
131 if(newy!=NULL) newy[j]=ty;
132 if(newyi!=NULL) newyi[j]=tyi;
133 if(newyii!=NULL) newyii[j]=tyii;
134 if(verbose>5) printf(" j=%d newx=%g ty=%g tyi=%g\n", j, newx[j], ty, tyi);
135 j++;
136 }
137
138 if(verbose>0) printf("out interpolate()\n");
139 return 0;
140}

Referenced by bfIrr2TCM(), bfRadiowater(), dftDivideFrames(), dftDoubleFrames(), dftInterpolate(), dftInterpolateInto(), dftReadinput(), dftTimeIntegral(), and interpolate4pet().

◆ interpolate4pet()

int interpolate4pet ( double * x,
double * y,
int nr,
double * newx1,
double * newx2,
double * newy,
double * newyi,
double * newyii,
int newnr )
extern

Interpolate and integrate TAC to PET frames.

It is assumed, that original data is not from framed data, but that the values represent the actual value at specified time point, which allows the integration to be calculated dot-by-dot.

If NULL is specified for *newy, *newyi and/or *newyii, their values are not calculated.

Original data and new x values must be sorted by ascending x. Subsequent x values can have equal values, enabling the use of step functions. PET frames can overlap, but interpolation may then be slower. Negative x (time) values can be processed. If necessary, the data is extrapolated assuming that 1) y[inf]=y[nr-1] and 2) if x[0]>0 and y[0]>0 and x[0]>x[1]-x[0], then an imaginary line is drawn from (0,0) to (x[0],y[0]).

Returns
Non-zero in case of an error.
See also
petintegrate, finterpolate4pet, interpolate, integrate, petintegral
Parameters
xTimes of original data
yValues of original data
nrNumber of original data values
newx1PET frame start times; frames may overlap
newx2PET frame end times; frames may overlap
newyMean value during PET frame, or NULL if not needed; calculation may be faster if newyi is calculated too
newyiIntegral at frame mid time, or NULL if not needed
newyii2nd integral at frame mid time, or NULL if not needed
newnrNumber of PET frames

Definition at line 510 of file integr.c.

530 {
531 int ret, fi, overlap=0, zeroframe=0;
532 double petx[3], pety[3], petyi[3], petyii[3], fdur;
533 int verbose=0;
534
535 if(verbose>0) printf("in interpolate4pet()\n");
536
537 /* Check for data */
538 if(nr<1 || newnr<1) return 1;
539 /* Check that programmer understood that outp data must've been allocated */
540 if(newy==NULL && newyi==NULL && newyii==NULL) return 2;
541 /* Check that input data is not totally outside the input data */
542 if(newx2[newnr-1]<=x[0] || newx1[0]>=x[nr-1]) return 3;
543
544 /* Check frame lengths, also for overlap and zero length frames */
545 for(fi=0; fi<newnr; fi++) {
546 /* Calculate frame length */
547 fdur=newx2[fi]-newx1[fi];
548 /* If frame length is <0, that is an error */
549 if(fdur<0.0) return 4;
550 if(fdur==0.0) zeroframe++;
551 /* Overlap? */
552 if(fi>0 && newx2[fi-1]>newx1[fi]) overlap++;
553 }
554 if(verbose>1) {
555 printf("overlap := %d\n", overlap);
556 printf("zeroframe := %d\n", zeroframe);
557 }
558
559 /* Interpolate and integrate one frame at a time, if there is:
560 -overlap in frames
561 -frames of zero length
562 -only few interpolated frames
563 -if only integrals are needed
564 -if neither of integrals is needed, then there is no temp memory to
565 do otherwise
566 */
567 if(overlap>0 || zeroframe>0 || newnr<=3 || newy==NULL || (newyi==NULL && newyii==NULL) ) {
568
569 if(verbose>1) printf("frame-by-frame interpolation/integration\n");
570 for(fi=0; fi<newnr; fi++) {
571 /* Set frame start, middle and end times */
572 petx[0]=newx1[fi]; petx[2]=newx2[fi]; petx[1]=0.5*(petx[0]+petx[2]);
573 /* Calculate frame length */
574 fdur=petx[2]-petx[0];
575 /* If frame length is <0, that is an error */
576 if(fdur<0.0) return 4;
577 /* If frame length is 0, then use direct interpolation */
578 if(fdur==0.0) {
579 ret=interpolate(x, y, nr, petx, pety, petyi, petyii, 1);
580 if(ret) return 10+ret;
581 if(newy!=NULL) newy[fi]=petyi[0];
582 if(newyi!=NULL) newyi[fi]=petyi[0];
583 if(newyii!=NULL) newyii[fi]=petyii[0];
584 continue;
585 }
586 /* Calculate integrals at frame start, middle, and end */
587 ret=interpolate(x, y, nr, petx, NULL, petyi, petyii, 3);
588 if(ret) return 20+ret;
589 /* Set output integrals, if required */
590 if(newyi!=NULL) newyi[fi]=petyi[1];
591 if(newyii!=NULL) newyii[fi]=petyii[1];
592 /* Calculate frame mean, if required */
593 if(newy!=NULL) newy[fi]=(petyi[2]-petyi[0])/fdur;
594 } // next frame
595
596 } else {
597
598 if(verbose>1) printf("all-frames-at-once interpolation/integration\n");
599 /* Set temp array */
600 double *tp; if(newyii!=NULL) tp=newyii; else tp=newyi;
601 /* Integrate at frame start times */
602 ret=interpolate(x, y, nr, newx1, NULL, tp, NULL, newnr);
603 if(ret) return 10+ret;
604 /* Integrate at frame end times */
605 ret=interpolate(x, y, nr, newx2, NULL, newy, NULL, newnr);
606 if(ret) return 10+ret;
607 /* Calculate average frame value */
608 for(fi=0; fi<newnr; fi++)
609 newy[fi]=(newy[fi]-tp[fi])/(newx2[fi]-newx1[fi]);
610 /* Calculate integrals */
611 if(newyi!=NULL || newyii!=NULL) {
612 for(fi=0; fi<newnr; fi++) newx1[fi]+=0.5*(newx2[fi]-newx1[fi]);
613 ret=interpolate(x, y, nr, newx1, NULL, newyi, newyii, newnr);
614 if(ret) return 10+ret;
615 for(fi=0; fi<newnr; fi++) newx1[fi]-=(newx2[fi]-newx1[fi]);
616 }
617 }
618
619 if(verbose>0) printf("out interpolate4pet()\n");
620 return 0;
621}
int interpolate(double *x, double *y, int nr, double *newx, double *newy, double *newyi, double *newyii, int newnr)
Linear interpolation and integration.
Definition integr.c:28

Referenced by bfIrr2TCM(), bfRadiowater(), dftAutointerpolate(), dftInterpolate(), dftInterpolateForIMG(), dftInterpolateInto(), img_k1_using_ki(), img_logan(), and img_patlak().

◆ least_median_of_squares()

double least_median_of_squares ( double * data,
int n )
extern

Fit a constant (horisontal straight line) to the data by minimising the median of squared residuals.

The algorithm is described in P.J. Rousseeuw: Least Median of Squares Regression, Journal of the American Statistical Association, Vol. 79, No. 388 (1984), 871-880.

Returns
Returns the LMS estimate.
Parameters
dataData array
nNumber of data values

Definition at line 21 of file lms.c.

26 {
27 int i, odd=1, half=floor(n/2), smallnr;
28 double small, *help;
29 if(fmod((double)n, 2.0)<1e-99) odd=0;
30 double *halfs_data;
31
32 halfs_data=(double*)malloc((half+odd) * sizeof(double));
33
34 help=data;
35 /* sort data in ascending order*/
36 qsort(help, n, sizeof(double), lmsQSort);
37
38 /* if n is even number */
39 for(i=0; i<half+odd; i++) {
40 halfs_data[i]=data[half+i]-data[i];
41 }
42
43 i=smallnr=0;
44 for(i=1, small=halfs_data[0]; i<half+odd; i++) {
45 if(halfs_data[i]<small) {
46 small=halfs_data[i];
47 smallnr=i;
48 }
49 }
50
51 return (data[half+smallnr]+data[smallnr])/2.0;
52}
int lmsQSort(const void *par1, const void *par2)
Definition lms.c:59

◆ least_trimmed_square()

int least_trimmed_square ( double data[],
long int n,
double * mean,
double * variance )
extern

Least trimmed squares estimates for univariate location and variance. Data samples are expected to be truly real valued (i.e too many samples having the same value might lead to problems. The algorithm (exact) is described in P.J. Rousseeuw and A.M. Leroy: Robust Regression and Outlier Detection John Wiley & Sons 1987.

Returns
Returns 0, if successful.
Parameters
dataInput vector of n sample values; data samples are expected to be truly real valued (i.e too many samples having the same value might lead to problems.
nNumber of samples
meanOutput: Mean of sample values
varianceOutput: Variance of sample values

Definition at line 27 of file lts.c.

38 {
39 int i, j, h, h2;
40 double score, best_score, loc, best_loc, old_sum, new_sum, medd;
41 double old_power_sum, new_power_sum;
42 double *scaled_data;
43
44 h = n - n/2;
45 h2 = n/2;
46
47 qsort(data, n, sizeof(double),ltsQSort);
48
49 old_sum=old_power_sum=0.0;
50 for(i=0; i<h; i++) {
51 old_sum = old_sum + data[i];
52 old_power_sum = old_power_sum + data[i]*data[i];
53 }
54
55 loc = old_sum/h;
56 /* For better understanding of the algorithm:
57 O(N^2) implementation of the algorithm would compute score as:
58 score = 0.0;
59 for(i = 0;i < h;i++) {
60 score = score + (data[i] - loc)*(data[i] - loc);
61 }
62 But there is a faster way to this: */
63 score = old_power_sum - old_sum*loc;
64 best_score = score;
65 best_loc = loc;
66 for(j=1; j<h2+1; j++) {
67 new_sum = old_sum - data[j-1] + data[h-1+j];
68 old_sum = new_sum;
69 loc = old_sum/h;
70 new_power_sum = old_power_sum - data[j-1]*data[j-1]
71 + data[h-1+j]*data[h-1+j];
72 old_power_sum = new_power_sum;
73 score = old_power_sum - old_sum*loc;
74 if(score < best_score) {
75 best_score = score;
76 best_loc = loc;
77 }
78 }
79 *mean = best_loc;
80
81 /* For the variance, it is needed to calculate the ellipsoid covering
82 one half of samples. This is not implemented optimally here because
83 data has already been sorted. */
84 scaled_data = malloc(n*sizeof(double));
85 if(scaled_data == NULL) return(1);
86 for(i=0; i<n; i++)
87 scaled_data[i] = (data[i]-best_loc)*((h-1)/best_score)*(data[i]-best_loc);
88 medd = dmedian(scaled_data, n);
89 free(scaled_data);
90 *variance = (best_score/(h-1))*(medd/CHI2INV_1);
91 return(0);
92}
double dmedian(double *data, int n)
Definition median.c:48
int mean(double *x, double *y, int nr, double *xmean, double *xsd, double *ymean, double *ysd)
Definition pearson.c:341
int ltsQSort(const void *par1, const void *par2)
Definition lts.c:99

◆ llsqperp()

int llsqperp ( double * x,
double * y,
int nr,
double * slope,
double * ic,
double * ssd )
extern

Simple non-iterative perpendicular line fitting. This function is fully based on the article [1].

References:

  1. Varga J & Szabo Z. Modified regression model for the Logan plot. J Cereb Blood Flow Metab 2002; 22:240-244.
See also
llsqperp3, medianline, llsqwt, mtga_best_perp
Returns
If successful, function returns value 0.
Parameters
xCoordinates of data points (dimension nr).
yCoordinates of data points (dimension nr).
nrNumber of data points.
slopeEstimated slope.
icEstimated intercept.
ssdSum of squared distances / nr.

Definition at line 382 of file llsqwt.c.

395 {
396 int i, rnr;
397 double qxx, qyy, qxy, mx, my, a, b, c, d, m1, m2, ssd1, ssd2;
398
399 if(0) {fprintf(stdout, "llsqperp()\n"); fflush(stdout);}
400 /* Check the data */
401 if(nr<2 || x==NULL || y==NULL) return(1);
402 /* Calculate the means */
403 for(i=0, mx=my=0; i<nr; i++) {mx+=x[i]; my+=y[i];}
404 mx/=(double)nr; my/=(double)nr;
405 /* Calculate the Q's */
406 for(i=0, qxx=qyy=qxy=0; i<nr; i++) {
407 a=x[i]-mx; b=y[i]-my; qxx+=a*a; qyy+=b*b; qxy+=a*b;
408 }
409 if(qxx<1.0E-100 || qyy<1.0E-100) return(2);
410 /* Calculate the slope as real roots of quadratic equation */
411 a=qxy; b=qxx-qyy; c=-qxy;
412 rnr=quadratic(a, b, c, &m1, &m2);
413 if(0) {
414 fprintf(stdout, "%d quadratic roots", rnr);
415 if(rnr>0) fprintf(stdout, " %g", m1);
416 if(rnr>1) fprintf(stdout, " %g", m2);
417 fprintf(stdout, " ; traditional slope %g\n", qxy/qxx);
418 }
419 if(rnr==0) return(3);
420 /* Calculate the sum of squared distances for the first root */
421 a=m1; b=-1; c=my-m1*mx;
422 for(i=0, ssd1=0; i<nr; i++) {
423 /* calculate the distance from point (x[i],y[i]) to line ax+by+c=0 */
424 //d=(a*x[i]+b*y[i]+c)/sqrt(a*a+b*b);
425 d=(a*x[i]+b*y[i]+c)/hypot(a, b);
426 ssd1+=d*d;
427 }
428 /* Also to the 2nd root, if there is one */
429 if(rnr==2) {
430 a=m2; b=-1; c=my-m2*mx;
431 for(i=0, ssd2=0; i<nr; i++) {
432 /* calculate the distance from point (x[i],y[i]) to line ax+by+c=0 */
433 //d=(a*x[i]+b*y[i]+c)/sqrt(a*a+b*b);
434 d=(a*x[i]+b*y[i]+c)/hypot(a, b);
435 ssd2+=d*d;
436 }
437 } else ssd2=ssd1;
438 /* If there were 2 roots, select the one with smaller ssd */
439 if(rnr==2 && ssd2<ssd1) {ssd1=ssd2; m1=m2;}
440 /* Set the slope and intercept */
441 *slope=m1; *ic=my-m1*mx; *ssd=ssd1/(double)nr;
442
443 return(0);
444}
int quadratic(double a, double b, double c, double *m1, double *m2)
Definition llsqwt.c:490

Referenced by img_logan(), img_patlak(), llsqperp3(), and mtga_best_perp().

◆ llsqperp3()

int llsqperp3 ( double * x,
double * y,
int nr,
double * slope,
double * ic,
double * ssd )
extern

Simple non-iterative perpendicular line fitting. This version of the function accepts data that contains NaN's.

See also
llsqperp, medianline
Returns
If successful, function returns value 0.
Parameters
xCoordinates of data points (dimension nr).
yCoordinates of data points (dimension nr).
nrNumber of data points.
slopeEstimated slope.
icEstimated intercept.
ssdSum of squared distances / nr.

Definition at line 453 of file llsqwt.c.

466 {
467 int i, j;
468 double *nx, *ny;
469
470 /* Allocate memory for new data pointers */
471 nx=(double*)calloc(nr, sizeof(double)); if(nx==NULL) return 1;
472 ny=(double*)calloc(nr, sizeof(double));
473 if(ny==NULL) {free((char*)nx); return 1;}
474
475 /* Copy data to pointers */
476 for(i=0, j=0; i<nr; i++)
477 if(!isnan(x[i]) && !isnan(y[i])) {nx[j]=x[i]; ny[j]=y[i]; j++;}
478
479 /* Use llsqperp() */
480 i=llsqperp(nx, ny, j, slope, ic, ssd);
481 free((char*)nx); free((char*)ny);
482 return(i);
483}
int llsqperp(double *x, double *y, int nr, double *slope, double *ic, double *ssd)
Definition llsqwt.c:382

◆ llsqWght()

int llsqWght ( int N,
int M,
double ** A,
double * a,
double * b,
double * weight )
extern

Algorithm for weighting the problem that is given to a LLSQ algorithm.

Square roots of weights are used because in LLSQ algorithms the difference w*A-w*b is squared.

See also
llsqWghtSquared
Returns
Algorithm returns zero if successful, 1 if arguments are inappropriate.
Parameters
NMatrix A dimension N (nr of parameters).
MMatrix A dimension M (nr of samples).
APointer to matrix A[N][M]; enter NULL to use following matrix format instead.
aPointer to matrix A[N*M]; enter NULL to use previous matrix format instead.
bVector B of length M.
weightWeights for each sample (array of length M).

Definition at line 419 of file bvls.c.

432 {
433 int n, m;
434 double *w;
435
436 /* Check the arguments */
437 if(N<1 || M<1 || (A==NULL && a==NULL) || b==NULL || weight==NULL) return(1);
438
439 /* Allocate memory */
440 w=(double*)malloc(M*sizeof(double)); if(w==NULL) return(2);
441
442 /* Check that weights are not zero and get the square roots of them to w[] */
443 for(m=0; m<M; m++) {
444 if(weight[m]<=1.0e-20) w[m]=0.0;
445 else w[m]=sqrt(weight[m]);
446 }
447
448 /* Multiply rows of matrix A and elements of vector b with weights*/
449 for(m=0; m<M; m++) {
450 for(n=0; n<N; n++) {
451 if(A!=NULL) A[n][m]*=w[m];
452 if(a!=NULL) a[m+n*M]*=w[m];
453 }
454 b[m]*=w[m];
455 }
456
457 free(w);
458 return(0);
459}

◆ llsqWghtSquared()

int llsqWghtSquared ( int N,
int M,
double ** A,
double * a,
double * b,
double * sweight )
extern

Algorithm for weighting the problem that is given to a LLSQ algorithm.

Square roots of weights are used because in LLSQ algorithms the difference w*A-w*b is squared.

Here user must give squared weights; this makes calculation faster, when this function needs to be called many times.

See also
llsqWght
Returns
Algorithm returns zero if successful, 1 if arguments are inappropriate.
Parameters
NMatrix A dimension N (nr of parameters).
MMatrix A dimension M (nr of samples).
APointer to matrix A[N][M]; enter NULL to use following matrix format instead.
aPointer to matrix A[N*M]; enter NULL to use previous matrix format instead.
bVector B of length M.
sweightSquared weights for each sample (array of length M).

Definition at line 474 of file bvls.c.

487 {
488 int n, m;
489
490 /* Check the arguments */
491 if(N<1 || M<1 || (A==NULL && a==NULL) || b==NULL || sweight==NULL) return(1);
492
493 /* Multiply rows of matrix A and elements of vector b with weights*/
494 for(m=0; m<M; m++) {
495 for(n=0; n<N; n++) {
496 if(A!=NULL) A[n][m]*=sweight[m];
497 if(a!=NULL) a[m+n*M]*=sweight[m];
498 }
499 b[m]*=sweight[m];
500 }
501
502 return(0);
503}

◆ llsqwt()

int llsqwt ( double * x,
double * y,
int n,
double * wx,
double * wy,
double tol,
double * w,
double * ic,
double * slope,
double * nwss,
double * sic,
double * sslope,
double * cx,
double * cy )
extern

Iterative method for linear least-squares fit with errors in both coordinates.

This function is fully based on article [3].

For n data-point pairs (x[i], y[i]) each point has its own weighting factors in (wx[i], wy[i]). This routine finds the values of the parameters m (slope) and c (intercept, ic) that yield the "best-fit" of the model equation Y = mX + c to the data, where X and Y are the predicted or calculated values of the data points.

Weighting factors wx and wy must be assigned as the inverses of the variances or squares of the measurement uncertainties (SDs), i.e. w[i]=1/(sd[i])^2

If true weights are unknown but yet the relative weights are correct, the slope, intercept and residuals (WSS) will be correct. The applied term S/(N-2) makes also the estimate of sigma (sd) of slope less dependent on the scaling of weights. The sigmas are not exact, since only the lowest-order terms in Taylor-series expansion are incorporated; anyhow sigmas are more accurate than the ones based on York algorithm.

One or more data points can be excluded from the fit by setting either x or y weight to 0.

References:

  1. York, D. Linear-squares fitting of a straight line. Can J Phys. 1966;44:1079-1086.
  2. Lybanon, M. A better least squares method when both variables have uncertainties. Am J Phys. 1984;52:22-26 and 276-278.
  3. Reed BC. Linear least-squares fits with errors in both coordinates. II: Comments on parameter variances. Am J Phys. 1992;60:59-62.
See also
llsqperp, best_llsqwt, medianline
Returns
If successful, function returns value 0.
Parameters
xcoordinates of data points (of dimension n).
ycoordinates of data points (of dimension n).
nnumber of data points.
wxweighting factors in x.
wyweighting factors in y.
tolallowed tolerance in slope estimation.
wwork vector (of dimension n); effective weights w[i] are returned in it.
icEstimated intercept.
slopeEstimated slope.
nwsssqrt(WSS)/wsum of the residuals.
sicexpected sd of intercept at calculated points; If NULL, then not calculated and variable is left unchanged.
sslopeExpected sd of slope at calculated points; If NULL, then not calculated and variable is left unchanged.
cxEstimated data points (X,y); If NULL, then not calculated and variable is left unchanged.
cyEstimated data points (x,Y); If NULL, then not calculated and variable is left unchanged.

Definition at line 48 of file llsqwt.c.

83 {
84 int i, j, niter=0, nn, calcVar=1;
85 double c, m, f, xb=0.0, yb=0.0, qa=0.0, qb=0.0, qc, ss=0.0, s1, s2, wsum=0.0;
86 double xsum=0.0, x2sum=0.0, ysum=0.0, xysum=0.0, delta, discr, sqdis;
87 double m_1, m_2, bcont, m2=0.0, w2;
88 double u, v, AA, BB, CC, DD, EE, FF, GG, HH, JJ;
89 double varc, varm, dmx, dmy, dcx, dcy;
90
91
92 /*
93 * Lets look what we got for arguments
94 */
95 if(0) {fprintf(stdout, "llsqwt()\n"); fflush(stdout);}
96 /* Check that there is some data */
97 if(n<2) return(1);
98 if(0) {
99 for(i=0; i<n; i++) printf("%e +- %e %e +- %e\n",
100 x[i], wx[i], y[i], wy[i]);
101 }
102 if(tol<1.0e-100) return(1);
103 if(w==NULL) return(1);
104 /* Check if variances and fitted data will be calculated */
105 if(sic==NULL || sslope==NULL || cx==NULL || cy==NULL) calcVar=0;
106 else calcVar=1;
107
108 /* If only 2 datapoints */
109 if(n==2) {
110 f=x[1]-x[0];
111 if(f==0.0) {*slope=*ic=*sic=*sslope=*nwss=w[0]=w[1]=0.0; return(0);}
112 *slope=(y[1]-y[0])/f; *ic=y[0]-(*slope)*x[0];
113 *sic=*sslope=0.; w[0]=1.0; w[1]=1.0; *nwss=0.0;
114 return(0);
115 }
116
117 /*
118 * Fit the LLSQ line
119 */
120
121 /* First estimation of the slope and intercept by unweighted regression */
122 for(i=0; i<n; i++) {
123 xsum+=x[i]; ysum+=y[i]; x2sum+=x[i]*x[i]; xysum+=x[i]*y[i];
124 }
125 delta=(double)n*x2sum - xsum*xsum;
126 /* Initial guesses of the slope and intercept */
127 if(delta==0.0) {
128 if(0) printf("x axis values contain only zeroes.\n");
129 *slope=*ic=*sic=*sslope=*nwss=w[0]=w[1]=0.0;
130 return(0);
131 }
132 m=((double)n*xysum - xsum*ysum)/delta;
133 c=(x2sum*ysum - xsum*xysum)/delta;
134 if(0) printf("initial guesses: a=%e b=%e\n", c, m);
135
136 /* Begin the iterations */
137 bcont=m+2.0*tol;
138 while(fabs(m-bcont)>tol && niter<20) {
139 if(0) printf(" %d. iteration, improvement=%g, tol=%g\n", niter, fabs(m-bcont), tol);
140 bcont=m; niter++;
141 /* Compute the weighting factors */
142 m2=m*m;
143 for(i=0, nn=0; i<n; i++) {
144 if(wx[i]<=0.0 || wy[i]<=0.0) w[i]=0.0;
145 else {w[i]=wx[i]*wy[i]/(m2*wy[i]+wx[i]); nn++;}
146 //printf("wx[i]=%g wy[i]=%g -> w[%d]=%g\n", wx[i], wy[i], i, w[i]);
147 }
148 if(nn<2) {
149 if(0) printf("less than two points with weight > 0.\n");
150 *slope=*ic=*sic=*sslope=*nwss=0.0;
151 return(0);
152 }
153 /* Compute the barycentre coordinates */
154 for(i=0, xb=yb=wsum=0.0; i<n; i++) {xb+=w[i]*x[i]; yb+=w[i]*y[i]; wsum+=w[i];}
155 if(wsum<=0.0) return(2);
156 xb/=wsum; yb/=wsum;
157 if(0) printf("barycentre: xb=%g yb=%g\n", xb, yb);
158 /* Estimate the slope as either of the roots of the quadratic */
159 /* compute the coefficients of the quadratic */
160 for(i=0, qa=qb=qc=0.0; i<n; i++) if(w[i]>0.0) {
161 u=x[i]-xb; v=y[i]-yb; w2=w[i]*w[i];
162 qa += w2*u*v/wx[i];
163 qb += w2*(u*u/wy[i] - v*v/wx[i]);
164 qc += -w2*u*v/wy[i];
165 }
166 if(0) printf("quadratic coefs: qa=%g qb=%g qc=%g\n", qa, qb, qc);
167 if(qa==0.0) {
168 m=0.0;
169 /* Calculate WSS */
170 for(i=0, ss=0.0; i<n; i++) {f=v=y[i]-yb; ss+=w[i]*f*f;}
171 } else if(qa==1.0) { /* check if quadratic reduces to a linear form */
172 m=-qc/qb;
173 /* Calculate WSS */
174 for(i=0, ss=0.0; i<n; i++) {u=x[i]-xb; v=y[i]-yb; f=v-m*u; ss+=w[i]*f*f;}
175 } else {
176 /* discriminant of quadratic */
177 discr=qb*qb-4.0*qa*qc; if(discr<=0.0) sqdis=0.0; else sqdis=sqrt(discr);
178 /* compute the two solutions of quadratic */
179 m_1=(-qb+sqdis)/(2.0*qa); m_2=(-qb-sqdis)/(2.0*qa);
180 /* Calculate WSS for both solutions */
181 for(i=0, s1=s2=0.0; i<n; i++) {
182 u=x[i]-xb; v=y[i]-yb;
183 f=v-m_1*u; s1+=w[i]*f*f;
184 f=v-m_2*u; s2+=w[i]*f*f;
185 }
186 /* choose the solution with lower WSS */
187 if(s1<=s2) {m=m_1; ss=s1;} else {m=m_2; ss=s2;}
188 }
189 /* Calculate the intercept */
190 c = yb - m*xb;
191 if(0) printf("iterated parameters: c=%e m=%e\n", c, m);
192
193 } /* end of iteration loop */
194 *ic=c; *slope=m; *nwss=sqrt(ss)/wsum; /* Set function return values */
195 if(0) {
196 fprintf(stdout, "c=%14.7e m=%14.7e ss=%14.7e niter=%d\n", c, m, ss, niter);
197 }
198
199 /* Return here, if variances are not to be calculated */
200 if(!calcVar) return(0);
201
202 /*
203 * Calculate the fitted line
204 */
205 for(i=0; i<n; i++) {
206 if(w[i]>0.0) {
207 f=w[i]*(c + m*x[i] - y[i]); /* Lagrangian multiplier */
208 cx[i]=x[i]-f*m/wx[i]; cy[i]=y[i]+f/wy[i];
209 } else {
210 cx[i]=x[i]; cy[i]=y[i];
211 }
212 }
213
214 /*
215 * Estimate the variances of the parameters (Reed 1992)
216 */
217 /* varm = var of slope ; varc = var of intercept */
218
219 /* Use the true nr of data points, i.e. exclude the ones with zero weight */
220 for(i=nn=0; i<n; i++) if(w[i]>0.0) nn++;
221 if(nn<3) {*sslope=*sic=0.0; return(0);}
222
223 /* Compute the barycentre coordinates again from computed data points */
224 for(i=0, xb=yb=wsum=0.0; i<n; i++) {xb+=w[i]*cx[i]; yb+=w[i]*cy[i]; wsum+=w[i];}
225 if(wsum<=0.0) return(2);
226 xb/=wsum; yb/=wsum;
227 if(0) printf("barycentre: xb=%g yb=%g\n", xb, yb);
228
229 /* common factors */
230 HH=JJ=qa=qb=qc=0.0;
231 for(i=0; i<n; i++) if(w[i]>0.0) {
232 u=cx[i]-xb; v=cy[i]-yb; w2=w[i]*w[i];
233 qa += w2*u*v/wx[i];
234 qb += w2*(u*u/wy[i] - v*v/wx[i]);
235 qc += -w2*u*v/wy[i];
236 HH += w2*v/wx[i];
237 JJ += w2*u/wx[i];
238 }
239 HH*=-2.0*m/wsum; JJ*=-2.0*m/wsum;
240 if(0) printf("quadratic coefs: qa=%g qb=%g qc=%g ; HH=%g JJ=%g\n", qa, qb, qc, HH, JJ);
241 AA=BB=CC=0.0;
242 for(i=0; i<n; i++) if(w[i]>0.0) {
243 u=cx[i]-xb; v=cy[i]-yb; w2=w[i]*w[i];
244 AA += w[i]*w[i]*w[i]*u*v / (wx[i]*wx[i]);
245 BB -= w2 * (4.0*m*(w[i]/wx[i])*(u*u/wy[i]-v*v/wx[i]) - 2.0*v*HH/wx[i] + 2.0*u*JJ/wy[i]);
246 CC -= (w2/wy[i]) * (4.0*m*w[i]*u*v/wx[i] + v*JJ + u*HH);
247 }
248 if(m!=0) AA = 4.0*m*AA - wsum*HH*JJ/m; else AA=0.0;
249 if(0) printf("AA=%g BB=%g CC=%g\n", AA, BB, CC);
250 /* sigmas */
251 varc=varm=0.0;
252 for(j=0; j<n; j++) if(w[j]>0.0) {
253 /* factors for this j */
254 DD=EE=FF=GG=0.0;
255 for(i=0; i<n; i++) if(w[i]>0.0) {
256 u=cx[i]-xb; v=cy[i]-yb; w2=w[i]*w[i];
257 if(i==j) delta=1.0; else delta=0.0; /* Kronecker delta */
258 f = delta - w[j]/wsum;
259 DD += (w2*v/wx[i])*f;
260 EE += (w2*u/wy[i])*f;
261 FF += (w2*v/wy[i])*f;
262 GG += (w2*u/wx[i])*f;
263 }
264 EE*=2.0;
265 /* derivatives at jth data point */
266 f = (2.0*m*qa + qb - AA*m2 + BB*m - CC); m2=m*m;
267 dmx = -(m2*DD + m*EE - FF) / f;
268 dmy = -(m2*GG - 2.0*m*DD - EE/2.0) / f;
269 dcx = (HH - m*JJ - xb)*dmx - m*w[j]/wsum;
270 dcy = (HH - m*JJ - xb)*dmy + w[j]/wsum;
271 /* sum terms for sigmas */
272 varm += dmy*dmy/wy[j] + dmx*dmx/wx[j];
273 varc += dcy*dcy/wy[j] + dcx*dcx/wx[j];
274 if(0)
275 printf("DD=%g EE=%g FF=%g GG=%g dmx=%g dmy=%g dcx=%g dcy=%g\n",
276 DD, EE, FF, GG, dmx, dmy, dcx, dcy);
277 }
278 varm *= ss/(double)(nn-2);
279 varc *= ss/(double)(nn-2);
280 if(0) printf("varm=%g varc=%g\n", varm, varc);
281 *sslope = sqrt(varm);
282 *sic = sqrt(varc);
283 if(0) {fprintf(stdout, "sslope=%14.7e sic=%14.7e\n", *sslope, *sic);}
284 return(0);
285}

Referenced by best_llsqwt(), and best_logan_reed().

◆ logan_data()

int logan_data ( int data_nr,
double * i,
double * ii,
double * c,
double * ci,
double k2,
double * x,
double * y )
extern

Calculates Logan plot x,y values from the measured input and ROI concentration TACs.

Plot will not include data where: 1) any of the values is not available (NaN), 2) integral is negative at this or later point, 3) divider is too close to zero.

See also
patlak_data, img_logan, llsqperp, mtga_best_perp
Returns
Returns the number of acceptable Logan plot data pairs, or <0 in case of an error. Note that zero or one return values prevent the line fitting, but are here not considered as errors.
Parameters
data_nrNr of samples.
iArray of input concentrations.
iiArray of integrals (from zero to sample time) of input concentrations; if reference region input, then remember to consider the frame length.
cArray of ROI concentrations.
ciArray of ROI integrals (from zero to frame middle time).
k2Reference region k2; set to <=0 if not needed.
xPointer to preallocated memory (at least size dnr) where MTGA plot x values will be written.
yPointer to preallocated memory (at least size dnr) where MTGA plot y values will be written.

Definition at line 81 of file mtga.c.

99 {
100 int fi, plot_nr=0;
101 double divider_limit=1.0E-18;
102
103 if(data_nr<0 || i==NULL || ii==NULL || c==NULL || ci==NULL) return -1;
104 if(x==NULL || y==NULL) return -1;
105
106 for(fi=0; fi<data_nr; fi++) {
107 // check that all measured data is available
108 if(isnan(i[fi]) || isnan(ii[fi]) || isnan(c[fi]) || isnan(ci[fi])) continue;
109 if(!(i[fi]>-1.0E+30 && i[fi]<+1.0E+30)) continue;
110 if(!(ii[fi]>-1.0E+30 && ii[fi]<+1.0E+30)) continue;
111 if(!(c[fi]>-1.0E+30 && c[fi]<+1.0E+30)) continue;
112 if(!(ci[fi]>-1.0E+30 && ci[fi]<+1.0E+30)) continue;
113 // check that integrals have been >=0 all the time
114 if(ii[fi]<0.0) {plot_nr=0; continue;}
115 if(ci[fi]<0.0) {plot_nr=0; continue;}
116 // check that dividers are not too close to zero
117 if(fabs(c[fi])<divider_limit) continue;
118 // calculate plot x axis value
119 if(k2>0.0) x[plot_nr]=(ii[fi]+i[fi]/k2)/c[fi];
120 else x[plot_nr]=ii[fi]/c[fi];
121 if(!(x[plot_nr]>-1.0E+30 && x[plot_nr]<+1.0E+30)) continue;
122 // calculate plot y axis value
123 y[plot_nr]=ci[fi]/c[fi];
124 if(!(y[plot_nr]>-1.0E+30 && y[plot_nr]<+1.0E+30)) continue;
125 // so this plot data point is fine
126 plot_nr++;
127 }
128 return(plot_nr);
129}

Referenced by img_logan().

◆ mean()

int mean ( double * x,
double * y,
int nr,
double * xmean,
double * xsd,
double * ymean,
double * ysd )
extern

Calculates the mean and SD of data. Data (y data) may contain NaN's.

See also
dmean, dmedian, dmean_nan, regr_line, pearson
Returns
Returns !=0 in case of an error.
Parameters
xData x values
yData y values
nrNumber of data sample values
xmeanCalculated x mean
xsdCalculated SD of x mean
ymeanCalculated y mean
ysdCalculated SD of y mean

Definition at line 341 of file pearson.c.

356 {
357 int i, n;
358 double sumsqr, sqrsum;
359
360 for(i=0, sumsqr=sqrsum=0.0, n=0; i<nr; i++) if(!isnan(x[i]) && !isnan(y[i])) {
361 sumsqr+=x[i]*x[i]; sqrsum+=x[i]; n++;}
362 if(n<=0) return -1;
363 *xmean=sqrsum/(double)n;
364 if(n==1) *xsd=0.0; else {
365 sqrsum*=sqrsum;
366 *xsd=sqrt( (sumsqr - sqrsum/(double)n) / (double)(n-1) );
367 }
368 for(i=0, sumsqr=sqrsum=0.0, n=0; i<nr; i++) if(!isnan(x[i]) && !isnan(y[i])) {
369 sumsqr+=y[i]*y[i]; sqrsum+=y[i]; n++;}
370 if(n<=0) return -1;
371 *ymean=sqrsum/(double)n;
372 if(n==1) *ysd=0.0; else {
373 sqrsum*=sqrsum;
374 *ysd=sqrt( (sumsqr - sqrsum/(double)n) / (double)(n-1) );
375 }
376 return 0;
377}

Referenced by dftMeanTAC(), doubleMatchRel(), imgsegmClusterExpand(), least_trimmed_square(), mertwiRandomExponential(), noiseSD4SimulationFromDFT(), and resMean().

◆ medianline()

int medianline ( double * x,
double * y,
int nr,
double * slope,
double * ic )
extern

Median-based distribution-free estimation of slope and intercept. This method has no need for weighting and is insensitive to outliers. Note that this is not LMS !

Reference (containing reference to the original idea):

  1. Siegel AF. Robust regression using repeated medians. Biometrika 1982;69(1):242-244.
See also
llsqperp
Returns
If successful, function returns value 0.
Parameters
xCoordinates of data points (dimension nr).
yCoordinates of data points (dimension nr).
nrNumber of data points.
slopeEstimated slope.
icEstimated intercept.

Definition at line 533 of file llsqwt.c.

544 {
545 int i, j, snr;
546 double *sp, *ip, d;
547
548 if(0) fprintf(stdout, "medianline()\n");
549 /* Check the data */
550 if(nr<2 || x==NULL || y==NULL) return(1);
551 /* Allocate memory for slopes and intercepts */
552 for(i=0, snr=0; i<nr-1; i++) for(j=i+1; j<nr; j++) snr++;
553 sp=(double*)malloc(snr*sizeof(double));
554 ip=(double*)malloc(snr*sizeof(double));
555 if(sp==NULL || ip==NULL) return(2);
556 /* Calculate the slopes and intercepts */
557 for(i=0, snr=0; i<nr-1; i++) for(j=i+1; j<nr; j++) {
558 if(isnan(x[i]) || isnan(x[j]) || isnan(y[i]) || isnan(y[j])) continue;
559 d=x[j]-x[i]; if(d==0) continue;
560 sp[snr]=(y[j]-y[i])/d; ip[snr]=y[i]-sp[snr]*x[i];
561 snr++;
562 }
563 if(snr<2) {free(sp); free(ip); return(3);}
564 /* Get the medians of slope and intercept */
565 qsort(sp, snr, sizeof(double), _medianline_cmp);
566 qsort(ip, snr, sizeof(double), _medianline_cmp);
567 if(snr%2==1) {*slope=sp[snr/2]; *ic=ip[snr/2];}
568 else {*slope=0.5*(sp[snr/2]+sp[(snr/2)-1]); *ic=0.5*(ip[snr/2]+ip[(snr/2)-1]);}
569 free(sp); free(ip);
570 return(0);
571}

◆ mertwiInit()

void mertwiInit ( MERTWI * mt)
extern

Prepare data struct Mersenne Twister MT19937 for usage. Do not call any mertwi* functions before calling this function!

Definition at line 23 of file mertwi.c.

25 {
26 mt->n=TPCCLIB_MERTWI_NN; // Length of mt array
27 mt->m=mt->n/2; // N/2
29 mt->um=UINT64_C(0xFFFFFFFF80000000);
30 mt->lm=UINT64_C(0x7FFFFFFF);
31 mt->mti=mt->n+1; // means that mt[] is not initialized
32}
#define TPCCLIB_MERTWI_NN
Definition libtpcmodel.h:41
#define TPCCLIB_MERTWI_A
Definition libtpcmodel.h:43
uint64_t mti
Definition libtpcmodel.h:60
unsigned int m
Definition libtpcmodel.h:50
uint64_t lm
Definition libtpcmodel.h:56
uint64_t a
Definition libtpcmodel.h:52
uint64_t um
Definition libtpcmodel.h:54
unsigned int n
Definition libtpcmodel.h:48

◆ mertwiInitByArray64()

void mertwiInitByArray64 ( MERTWI * mt,
uint64_t init_key[],
uint64_t key_length )
extern

Initialize the state vector mt[] inside data struct for Mersenne Twister MT19937 pseudorandom number generator using given array.

Call either this or mertwiInitWithSeed64 before generating random numbers with MT19937 using functions.

Precondition
Initialize MERTWI data struct by calling mertwiInit() before this.
See also
mertwiSeed64, mertwiInitWithSeed64, mertwiInit
Parameters
mtData struct for Mersenne Twister MT19937 pseudorandom number generator
init_keyThe array for initializing keys
key_lengthLength of initialization array init_key[]

Definition at line 111 of file mertwi.c.

118 {
119 unsigned int i, j;
120 uint64_t k;
121 mertwiInitWithSeed64(mt, UINT64_C(19650218));
122 i=1; j=0; if(mt->n>key_length) k=mt->n; else k=key_length;
123 for(; k; k--) {
124 mt->mt[i] =
125 (mt->mt[i] ^ ((mt->mt[i-1] ^ (mt->mt[i-1]>>62)) * UINT64_C(3935559000370003845)))
126 + init_key[j] + j;
127 i++; j++;
128 if(i>=mt->n) {mt->mt[0]=mt->mt[mt->n-1]; i=1;}
129 if(j>=key_length) j=0;
130 }
131 for(k=mt->n-1; k; k--) {
132 mt->mt[i]=
133 (mt->mt[i] ^ ((mt->mt[i-1] ^ (mt->mt[i-1] >> 62)) * UINT64_C(2862933555777941757)))
134 - i;
135 i++;
136 if(i>=mt->n) {mt->mt[0]=mt->mt[mt->n-1]; i=1;}
137 }
138 mt->mt[0] = UINT64_C(1) << 63; /* MSB is 1; assuring non-zero initial array */
139}
void mertwiInitWithSeed64(MERTWI *mt, uint64_t seed)
Initialize the state vector mt[] inside data struct for Mersenne Twister MT19937 pseudorandom number ...
Definition mertwi.c:91
uint64_t mt[TPCCLIB_MERTWI_NN]
Definition libtpcmodel.h:58

◆ mertwiInitWithSeed64()

void mertwiInitWithSeed64 ( MERTWI * mt,
uint64_t seed )
extern

Initialize the state vector mt[] inside data struct for Mersenne Twister MT19937 pseudorandom number generator using given seed.

Call either this or mertwiInitByArray64 before generating random numbers with MT19937 using functions.

Precondition
Initialize MERTWI data struct by calling mertwiInit() before this.
See also
mertwiSeed64, mertwiInitByArray64, mertwiInit
Parameters
mtData struct for Mersenne Twister MT19937 pseudorandom number generator
seedSeed, for example from mertwiSeed64()

Definition at line 91 of file mertwi.c.

96 {
97 mt->mt[0]=seed;
98 for(mt->mti=1; mt->mti<mt->n; mt->mti++)
99 mt->mt[mt->mti]=
100 (UINT64_C(6364136223846793005)*(mt->mt[mt->mti-1] ^ (mt->mt[mt->mti-1]>>62)) + mt->mti);
101}

Referenced by mertwiInitByArray64(), and mertwiRandomInt64().

◆ mertwiRandomDouble1()

double mertwiRandomDouble1 ( MERTWI * mt)
extern

Generate a 64-bit double precision floating point pseudorandom number in the range of [0,1] with uniform distribution using Mersenne Twister MT19937.

With uniform distribution, the SD=(up-low)/sqrt(12), and CV=(up-low)/(sqrt(3)*(low+up)).

Precondition
Initialize MERTWI data struct by calling mertwiInit() before using this function. Preferably also initialize state vector by calling either mertwiInitWithSeed64() or mertwiInitByArray64; if you do not do that, mertwiInitWithSeed64() is called automatically with predetermined seed.
See also
mertwiInit, mertwiInitWithSeed64, mertwiInitByArray64
Returns
Returns the random double value in the range [0,1].
Parameters
mtData struct for Mersenne Twister MT19937 pseudorandom number generator

Definition at line 218 of file mertwi.c.

221 {
222 return(mertwiRandomInt64(mt) >> 11) * (1.0/9007199254740991.0);
223}
uint64_t mertwiRandomInt64(MERTWI *mt)
Generate a random number on [0, 2^64-1]-interval using Mersenne Twister MT19937.
Definition mertwi.c:152

Referenced by mertwiRandomBetween(), mertwiRandomExponential(), and mertwiRandomGaussian().

◆ mertwiRandomDouble2()

double mertwiRandomDouble2 ( MERTWI * mt)
extern

Generate a 64-bit double precision floating point pseudorandom number in the range of [0,1) with uniform distribution using Mersenne Twister MT19937.

Precondition
Initialize MERTWI data struct by calling mertwiInit() before using this function. Preferably also initialize state vector by calling either mertwiInitWithSeed64() or mertwiInitByArray64; if you do not do that, mertwiInitWithSeed64() is called automatically with predetermined seed.
See also
mertwiInit, mertwiInitWithSeed64, mertwiInitByArray64
Returns
Returns the random double value in the range [0,1).
Parameters
mtData struct for Mersenne Twister MT19937 pseudorandom number generator

Definition at line 235 of file mertwi.c.

238 {
239 return(mertwiRandomInt64(mt) >> 11) * (1.0/9007199254740992.0);
240}

◆ mertwiRandomDouble3()

double mertwiRandomDouble3 ( MERTWI * mt)
extern

Generate a 64-bit double precision floating point pseudorandom number in the range of (0,1) with uniform distribution using Mersenne Twister MT19937.

Precondition
Initialize MERTWI data struct by calling mertwiInit() before using this function. Preferably also initialize state vector by calling either mertwiInitWithSeed64() or mertwiInitByArray64; if you do not do that, mertwiInitWithSeed64() is called automatically with predetermined seed.
See also
mertwiInit, mertwiInitWithSeed64, mertwiInitByArray64
Returns
Returns the random double value in the range (0,1).
Parameters
mtData struct for Mersenne Twister MT19937 pseudorandom number generator

Definition at line 252 of file mertwi.c.

255 {
256 return((mertwiRandomInt64(mt) >> 12) + 0.5) * (1.0/4503599627370496.0);
257}

◆ mertwiRandomInt63()

int64_t mertwiRandomInt63 ( MERTWI * mt)
extern

Generate a random number on [0, 2^63-1]-interval using Mersenne Twister MT19937.

Precondition
Initialize MERTWI data struct by calling mertwiInit() before using this function. Preferably also initialize state vector by calling either mertwiInitWithSeed64() or mertwiInitByArray64; if you do not do that, mertwiInitWithSeed64() is called automatically with predetermined seed.
See also
mertwiInit, mertwiInitWithSeed64, mertwiInitByArray64
Returns
Returns the random number with range from 0 to INT64_MAX.
Parameters
mtData struct for Mersenne Twister MT19937 pseudorandom number generator

Definition at line 197 of file mertwi.c.

200 {
201 return(int64_t)(mertwiRandomInt64(mt) >> 1);
202}

◆ mertwiRandomInt64()

uint64_t mertwiRandomInt64 ( MERTWI * mt)
extern

Generate a random number on [0, 2^64-1]-interval using Mersenne Twister MT19937.

Precondition
Initialize MERTWI data struct by calling mertwiInit() before using this function. Preferably also initialize state vector by calling either mertwiInitWithSeed64() or mertwiInitByArray64; if you do not do that, mertwiInitWithSeed64() is called automatically with predetermined seed.
See also
mertwiInit, mertwiInitWithSeed64, mertwiInitByArray64
Returns
Returns the random number with range from 0 to UINT64_MAX.
Parameters
mtData struct for Mersenne Twister MT19937 pseudorandom number generator

Definition at line 152 of file mertwi.c.

155 {
156 unsigned int i;
157 uint64_t x;
158 static uint64_t mag01[2]={UINT64_C(0), TPCCLIB_MERTWI_A};
159
160 if(mt->mti>=mt->n) { /* generate NN words at one time */
161
162 /* if init_genrand64() has not been called, a default initial seed is used */
163 if(mt->mti==mt->n+1) mertwiInitWithSeed64(mt, UINT64_C(5489));
164
165 for(i=0; i<mt->n-mt->m; i++) {
166 x=(mt->mt[i]&mt->um)|(mt->mt[i+1]&mt->lm);
167 mt->mt[i] = mt->mt[i+mt->m] ^ (x>>1) ^ mag01[(int)(x&UINT64_C(1))];
168 }
169 for(; i<mt->n-1; i++) {
170 x = (mt->mt[i]&mt->um)|(mt->mt[i+1]&mt->lm);
171 mt->mt[i] = mt->mt[i+(mt->m-mt->n)] ^ (x>>1) ^ mag01[(int)(x&UINT64_C(1))];
172 }
173 x = (mt->mt[mt->n-1]&mt->um)|(mt->mt[0]&mt->lm);
174 mt->mt[mt->n-1] = mt->mt[mt->m-1] ^ (x>>1) ^ mag01[(int)(x&UINT64_C(1))];
175 mt->mti=0;
176 }
177 x = mt->mt[mt->mti];
178
179 x ^= (x>>29) & UINT64_C(0x5555555555555555);
180 x ^= (x<<17) & UINT64_C(0x71D67FFFEDA60000);
181 x ^= (x<<37) & UINT64_C(0xFFF7EEE000000000);
182 x ^= (x>>43);
183 mt->mti++;
184
185 return(x);
186}

Referenced by mertwiRandomDouble1(), mertwiRandomDouble2(), mertwiRandomDouble3(), and mertwiRandomInt63().

◆ mertwiSeed32()

uint32_t mertwiSeed32 ( void )
extern

Make uint32_t seed for pseudorandom number generators.

Uses microseconds from the computer clock and process ID to reduce the chance of getting the same seed for simultaneously executing program threads and instances.

Returns
Returns the seed.
See also
mertwiSeed64

Definition at line 43 of file mertwi.c.

44{
45 uint32_t li;
46#if defined HAVE_TIMESPEC_GET
47 struct timespec ts;
48 timespec_get(&ts, TIME_UTC);
49 li=((ts.tv_sec % 10000)*523 ^ ts.tv_nsec*10) ^ ((getpid() % 1000)*983);
50#elif defined HAVE_CLOCK_GETTIME
51 struct timespec ts;
52 clock_gettime(CLOCK_REALTIME, &ts);
53 li=((ts.tv_sec % 10000)*523 ^ ts.tv_nsec*10) ^ ((getpid() % 1000)*983);
54#elif defined HAVE_GETTIMEOFDAY
55 struct timeval tv;
56 gettimeofday(&tv, 0);
57 li=((tv.tv_sec % 10000)*523 ^ tv.tv_usec*13) ^ ((getpid() % 1000)*983);
58#else
59 li=(unsigned int)time(NULL)+(unsigned int)getpid();
60#endif
61 li+=(uint32_t)rand();
62 return(li);
63}

Referenced by mertwiSeed64().

◆ mertwiSeed64()

uint64_t mertwiSeed64 ( void )
extern

Make uint64_t seed for pseudorandom number generators.

Uses microseconds from the computer clock and process ID to reduce the chance of getting the same seed for simultaneously executing program threads and instances.

Returns
Returns the seed.
See also
mertwiSeed32

Definition at line 72 of file mertwi.c.

73{
74 uint32_t li;
75 uint64_t lli;
76 lli=li=mertwiSeed32();
77 lli=li; lli<<=32; lli+=li;
78 return(lli);
79}
uint32_t mertwiSeed32(void)
Make uint32_t seed for pseudorandom number generators.
Definition mertwi.c:43

◆ mEstim()

double mEstim ( double * data,
int nr,
int iterNr,
double cutoff )
extern

Fit a constant (horizontal straight line) to the data with M-estimator.

The algorithm was described in the lecture notes of Nonlinear signal processing course of Tampere university of technology www.cs.tut.fi/~eeroh/nonlin.html

Returns
Returns Hubers M-estimator for single dataset.
Parameters
dataData array
nrNumber of data values
iterNrNumber of iterations
cutoffcutoff point

Definition at line 18 of file mestim.c.

27 {
28 double theta, sum1, sum2, help;
29
30 theta=dmedian(data, nr);
31 for(int ii=0; ii<iterNr; ii++){
32 sum1=sum2=0;
33 for(int in=0; in<nr; in++){
34 if(data[in]<0.9999*theta || data[in]>1.0001*theta){
35 help=huber(data[in]-theta, cutoff);
36 sum1=sum1+data[in]*help/(data[in]-theta);
37 sum2=sum2+help/(data[in]-theta);
38 } else {
39 sum1=sum1+cutoff*data[in];
40 sum2=sum2+cutoff;
41 }
42 }
43 theta=sum1/sum2;
44 }
45 return theta;
46}
double huber(double x, double b)
Definition mestim.c:53

◆ mo2k1k2()

double mo2k1k2 ( const double OER,
const double SaO2,
const double p50Hb,
const double p50Mb,
const double nHb,
const double cHb,
const double cMb,
const int verbose )
extern

Calculates K1/k2 ratio for [O-15]O2 in muscle, based on OER.

Returns
Returns K1/k2.
Parameters
OEROxygen extraction ratio; assumptions hold only in the range OER=0.2-0.9
SaO2Arterial oxygen saturation fraction; you can enter DEFAULT_SAO2
p50HbHalf-saturation pressure p50 (kPa) for hemoglobin; you can enter DEFAULT_P50HB
p50MbHalf-saturation pressure p50 (kPa) p50 for myoglobin; you can enter DEFAULT_P50MB
nHbHill coefficient n for hemoglobin; you can enter DEFAULT_NHB
cHbHemoglobin concentration in blood (mg/g); you can enter DEFAULT_CHB
cMbMyoglobin concentration in muscle (mg/g); you can enter DEFAULT_CMB
verboseVerbose level; if zero, then nothing is printed into stdout or stderr

Definition at line 29 of file o2.c.

48 {
49 if(verbose>0) printf("mo2k1k2()\n");
50 if(verbose>1) {
51 printf("input:\n");
52 printf(" OER := %g\n", OER);
53 printf(" SaO2 := %g\n", SaO2);
54 printf(" p50Hb := %g\n", p50Hb);
55 printf(" p50Mb := %g\n", p50Mb);
56 printf(" nHb := %g\n", nHb);
57 printf(" cHb := %g\n", cHb);
58 printf(" cMb := %g\n", cMb);
59 }
60 double SHb=(1.0-OER)*SaO2;
61 if(verbose>2) printf("SHb := %g\n", SHb);
62
63 double pO2=p50Hb*pow(SHb/(1.0-SHb), 1.0/nHb);
64 if(verbose>2) printf("pO2 := %g\n", pO2);
65
66 double SMb=pO2/(pO2+p50Mb);
67 if(verbose>2) printf("SMb := %g\n", SMb);
68
69 double rO2=cMb/cHb;
70 if(verbose>2) printf("rO2 := %g\n", rO2);
71
72 double k1k2=rO2*(SMb/SHb);
73 if(verbose>1) printf("K1/k2 := %g\n", k1k2);
74
75 return(k1k2);
76}
double p50Mb
Definition o2.c:16
double nHb
Definition o2.c:18
double p50Hb
Definition o2.c:14
double cHb
Definition o2.c:20
double SaO2
Definition o2.c:12
double cMb
Definition o2.c:22

◆ mo2pO2()

double mo2pO2 ( const double OER,
const double K1k2,
const double SaO2,
const double p50Mb,
const double cHb,
const double cMb,
const int verbose )
extern

Calculates the partial pressure of oxygen in muscle, based on OER and K1/k2.

Returns
Returns pO2 (kPa).
Parameters
OEROxygen extraction ratio; assumptions hold only in the range OER=0.2-0.9
K1k2K1/k2 ratio for [O-15]O2
SaO2Arterial oxygen saturation fraction; you can enter DEFAULT_SAO2
p50MbHalf-saturation pressure p50 (kPa) p50 for myoglobin; you can enter DEFAULT_P50MB
cHbHemoglobin concentration in blood (mg/g); you can enter DEFAULT_CHB
cMbMyoglobin concentration in muscle (mg/g); you can enter DEFAULT_CMB
verboseVerbose level; if zero, then nothing is printed into stdout or stderr

Definition at line 83 of file o2.c.

99 {
100 if(verbose>0) printf("mo2pO2()\n");
101 if(verbose>1) {
102 printf("input:\n");
103 printf(" OER := %g\n", OER);
104 printf(" K1/k2 := %g\n", K1k2);
105 printf(" SaO2 := %g\n", SaO2);
106 printf(" cHb := %g\n", cHb);
107 printf(" cMb := %g\n", cMb);
108 printf(" p50Mb := %g\n", p50Mb);
109 }
110 double SHb=(1.0-OER)*SaO2;
111 if(verbose>2) printf("SHb := %g\n", SHb);
112
113 double rO2=cMb/cHb;
114 if(verbose>2) printf("rO2 := %g\n", rO2);
115
116 double SMb=K1k2*(1.0-OER)*SaO2/rO2;
117 if(verbose>2) printf("SMb := %g\n", SMb);
118
119 double pO2=SMb*p50Mb/(1.0-SMb);
120 if(verbose>1) printf("pO2 := %g\n", pO2);
121
122 return(pO2);
123}

◆ modelCheckLimits()

int modelCheckLimits ( int par_nr,
double * lower_p,
double * upper_p,
double * test_p )
extern

Check if model parameters have collided with given limits.

If parameter is fixed (equal lower and upper limit) then it is not counted as collision.

Returns
Return the number of parameters that too close to the limits; 0 in case all are well inside the limits.
Parameters
par_nrNr of parameters
lower_pLower limits
upper_pUpper limits
test_pParameters to test

Definition at line 59 of file constraints.c.

68 {
69 int pi, collision_nr=0;
70 double range, range_factor=0.00001;
71
72 for(pi=0; pi<par_nr; pi++) {
73 // fixed parameters are not checked
74 range=upper_p[pi]-lower_p[pi]; if(range<=0.0) continue;
75 // if parameter exceeds the limit, then that is a collision for sure
76 if(test_p[pi]<=lower_p[pi]) {
77 collision_nr++; continue;
78 } else if(test_p[pi]>upper_p[pi]) {
79 collision_nr++; continue;
80 }
81 // but in addition, accepted range is a bit smaller than constrained range
82 // except if limit is 0, then it is ok that parameter is close to zero
83 range*=range_factor;
84 if(test_p[pi]<lower_p[pi]+range) {
85 if(fabs(lower_p[pi])>=1.0E-06) collision_nr++;
86 } else if(test_p[pi]>upper_p[pi]-range) {
87 if(fabs(upper_p[pi])>=1.0E-06) collision_nr++;
88 }
89 }
90 return collision_nr;
91}

◆ modelCheckParameters()

int modelCheckParameters ( int par_nr,
double * lower_p,
double * upper_p,
double * test_p,
double * accept_p,
double * penalty )
extern

Check that model parameters are within given limits. If not, then compute a penalty factor.

Returns
Return the number of parameters that are inside or at the limits; 0 in case of error or if all are outside of the limits.
Parameters
par_nrNr of parameters
lower_pLower limits
upper_pUpper limits
test_pParameters to test
accept_pPointer to corrected parameters (NULL if not needed)
penaltyPointer to variable in which the possible penalty factor will be written; 1 if no penalty, or >1. Set to NULL if not needed.

Definition at line 15 of file constraints.c.

29 {
30 int pi, accept_nr=0;
31 double range;
32
33 if(penalty!=NULL) *penalty=1.0;
34 for(pi=0; pi<par_nr; pi++) {
35 range=upper_p[pi]-lower_p[pi]; if(range<=0.0) range=1.0;
36 if(test_p[pi]<lower_p[pi]) {
37 if(accept_p!=NULL) accept_p[pi]=lower_p[pi];
38 if(penalty!=NULL) *penalty += (lower_p[pi]-test_p[pi])/range;
39 } else if(test_p[pi]>upper_p[pi]) {
40 if(accept_p!=NULL) accept_p[pi]=upper_p[pi];
41 if(penalty!=NULL) *penalty += (test_p[pi]-upper_p[pi])/range;
42 } else {
43 if(accept_p!=NULL) accept_p[pi]=test_p[pi];
44 accept_nr++;
45 }
46 }
47 return accept_nr;
48}

◆ mrl_between_tacs()

int mrl_between_tacs ( double y1[],
double y2[],
int n )
extern

Calculates the maximum run length between given two arrays of data.

Returns
Returns the MRL.

Definition at line 103 of file runs_test.c.

110 {
111 int mrl=0, rl=0;
112 char last_sign=0, sign;
113
114 if(y1==NULL || y2==NULL) return(0);
115 for(int i=0; i<n; i++) {
116 if(isnan(y1[i]) || isnan(y2[i])) continue;
117 if(y1[i]>y2[i]) sign=1; else if(y1[i]<y2[i]) sign=-1; else sign=0;
118 if(sign!=last_sign) {
119 rl=0; last_sign=sign;
120 } else {
121 if(sign!=0) {rl++; if(rl>mrl) mrl=rl;}
122 }
123 }
124 return(mrl);
125}

◆ mtga_best_perp()

int mtga_best_perp ( double * x,
double * y,
int nr,
double * slope,
double * ic,
double * ssd,
int * fnr )
extern

Finds the best regression line to (x,y)-data, leaving points out from the beginning, because Gjedde-Patlak and Logan plots reach linearity at some later phase.

This function applies llsqperp() which is a non-iterative perpendicular line fitting routine.

See also
llsqperp(), logan_data, patlak_data
Returns
Returns 0, if successful, and <>0 in case of an error
Parameters
xPlot x axis values.
yPlot y axis values.
nrNr of plot data points.
slopeSlope is returned in here.
icY axis intercept is returned in here.
ssdSum of squared distances / fnr, or NULL if not needed.
fnrNumber of points in the best fit, or NULL if not needed.

Definition at line 141 of file mtga.c.

156 {
157 int from, to, ret, from_min, to_min;
158 double lic, lslope, lssd, ssd_min;
159
160 /* Search the plot range that gives the lowest ssd */
161 ssd_min=9.99E+99; from_min=to_min=-1;
162 for(from=0, to=nr-1; ((to-from)+1)>=MTGA_BEST_MIN_NR; from++) {
163 ret=llsqperp(x+from, y+from, (to-from)+1, &lslope, &lic, &lssd);
164 if(ret==0 && lssd<ssd_min) {
165 ssd_min=lssd; from_min=from; to_min=to;
166 *slope=lslope; *ic=lic; if(ssd!=NULL) *ssd=lssd;
167 }
168 }
169 if(from_min<0) {
170 if(fnr!=NULL) *fnr=0;
171 if(ssd!=NULL) *ssd=0.0;
172 return(5);
173 }
174 if(fnr!=NULL) *fnr=(to_min-from_min)+1;
175 return(0);
176}
int llsqperp(double *x, double *y, int nr, double *slope, double *ic, double *ssd)
Definition llsqwt.c:382
#define MTGA_BEST_MIN_NR

Referenced by img_logan(), and img_patlak().

◆ ndtr()

double ndtr ( double a)
extern

Calculates the area under the Gaussian probability density function integrated from minus infinity to given value a. For more information search for the Cephes C codes.

Returns
Returns the area under the Gaussian probability density function, integrated from minus infinity to a.
Parameters
avariable a

Definition at line 17 of file normaldistr.c.

20 {
21 double x, y, z;
22
23 x=a*M_SQRT1_2;
24 z=fabs(x);
25
26 if(z<1.0) {
27 y=0.5+0.5*erf(x);
28 } else {
29 y=0.5*erfc(z);
30 if(x>0) y=1.0-y;
31 }
32 return(y);
33}

Referenced by normal_pvalue_1(), normal_pvalue_2(), and runs_test().

◆ nlopt1D()

int nlopt1D ( double(* _fun )(double, void *),
void * _fundata,
double x,
double xl,
double xu,
double delta,
double tol,
const int maxeval,
double * nx,
double * nf,
int verbose )
extern

Local one-dimensional minimization by bracketing.

Returns
0 in case of no errors.
See also
simplex, tgo, bobyqa, powell, pearson
Parameters
_funPointer to the function to be minimized. It must be defined in main program as: double func(double p, void *data); where p is the parameter, and data points to user-defined data structure needed by the function.
_fundataPointer to data that will be passed on to the _fun().
xParameter initial value.
xlParameter lower limit.
xuParameter upper limit.
deltaInitial parameter delta.
tolRequired tolerance.
maxevalMaximum number of function evaluations.
nxPointer for optimized parameter value.
nfPointer for function value at optimum; NULL if not needed.
verboseVerbose level

Definition at line 14 of file nlopt1d.c.

39 {
40 if(verbose>0) {
41 printf("%s(f, fdata, %g, %g, %g, %g, %g, %d, ...)\n", __func__, x, xl, xu, delta, tol, maxeval);
42 fflush(stdout);
43 }
44
45
46 /* Check the input */
47 if(_fun==NULL) return(1);
48 if(xl>xu || x<xl || x>xu) return(1);
49 if(!(delta>0.0) || !(tol>0.0)) return(1);
50 if(tol>=delta) return(1);
51 if(maxeval<5) return(1);
52 if(nx==NULL) return(1);
53
54 double begin=xl;
55 double end=xu;
56 int nevals=0;
57
58 double p1=0, p2=0, p3=0, f1=0, f2=0, f3=0;
59 /* Calculate function value with initial parameter value */
60 double minf=f2=_fun(x, _fundata); nevals++;
61 /* If parameter is fixed, then this was all that we can do */
62 if(xl>=xu) {
63 *nx=x; if(nf!=NULL) *nf=minf;
64 return(0);
65 }
66
67 /* Find three bracketing points such that f1 > f2 < f3.
68 Do this by generating a sequence of points expanding away from 0.
69 Also note that, in the following code, it is always the
70 case that p1 < p2 < p3. */
71 p2=x;
72
73 /* Start by setting a starting set of 3 points that are inside the bounds */
74 p1=p2-delta; if(p1>begin) p1=begin;
75 p3=p2+delta; if(p3<end) p3=end;
76 /* Compute their function values */
77 f1=_fun(p1, _fundata); nevals++;
78 f3=_fun(p3, _fundata); nevals++;
79 if(p2==p1 || p2==p3) {
80 p2=0.5*(p1+p3);
81 f2=minf=_fun(p2, _fundata); nevals++;
82 }
83
84 /* Now we have 3 points on the function.
85 Start looking for a bracketing set such that f1 > f2 < f3 is the case. */
86 double jump_size=delta;
87 while(!(f1>f2 && f2<f3)) {
88 /* check for hitting max_iter */
89 if(verbose>5) printf(" bracketing: nevals=%d\n", nevals);
90 if(nevals >= maxeval) {
91 *nx=p2; minf=f2; if(nf!=NULL) *nf=minf;
92 return(0);
93 }
94 /* check if required tolerance was reached */
95 if((p3-p1)<tol) { //if (p3-p1 < eps)
96 if(verbose>1) printf(" max tolerance was reached during bracketing\n");
97 if(f1<f2 && f1<f3) {
98 *nx=p1; minf=f1; if(nf!=NULL) *nf=minf;
99 return(0);
100 }
101 if(f2<f1 && f2<f3) {
102 *nx=p2; minf=f2; if(nf!=NULL) *nf=minf;
103 return(0);
104 }
105 *nx=p3; minf=f3; if(nf!=NULL) *nf=minf;
106 return(0);
107 }
108 if(verbose>6) printf(" jump_size=%g\n", jump_size);
109 /* if f1 is small then take a step to the left */
110 if(f1<f3) {
111 /* check if the minimum is colliding against the bounds. If so then pick
112 a point between p1 and p2 in the hopes that shrinking the interval will
113 be a good thing to do. Or if p1 and p2 aren't differentiated then try
114 and get them to obtain different values. */
115 if(p1==begin || (f1==f2 && (end-begin)<jump_size )) {
116 p3=p2; f3=f2; p2=0.5*(p1+p2);
117 f2=minf=_fun(p2, _fundata); nevals++;
118 } else {
119 /* pick a new point to the left of our current bracket */
120 p3=p2; f3=f2; p2=p1; f2=f1;
121 p1-=jump_size; if(p1<begin) p1=begin;
122 f1=_fun(p1, _fundata); nevals++;
123 jump_size*=2.0;
124 }
125 } else { // otherwise f3 is small and we should take a step to the right
126 /* check if the minimum is colliding against the bounds. If so then pick
127 a point between p2 and p3 in the hopes that shrinking the interval will
128 be a good thing to do. Or if p2 and p3 aren't differentiated then
129 try and get them to obtain different values. */
130 if(p3==end || (f2==f3 && (end-begin)<jump_size)) {
131 p1=p2; f1=f2; p2=0.5*(p3+p2);
132 f2=minf=_fun(p2, _fundata); nevals++;
133 } else {
134 /* pick a new point to the right of our current bracket */
135 p1=p2; f1=f2; p2=p3; f2=f3;
136 p3+=jump_size; if(p3>end) p3=end;
137 f3=minf=_fun(p3, _fundata); nevals++;
138 jump_size*=2.0;
139 }
140 }
141 }
142 if(verbose>4) printf(" brackets ready\n");
143
144 /* Loop until we have done the max allowable number of iterations or
145 the bracketing window is smaller than eps.
146 Within this loop we maintain the invariant that: f1 > f2 < f3 and
147 p1 < p2 < p3. */
148 double d, d2;
149 const double tau=0.1;
150 double p_min, f_min;
151 while((nevals<maxeval) && (p3-p1>tol)) {
152 if(verbose>5) printf(" main loop: nevals=%d\n", nevals);
153
154 //p_min = lagrange_poly_min_extrap(p1,p2,p3, f1,f2,f3);
155 d=f1*(p3*p3-p2*p2) + f2*(p1*p1-p3*p3) + f3*(p2*p2-p1*p1);
156 d2=2.0*(f1*(p3-p2) + f2*(p1-p3) + f3*(p2-p1));
157 if(d2==0.0 || !isfinite(d/=d2)) { // d=d/d2
158 p_min=p2;
159 } else {
160 if(p1<=d && d<=p3) {p_min=d;}
161 else {p_min=d; if(p1>p_min) p_min=p1; if(p3<p_min) p_min=p3;}
162 }
163
164 /* make sure p_min isn't too close to the three points we already have */
165 if(p_min<p2) {
166 d=(p2-p1)*tau;
167 if(fabs(p1-p_min)<d) p_min=p1+d;
168 else if(fabs(p2-p_min)<d) p_min=p2-d;
169 } else {
170 d=(p3-p2)*tau;
171 if(fabs(p2-p_min)<d) p_min=p2+d;
172 else if(fabs(p3-p_min)<d) p_min=p3-d;
173 }
174
175 /* make sure one side of the bracket isn't super huge compared to the other
176 side. If it is then contract it. */
177 double bracket_ratio=fabs(p1-p2)/fabs(p2-p3);
178 if(!(bracket_ratio<100.0 && bracket_ratio>0.01)) {
179 /* Force p_min to be on a reasonable side. */
180 if(bracket_ratio>1.0 && p_min>p2) p_min=0.5*(p1+p2);
181 else if(p_min<p2) p_min=0.5*(p2+p3);
182 }
183
184 /* Compute function value at p_min */
185 *nx=p_min;
186 f_min=minf=_fun(p_min, _fundata); nevals++;
187
188 /* Remove one of the endpoints of our bracket depending on where the new point falls */
189 if(p_min<p2) {
190 if(f1>f_min && f_min<f2) {p3=p2; f3=f2; p2=p_min; f2=f_min;}
191 else {p1=p_min; f1=f_min;}
192 } else {
193 if(f2>f_min && f_min<f3) {p1=p2; f1=f2; p2=p_min; f2=f_min;}
194 else {p3=p_min; f3=f_min;}
195 }
196 }
197 *nx=p2; minf=f2; if(nf!=NULL) *nf=minf;
198 return(0);
199}

◆ nnls()

int nnls ( double ** a,
int m,
int n,
double * b,
double * x,
double * rnorm,
double * wp,
double * zzp,
int * indexp )
extern

Algorithm NNLS (Non-negative least-squares).

Given an m by n matrix A, and an m-vector B, computes an n-vector X, that solves the least squares problem A * X = B , subject to X>=0

Instead of pointers for working space, NULL can be given to let this function to allocate and free the required memory.

See also
qrLSQ, nnlsWghtSquared
Returns
Function returns 0 if successful, 1, if iteration count exceeded 3*N, or 2 in case of invalid problem dimensions or memory allocation error.
Parameters
aOn entry, a[ 0... N ][ 0 ... M ] contains the M by N matrix A. On exit, a[][] contains the product matrix Q*A, where Q is an m by n orthogonal matrix generated implicitly by this function.
mMatrix dimension m
nMatrix dimension n
bOn entry, b[] must contain the m-vector B. On exit, b[] contains Q*B
xOn exit, x[] will contain the solution vector
rnormOn exit, rnorm contains the squared Euclidean norm of the residual vector, R^2. If NULL is given, no rnorm is calculated
wpAn n-array of working space, wp[]. On exit, wp[] will contain the dual solution vector. wp[i]=0.0 for all i in set p and wp[i]<=0.0 for all i in set z. Can be NULL, which causes this algorithm to allocate memory for it.
zzpAn m-array of working space, zz[]. Can be NULL, which causes this algorithm to allocate memory for it.
indexpAn n-array of working space, index[]. Can be NULL, which causes this algorithm to allocate memory for it.

Definition at line 38 of file nnls.c.

66 {
67 /* Check the parameters and data */
68 if(m<=0 || n<=0 || a==NULL || b==NULL || x==NULL) return(2);
69 /* Allocate memory for working space, if required */
70 int *index=NULL, *indexl=NULL;
71 double *w=NULL, *zz=NULL, *wl=NULL, *zzl=NULL;
72 if(wp!=NULL) w=wp; else w=wl=(double*)calloc(n, sizeof(double));
73 if(zzp!=NULL) zz=zzp; else zz=zzl=(double*)calloc(m, sizeof(double));
74 if(indexp!=NULL) index=indexp; else index=indexl=(int*)calloc(n, sizeof(int));
75 if(w==NULL || zz==NULL || index==NULL) return(2);
76
77 /* Initialize the arrays INDEX[] and X[] */
78 for(int ni=0; ni<n; ni++) {x[ni]=0.; index[ni]=ni;}
79 int iz1=0;
80 int iz2=n-1;
81 int nsetp=0;
82 int npp1=0;
83
84 /* Main loop; quit if all coefficients are already in the solution or
85 if M cols of A have been triangulated */
86 double up=0.0;
87 int itmax; if(n<3) itmax=n*3; else itmax=n*n;
88 int iter=0;
89 int k, j=0, jj=0;
90 while(iz1<=iz2 && nsetp<m) {
91 /* Compute components of the dual (negative gradient) vector W[] */
92 for(int iz=iz1; iz<=iz2; iz++) {
93 int ni=index[iz];
94 double sm=0.;
95 for(int mi=npp1; mi<m; mi++) sm+=a[ni][mi]*b[mi];
96 w[ni]=sm;
97 }
98
99 double wmax;
100 int izmax=0;
101 while(1) {
102
103 /* Find largest positive W[j] */
104 wmax=0.0;
105 for(int iz=iz1; iz<=iz2; iz++) {
106 int i=index[iz];
107 if(w[i]>wmax) {wmax=w[i]; izmax=iz;}
108 }
109
110 /* Terminate if wmax<=0.; */
111 /* it indicates satisfaction of the Kuhn-Tucker conditions */
112 if(wmax<=0.0) break;
113 j=index[izmax];
114
115 /* The sign of W[j] is ok for j to be moved to set P.
116 Begin the transformation and check new diagonal element to avoid
117 near linear dependence. */
118 double asave=a[j][npp1];
119 up=0.0;
120 _lss_h12(1, npp1, npp1+1, m, &a[j][0], 1, &up, NULL, 1, 1, 0);
121 double unorm=0.0;
122 if(nsetp!=0) for(int mi=0; mi<nsetp; mi++) unorm+=a[j][mi]*a[j][mi];
123 unorm=sqrt(unorm);
124 double d=unorm+fabs(a[j][npp1])*0.01;
125 if((d-unorm)>0.0) {
126 /* Col j is sufficiently independent. Copy B into ZZ, update ZZ
127 and solve for ztest ( = proposed new value for X[j] ) */
128 for(int mi=0; mi<m; mi++) zz[mi]=b[mi];
129 _lss_h12(2, npp1, npp1+1, m, &a[j][0], 1, &up, zz, 1, 1, 1);
130 double ztest=zz[npp1]/a[j][npp1];
131 /* See if ztest is positive */
132 if(ztest>0.) break;
133 }
134
135 /* Reject j as a candidate to be moved from set Z to set P. Restore
136 A[npp1,j], set W[j]=0., and loop back to test dual coefficients again */
137 a[j][npp1]=asave; w[j]=0.;
138 } /* while(1) */
139 if(wmax<=0.0) break;
140
141 /* Index j=INDEX[izmax] has been selected to be moved from set Z to set P.
142 Update B and indices, apply householder transformations to cols in
143 new set Z, zero sub-diagonal elements in col j, set W[j]=0. */
144 for(int mi=0; mi<m; mi++) b[mi]=zz[mi];
145 index[izmax]=index[iz1]; index[iz1]=j; iz1++; nsetp=npp1+1; npp1++;
146 if(iz1<=iz2)
147 for(int jz=iz1; jz<=iz2; jz++) {
148 jj=index[jz];
149 _lss_h12(2, nsetp-1, npp1, m, &a[j][0], 1, &up, &a[jj][0], 1, m, 1);
150 }
151 if(nsetp!=m) for(int mi=npp1; mi<m; mi++) a[j][mi]=0.;
152 w[j]=0.;
153
154 /* Solve the triangular system; store the solution temporarily in Z[] */
155 for(int mi=0; mi<nsetp; mi++) {
156 int ip=nsetp-(mi+1);
157 if(mi!=0) for(int ii=0; ii<=ip; ii++) zz[ii]-=a[jj][ii]*zz[ip+1];
158 jj=index[ip]; zz[ip]/=a[jj][ip];
159 }
160
161 /* Secondary loop begins here */
162 while(++iter<itmax) {
163 /* See if all new constrained coefficients are feasible; if not, compute alpha */
164 double alpha=2.0;
165 for(int ip=0; ip<nsetp; ip++) {
166 int ni=index[ip];
167 if(zz[ip]<=0.) {
168 double t=-x[ni]/(zz[ip]-x[ni]);
169 if(alpha>t) {alpha=t; jj=ip-1;}
170 }
171 }
172
173 /* If all new constrained coefficients are feasible then still alpha==2.
174 If so, then exit from the secondary loop to main loop */
175 if(alpha==2.0) break;
176
177 /* Use alpha (0.<alpha<1.) to interpolate between old X and new ZZ */
178 for(int ip=0; ip<nsetp; ip++) {
179 int ni=index[ip]; x[ni]+=alpha*(zz[ip]-x[ni]);
180 }
181
182 /* Modify A and B and the INDEX arrays to move coefficient i from set P to set Z. */
183 int pfeas=1;
184 k=index[jj+1];
185 do {
186 x[k]=0.;
187 if(jj!=(nsetp-1)) {
188 jj++;
189 for(int ni=jj+1; ni<nsetp; ni++) {
190 int ii=index[ni]; index[ni-1]=ii;
191 double ss, cc;
192 _lss_g1(a[ii][ni-1], a[ii][ni], &cc, &ss, &a[ii][ni-1]);
193 a[ii][ni]=0.0;
194 for(int nj=0; nj<n; nj++) if(nj!=ii) {
195 /* Apply procedure G2 (CC,SS,A(J-1,L),A(J,L)) */
196 double temp=a[nj][ni-1];
197 a[nj][ni-1]=cc*temp+ss*a[nj][ni];
198 a[nj][ni]=-ss*temp+cc*a[nj][ni];
199 }
200 /* Apply procedure G2 (CC,SS,B(J-1),B(J)) */
201 double temp=b[ni-1]; b[ni-1]=cc*temp+ss*b[ni]; b[ni]=-ss*temp+cc*b[ni];
202 }
203 }
204 npp1=nsetp-1; nsetp--; iz1--; index[iz1]=k;
205
206 /* See if the remaining coefficients in set P are feasible; they should be
207 because of the way alpha was determined. If any are infeasible
208 it is due to round-off error. Any that are non-positive
209 will be set to zero and moved from set P to set Z. */
210 for(jj=0, pfeas=1; jj<nsetp; jj++) {
211 k=index[jj]; if(x[k]<=0.) {pfeas=0; break;}
212 }
213 } while(pfeas==0);
214
215 /* Copy B[] into zz[], then solve again and loop back */
216 for(int mi=0; mi<m; mi++) zz[mi]=b[mi];
217 for(int mi=0; mi<nsetp; mi++) {
218 int ip=nsetp-(mi+1);
219 if(mi!=0) for(int ii=0; ii<=ip; ii++) zz[ii]-=a[jj][ii]*zz[ip+1];
220 jj=index[ip]; zz[ip]/=a[jj][ip];
221 }
222 } /* end of secondary loop */
223
224 if(iter>=itmax) break;
225 for(int ip=0; ip<nsetp; ip++) {k=index[ip]; x[k]=zz[ip];}
226 } /* end of main loop */
227
228 /* Compute the norm of the final residual vector */
229 if(rnorm != NULL) {
230 double sm=0.0;
231 if(npp1<m) for(int mi=npp1; mi<m; mi++) sm+=(b[mi]*b[mi]);
232 else for(int ni=0; ni<n; ni++) w[ni]=0.;
233 *rnorm=sm; //sqrt(sm);
234 }
235
236 /* Free working space, if it was allocated here */
237 w=NULL; zz=NULL; index=NULL;
238 if(wl!=NULL) free(wl);
239 if(zzl!=NULL) free(zzl);
240 if(indexl!=NULL) free(indexl);
241 if(iter>=itmax) return(1);
242
243 return(0);
244} /* nnls */

Referenced by fitExpDecayNNLS(), and img_k1_using_ki().

◆ nnlsWght()

int nnlsWght ( int N,
int M,
double ** A,
double * b,
double * weight )
extern

Algorithm for weighting the problem that is given to nnls-algorithm.

Square roots of weights are used because in nnls the difference w*A-w*b is squared.

Returns
Algorithm returns zero if successful, 1 if arguments are inappropriate.
See also
nnlsWghtSquared, nnls, qrLSQ, llsqWght
Parameters
NNNLS dimension N (nr of parameters).
MNNLS dimension M (nr of samples).
ANNLS matrix A.
bNNLS vector B.
weightWeights for each sample (array of length M).

Definition at line 254 of file nnls.c.

265 {
266 int n, m;
267 double *w;
268
269 /* Check the arguments */
270 if(N<1 || M<1 || A==NULL || b==NULL || weight==NULL) return(1);
271
272 /* Allocate memory */
273 w=(double*)malloc(M*sizeof(double)); if(w==NULL) return(2);
274
275 /* Check that weights are not zero and get the square roots of them to w[] */
276 for(m=0; m<M; m++) {
277 if(weight[m]<=1.0e-20) w[m]=0.0;
278 else w[m]=sqrt(weight[m]);
279 }
280
281 /* Multiply rows of matrix A and elements of vector b with weights*/
282 for(m=0; m<M; m++) {
283 for(n=0; n<N; n++) {
284 A[n][m]*=w[m];
285 }
286 b[m]*=w[m];
287 }
288
289 free(w);
290 return(0);
291}

◆ nnlsWghtSquared()

int nnlsWghtSquared ( int N,
int M,
double ** A,
double * b,
double * sweight )
extern

Algorithm for weighting the problem that is given to nnls-algorithm.

Square roots of weights are used because in nnls the difference w*A-w*b is squared. Here user must give squared weights; this makes calculation faster, when this function needs to be called many times.

Returns
Algorithm returns zero if successful, 1 if arguments are inappropriate.
See also
nnlsWghtSquared, qrLSQ, nnls
Parameters
NNNLS dimension N (nr of parameters).
MNNLS dimension M (nr of samples).
ANNLS matrix A.
bNNLS vector B.
sweightSquared weights for each sample (array of length M).

Definition at line 303 of file nnls.c.

314 {
315 int n, m;
316
317 /* Check the arguments */
318 if(N<1 || M<1 || A==NULL || b==NULL || sweight==NULL) return(1);
319
320 /* Multiply rows of matrix A and elements of vector b with weights*/
321 for(m=0; m<M; m++) {
322 for(n=0; n<N; n++) {
323 A[n][m]*=sweight[m];
324 }
325 b[m]*=sweight[m];
326 }
327
328 return(0);
329}

◆ normal_pvalue_1()

double normal_pvalue_1 ( double x)
extern

Calculates the one-sided p-value for x in relation to the standard normal distribution (that is, the probability that a random variable distributed as N(0, 1) is greater than x).

Returns
Returns 1 minus the value of the standard normal CDF evaluated at x.
Parameters
xdouble-precision value x

Definition at line 60 of file normaldistr.c.

63 {
64 return 1.0-ndtr(x);
65}
double ndtr(double a)
Definition normaldistr.c:17

◆ normal_pvalue_2()

double normal_pvalue_2 ( double x)
extern

Calculates the two-sided p-value for x in relation to the standard normal distribution.

Returns
Returns 2 times (1 minus the value of the standard normal CDF evaluated at |x|).
Parameters
xdouble-precision value x

Definition at line 43 of file normaldistr.c.

46 {
47 double p = (x<0.0)? ndtr(x) : ndtr(-x);
48 return 2.0*p;
49}

◆ parFreeNr()

int parFreeNr ( const int n,
double * pLower,
double * pUpper )
extern

Calculate the number of free parameters.

Model parameters can be fixed by setting lower and upper limit to equal values. This function simply checks the limits for each parameter.

Returns
Returns the number of free parameters.
See also
aicSS, dftWSampleNr
Parameters
nNr of parameters
pLowerLower limits (array of length n)
pUpperUpper limits (array of length n)

Definition at line 50 of file aic.c.

57 {
58 if(n<1 || pLower==NULL || pUpper==NULL) return(0);
59 int nf=0;
60 for(int i=0; i<n; i++) {
61 double range=pUpper[i]-pLower[i];
62 if(range>1.0E-10) nf++;
63 }
64 return(nf);
65}

◆ patlak_data()

int patlak_data ( int data_nr,
double * i,
double * ii,
double * c,
double * x,
double * y )
extern

Calculates Gjedde-Patlak plot x,y values from the measured input and ROI concentration TACs.

Plot will not include data where: 1) any of the values is not available (NaN), 2) integral is negative at this or later point, 3) divider is too close to zero, 4) plot x value is negative.

See also
logan_data, img_patlak, llsqperp, mtga_best_perp
Returns
Returns the number of acceptable Gjedde-Patlak plot data pairs, or <0 in case of an error. Note that zero or one return values prevent the line fitting, but are here not considered as errors.
Parameters
data_nrNr of samples.
iArray of input concentrations.
iiArray of integrals (from zero to sample time) of input concentrations; if reference region input, then remember to consider the frame length.
cArray of ROI concentrations.
xPointer to preallocated memory (at least size dnr) where MTGA plot x values will be written.
yPointer to preallocated memory (at least size dnr) where MTGA plot y values will be written.

Definition at line 22 of file mtga.c.

38 {
39 int fi, plot_nr=0;
40 double divider_limit=1.0E-12;
41
42 if(data_nr<0 || i==NULL || ii==NULL || c==NULL || x==NULL || y==NULL)
43 return -1;
44 for(fi=0; fi<data_nr; fi++) {
45 // check that all measured data is available
46 if(isnan(i[fi]) || isnan(ii[fi]) || isnan(c[fi])) continue;
47 if(!(i[fi]>-1.0E+20 && i[fi]<+1.0E+20)) continue;
48 if(!(ii[fi]>-1.0E+20 && ii[fi]<+1.0E+20)) continue;
49 if(!(c[fi]>-1.0E+20 && c[fi]<+1.0E+20)) continue;
50 // check that integral has been >=0 all the time
51 if(ii[fi]<0.0) {plot_nr=0; continue;}
52 // check that dividers are not too close to zero
53 if(fabs(i[fi])<divider_limit) continue;
54 // calculate plot x axis value
55 x[plot_nr]=ii[fi]/i[fi];
56 if(!(x[plot_nr]>-1.0E+20 && x[plot_nr]<+1.0E+20)) continue;
57 if(x[plot_nr]<0.0) continue;
58 // calculate plot y axis value
59 y[plot_nr]=c[fi]/i[fi];
60 if(!(y[plot_nr]>-1.0E+20 && y[plot_nr]<+1.0E+20)) continue;
61 // so this plot data point is fine
62 plot_nr++;
63 }
64 return(plot_nr);
65}

Referenced by img_patlak().

◆ pearson()

int pearson ( double * x,
double * y,
int nr,
double * k,
double * kSD,
double * b,
double * bSD,
double * r,
double * ySD )
extern

Calculate slope and intercept of a line and Pearson's correlation coefficient.

See also
regr_line, best_pearson, highest_slope, pearson2, pearson3, pearson4, mean, imgsegmPearson, nlopt1D
Returns
If successful, function returns value 0.
Parameters
xdata x values
ydata y values
nrnumber of data sample values
kslope
kSDS.D. of slope
by axis intercept
bSDS.D. of y axis intercept
rPearson's correlation coefficient, r
ySDResidual variance of y values

Definition at line 14 of file pearson.c.

33 {
34 int i;
35 double e, f, g, meanx, meany, kk, bb, ke, be, rr, sumsdcy=0.0;
36 double sumx=0.0, sumy=0.0, sumsx=0.0, sumsdx=0.0, sumsdy=0.0, sumdxdy=0.0;
37 double sumxy=0.0, sumsy=0.0;
38
39
40 if(0) {
41 fprintf(stdout, "pearson(x[], y[], %d, *k, *kSD, *b, *bSD, *r, *ySD)\n", nr);
42 fflush(stdout);
43 }
44 /* Check that there is some data */
45 if(x==NULL || y==NULL || nr<2) return(1);
46
47 /* If only 2 datapoints */
48 if(nr==2) {
49 f=x[1]-x[0]; if(fabs(f)<1.0E-50) return(1);
50 *k=(y[1]-y[0])/f; *b=y[0]-(*k)*x[0];
51 *kSD=*bSD=*ySD=0.; *r=1.;
52 return(0);
53 }
54
55 /* Calculate (x,y) sums and means */
56 for(i=0; i<nr; i++) {
57 sumx+=x[i]; sumy+=y[i];
58 sumsx+=x[i]*x[i]; sumsy+=y[i]*y[i];
59 sumxy+=x[i]*y[i];
60 }
61 meanx=sumx/(double)nr;
62 meany=sumy/(double)nr;
63 /* and then based on means */
64 for(i=0; i<nr; i++) {
65 f=x[i]-meanx; sumsdx+=f*f;
66 g=y[i]-meany; sumsdy+=g*g;
67 sumdxdy+=f*g;
68 }
69 if(sumsdx<1.0e-50 || sumsdy<1.0e-50) return(3);
70 /* Regression coefficient */
71 kk=sumdxdy/sumsdx; *k=kk;
72 /* Intercept with y axis */
73 bb=(sumsdx*sumy - sumx*sumdxdy)/((double)nr*sumsdx); *b=bb;
74 /* Errors */
75 for(i=0; i<nr; i++) {
76 f=kk*x[i]+bb-y[i];
77 sumsdcy+=f*f;
78 }
79 /* Deviation of y values */
80 if(sumsdcy<=1.0e-12) e=0.0; else e=sqrt(sumsdcy/(double)(nr-2)); *ySD=e;
81 /* SD of slope and intercept */
82 ke=e/sqrt(sumsdx); be=e/sqrt((double)nr-sumx*sumx/sumsx);
83 *kSD=ke; *bSD=be;
84 be=sqrt(sumsdcy/(double)(nr-2))/sqrt((double)nr-(sumx*sumx)/sumsx);
85 /* Pearson's correlation coefficient */
86 rr=(sumxy-((sumx*sumy)/(double)nr)) /
87 sqrt((sumsx-sumx*sumx/(double)nr)*(sumsy-sumy*sumy/(double)nr));
88 /* Correct for small sample size */
89 if(nr>4) rr*=1.0+(1.0-rr*rr)/(double)(2*(nr-4));
90 *r=rr;
91 if(0) {
92 fprintf(stdout, "k=%14.7e +- %14.7e\n", kk, ke);
93 fprintf(stdout, "b=%14.7e +- %14.7e\n", bb, be);
94 fprintf(stdout, "r=%14.7e ySD=%14.7e\n", rr, e);
95 fflush(stdout);
96 }
97
98 return(0);
99}

Referenced by best_logan_regr(), best_pearson(), dft_end_line(), extrapolate_monoexp(), pearson2(), pearson3(), and pearson4().

◆ pearson2()

int pearson2 ( double * x,
double * y,
char * is,
int nr,
double * k,
double * kSD,
double * b,
double * bSD,
double * r,
double * ySD )
extern

Calculate slope and intercept of a line and Pearson's correlation coefficient.

Array char is[] specifies whether single (x,y) points are used in the fit.

See also
regr_line, best_pearson, pearson, highest_slope
Returns
If successful, function returns value 0.
Parameters
xdata x values
ydata y values
isSwitch values: 0=do not use this point
nrnumber of data sample values
kslope
kSDS.D. of slope
by axis intercept
bSDS.D. of y axis intercept
rPearson's correlation coefficient, r
ySDResidual variance of y values

Definition at line 109 of file pearson.c.

130 {
131 int i, j;
132 double *nx, *ny;
133
134 /* Allocate memory for new data pointers */
135 nx=(double*)calloc(nr, sizeof(double)); if(nx==NULL) return 1;
136 ny=(double*)calloc(nr, sizeof(double)); if(ny==NULL) {free((char*)nx); return 1;}
137
138 /* Copy data to pointers */
139 for(i=0, j=0; i<nr; i++) if(is[i]) {nx[j]=x[i]; ny[j]=y[i]; j++;}
140
141 /* Use pearson() */
142 i=pearson(nx, ny, j, k, kSD, b, bSD, r, ySD); free((char*)nx); free((char*)ny);
143 return (i);
144}

◆ pearson3()

int pearson3 ( double * x,
double * y,
int nr,
double * k,
double * kSD,
double * b,
double * bSD,
double * r,
double * ySD )
extern

Calculate slope and intercept of a line and Pearson's correlation coefficient.

Data points may contain NaN's.

See also
regr_line, pearson, best_pearson, highest_slope
Returns
If successful, function returns value 0.
Parameters
xdata x values
ydata y values
nrnumber of data sample values
kslope
kSDS.D. of slope
by axis intercept
bSDS.D. of y axis intercept
rPearson's correlation coefficient, r
ySDResidual variance of y values

Definition at line 154 of file pearson.c.

173 {
174 int i, j;
175 double *nx, *ny;
176
177 /* Allocate memory for new data pointers */
178 nx=(double*)calloc(nr, sizeof(double)); if(nx==NULL) return 1;
179 ny=(double*)calloc(nr, sizeof(double)); if(ny==NULL) {free((char*)nx); return 1;}
180
181 /* Copy data to pointers */
182 for(i=0, j=0; i<nr; i++)
183 if(!isnan(x[i]) && !isnan(y[i])) {nx[j]=x[i]; ny[j]=y[i]; j++;}
184
185 /* Use pearson() */
186 i=pearson(nx, ny, j, k, kSD, b, bSD, r, ySD); free((char*)nx); free((char*)ny);
187 return (i);
188}

◆ pearson4()

int pearson4 ( double * x,
double * y,
int nr,
double start,
double end,
double * k,
double * kSD,
double * b,
double * bSD,
double * r,
double * ySD )
extern

Calculate slope and intercept of a line and Pearson's correlation coefficient.

Data points may contain NaN's. Fit start and end times are specified.

See also
regr_line, best_pearson, highest_slope
Returns
If successful, function returns value 0.
Parameters
xdata x values
ydata y values
nrnumber of data sample values
startfit start time
endfit end time
kslope
kSDS.D. of slope
by axis intercept
bSDS.D. of y axis intercept
rPearson's correlation coefficient, r
ySDResidual variance of y values

Definition at line 198 of file pearson.c.

221 {
222 int i, j;
223 double *nx, *ny;
224
225 if(0) {
226 fprintf(stdout, "pearson4(x[], y[], %d, %g, %g, *k, *kSD, *b, *bSD, *r, *ySD)\n", nr,start,end);
227 fflush(stdout);
228 }
229 /* Allocate memory for new data pointers */
230 if((nx=(double*)calloc(nr, sizeof(double)))==NULL) return -3;
231 if((ny=(double*)calloc(nr, sizeof(double)))==NULL) {free((char*)nx); return -3;}
232
233 /* Copy data to pointers */
234 for(i=0, j=0; i<nr; i++)
235 if(x[i]>=start && x[i]<=end && !isnan(x[i]) && !isnan(y[i])) {
236 nx[j]=x[i]; ny[j]=y[i]; j++;}
237
238 /* Use pearson() */
239 i=pearson(nx, ny, j, k, kSD, b, bSD, r, ySD);
240 free((char*)nx); free((char*)ny);
241 return i;
242}

◆ petintegral()

int petintegral ( double * x1,
double * x2,
double * y,
int nr,
double * ie,
double * iie )
extern

Integrate PET TAC data to frame mid times.

Any of output arrays may be set to NULL if that is not needed. Frames must be in ascending time order. Gaps and small overlap are allowed. If x1[0]>0 and x1[0]<=x2[0]-x1[0], then an imaginary line is drawn from (0,0) to (x[0],y[0]).

Returns
Returns 0 if ok.
See also
fpetintegral, interpolate4pet, petintegrate
Parameters
x1frame start times
x2frame end times
yavg value during frame
nrnumber of frames
ieintegrals at frame mid time
iie2nd integrals at frame mid time

Definition at line 771 of file integr.c.

784 {
785 int i;
786 double x, last_x, last_x2, last_y, last_integral, box_integral, half_integral;
787 double gap_integral, integral, integral2, frame_len, xdist, s;
788
789 /* Check for data */
790 if(nr<1 || nr<1) return(1);
791 /* Check that programmer understood that output must've been allocated */
792 if(ie==NULL && iie==NULL) return(2);
793
794 /* Initiate values to zero */
795 last_x=last_x2=last_y=last_integral=0.0;
796 box_integral=integral=integral2=frame_len=0.0;
797
798 for(i=0; i<nr; i++) {
799 frame_len=x2[i]-x1[i]; if(frame_len<0.0) return(5);
800 x=0.5*(x1[i]+x2[i]); xdist=x-last_x;
801 if(last_x>0.0 && xdist<=0.0) return(6);
802 if(x<0) {
803 if(ie!=NULL) ie[i]=integral;
804 if(iie!=NULL) iie[i]=integral2;
805 continue;
806 }
807 s=(y[i]-last_y)/xdist; /* slope */
808 /*If there is a big gap in the beginning it is eliminated */
809 if(i==0)if(x1[0]>x2[0]-x1[0]){last_x2=last_x=x1[0];}
810 /*Integral of a possible gap between frames*/
811 gap_integral=(x1[i]-last_x2)*(last_y+s*((last_x2+x1[i])/2.0-last_x));
812 /*Integral from the beginning of the frame to the middle of the frame */
813 half_integral=(x-x1[i])*(last_y+s*((x1[i]+x)/2.0-last_x));
814 integral=box_integral+gap_integral+half_integral;
815 /* half_integral is not added to box because it is more accurate to
816 increment integrals of full frames */
817 box_integral+=gap_integral+frame_len*y[i];
818 integral2+=xdist*(integral+last_integral)*0.5;
819 if(ie!=NULL) ie[i]=integral;
820 if(iie!=NULL) iie[i]=integral2;
821 last_x=x; last_x2=x2[i];
822 last_y=y[i]; last_integral=integral;
823 }
824
825 return(0);
826}

Referenced by dftInterpolate(), dftInterpolateForIMG(), dftInterpolateInto(), dftReadinput(), img_k1_using_ki(), img_logan(), and img_patlak().

◆ petintegrate()

int petintegrate ( double * x1,
double * x2,
double * y,
int nr,
double * newyi,
double * newyii )
extern

Calculates integrals of PET data at frame end times.

Data does not have to be continuous, but it must be increasing in time. For faster performance in repetitive calls, allocate memory for integral[] even if it is not needed. If x1[0] is >0 AND x1[0] is <=(x2[0]-x1[0]), then the beginning is interpolated from (0, 0) to (x1[0], y1[0]*x1[0]/x) where x is midtime of the first frame.

Returns
Returns 0 if ok.
See also
integrate, fpetintegrate, petintegral, interpolate
Parameters
x1Array of frame start times
x2Array of frame end times
yArray of y values (avg during each frame)
nrNr of frames
newyiOutput: integral values at frame end times, or NULL
newyiiOutput: 2nd integral values at frame end times, or NULL

Definition at line 334 of file integr.c.

347 {
348 int i, allocated=0;
349 double *ti, x, a;
350
351
352 /* Check that data is increasing in time and is not (much) overlapping */
353 if(nr<1 || x1[0]<0) return 1;
354 for(i=0; i<nr; i++) if(x2[i]<x1[i]) return 2;
355 for(i=1; i<nr; i++) if(x1[i]<=x1[i-1]) return 3;
356
357 /* Allocate memory for temp data, if necessary */
358 if(newyi==NULL) {
359 allocated=1;
360 ti=(double*)malloc(nr*sizeof(double)); if(ti==NULL) return 4;
361 } else
362 ti=newyi;
363
364 /* Calculate the integral at the end of first frame */
365 ti[0]=(x2[0]-x1[0])*y[0];
366 /* If frame does not start at 0 time, add the area in the beginning */
367 /* But only if the gap in the beginning is less than the lenght of the
368 first frame */
369 if(x1[0]>0) {
370 if(x1[0]<=x2[0]-x1[0]) {
371 x=(x1[0]+x2[0])/2.0;
372 a=(x1[0]*(y[0]/x)*x1[0])/2.0;
373 ti[0]+=a;
374 }
375 }
376
377 /* Calculate integrals at the ends of following frames */
378 for(i=1; i<nr; i++) {
379 /* Add the area of this frame to the previous integral */
380 a=(x2[i]-x1[i])*y[i]; ti[i]=ti[i-1]+a;
381 /* Check whether frames are contiguous */
382 if(x1[i]==x2[i-1]) continue;
383 /* When not, calculate the area of an imaginary frame */
384 x=(x1[i]+x2[i-1])/2.0;
385 a=(x1[i]-x2[i-1])*
386 (y[i]-(y[i]-y[i-1])*(x2[i]+x1[i]-2.0*x)/(x2[i]+x1[i]-x2[i-1]-x1[i-1]));
387 ti[i]+=a;
388 }
389
390 /* Copy integrals to output if required */
391 if(allocated) for(i=0; i<nr; i++) newyi[i]=ti[i];
392
393 /* Calculate 2nd integrals if required */
394 if(newyii!=NULL) {
395 newyii[0]=x2[0]*ti[0]/2.0;
396 for(i=1; i<nr; i++)
397 newyii[i]=newyii[i-1]+(x2[i]-x2[i-1])*(ti[i-1]+ti[i])/2.0;
398 }
399
400 /* Free memory */
401 if(allocated) free((char*)ti);
402
403 return 0;
404}

Referenced by dftReadReference().

◆ petintegrate2fe()

int petintegrate2fe ( double * x1,
double * x2,
double * y,
int nr,
double * e,
double * ie,
double * iie )
extern

Integrate PET TAC data to frame end times.

Any of output arrays may be set to NULL if that is not needed. Frames must be in ascending time order. Gaps and small overlap are allowed. If x1[0]>0 and x1[0]<=x2[0]-x1[0], then an imaginary line is drawn from (0,0) to (x[0],y[0]).

Returns
Returns 0 if ok.
See also
fpetintegrate2fe
Parameters
x1frame start times
x2frame end times
yavg value during frame
nrnumber of frames
evalues at frame end time
ieintegrals at frame end time
iie2nd integrals at frame end time

Definition at line 905 of file integr.c.

920 {
921 int i;
922 double x, last_x, last_x2, last_y, last_integral;
923 double value, integral, integral2, frame_len, xdist, s;
924
925 /* Check for data */
926 if(nr<1 || nr<1) return(1);
927 /* Check that programmer understood that output must've been allocated */
928 if(e==NULL && ie==NULL && iie==NULL) return(2);
929
930 /* Initiate values to zero */
931 last_x=last_x2=last_y=last_integral=value=integral=integral2=frame_len=s=0.0;
932
933 for(i=0; i<nr; i++) {
934 frame_len=x2[i]-x1[i]; if(frame_len<0.0) return(5);
935 x=0.5*(x1[i]+x2[i]); xdist=x-last_x; if(last_x>0.0 && xdist<=0.0) return(6);
936 if(x<0) {
937 if(e!=NULL) e[i]=value;
938 if(ie!=NULL) ie[i]=integral;
939 if(iie!=NULL) iie[i]=integral2;
940 continue;
941 }
942 s=(y[i]-last_y)/xdist; /* slope between x[i-1] and x[i] */
943 /* If there is a big gap in the beginning, it is eliminated */
944 if(i==0 && x1[0]>x2[0]-x1[0]) {last_x2=last_x=x1[0];}
945 integral+=(x1[i]-last_x2)*(last_y+s*((last_x2+x1[i])/2.0-last_x)); /*gap*/
946 integral+=frame_len*y[i];
947 integral2+=(x2[i]-last_x2)*(integral+last_integral)*0.5;
948 if(e!=NULL && i>0) {
949 value=last_y+s*(last_x2-last_x); /* value at previous frame end */
950 e[i-1]=value;
951 }
952 if(ie!=NULL) ie[i]=integral;
953 if(iie!=NULL) iie[i]=integral2;
954 last_x=x; last_x2=x2[i]; last_y=y[i]; last_integral=integral;
955 }
956 if(e!=NULL) {
957 value=last_y+s*(last_x2-last_x); /* Value for the last frame */
958 e[i-1]=value;
959 }
960
961 return(0);
962}

◆ powell()

int powell ( double * p,
double * delta,
int parNr,
double ftol,
int * iterNr,
double * fret,
double(* _fun )(int, double *, void *),
void * fundata,
int verbose )
extern

Powell function minimization routine.

Returns
Returns 0, if successful, 1 if required tolerance was not reached, 2 if initial guess does not give finite function value, 3 if final function value is NaN or infinite, and >3 in case of another error.
See also
simplex, tgo, bobyqa, nlopt1D
Parameters
pInitial guess and final set of parameters
deltaInitial changes for parameters, ==0 if fixed
parNrNr of parameters
ftolFractional tolerance (for WSS); 0<ftol<1
iterNrMax nr of iterations, and nr of required iters
fretFunction return value (WSS) at minimum
_funFunction to minimize (must return the WSS)
fundataPointer to data which is passed on to the function; NULL if not needed
verboseVerbose level; if zero, then nothing is printed into stdout or stderr

Definition at line 43 of file powell.c.

62 {
63 int pbIterNr;
64 int i, j, ibig, iterMax, fixed[MAX_PARAMETERS];
65 double xi[MAX_PARAMETERS][MAX_PARAMETERS]; /* Matrix for directions */
66 double pt[MAX_PARAMETERS], ptt[MAX_PARAMETERS], xit[MAX_PARAMETERS];
67 double del, fp, fptt, t;
68 double origp[MAX_PARAMETERS];
69 int ftol_reached=0;
70
71
72 if(verbose>0) printf("in powell(,,%d,%g,%d,,)\n", parNr, ftol, *iterNr);
73 if(verbose>1) {
74 printf("Initial parameter guesses and deltas:\n");
75 for(i=0; i<parNr; i++) printf(" %g %g\n", p[i], delta[i]);
76 }
77 *fret=nan("");
78 if(p==NULL) return(11);
79 if(delta==NULL) return(12);
80 if(parNr<1) return(21);
81 if(ftol<=0.0) return(22);
82 if(ftol>=1.0) return(23);
83 if((*iterNr)<1) return(24);
84
85 /* SetUp */
86 _powellFunc=_fun;
87 _powellFuncData=fundata;
88 iterMax=*iterNr; /* save the max nr of iterations */
89 _powell_ncom=parNr;
90 /* Function value at initial point */
91 _powell_func_calls=1;
92 *fret=(*_powellFunc)(parNr, p, _powellFuncData);
93 if(verbose>10) printf("initial point fret=%g\n", *fret);
94 if(!isfinite(*fret)) {
95 if(verbose>0) printf("in powell(): objf failed at initial point.\n");
96 *fret=nan(""); return(2);
97 }
98 /* Save the initial point (pt[] will be changed later) */
99 for(j=0; j<parNr; j++) origp[j]=pt[j]=p[j];
100 /* Check which parameters are fixed */
101 for(i=0; i<parNr; i++) if(fabs(delta[i])<1.0e-20) fixed[i]=1; else fixed[i]=0;
102
103 /* Initiate matrix for directions */
104 for(i=0; i<parNr; i++)
105 for(j=0; j<parNr; j++)
106 if(i==j) xi[i][j]=delta[i]; else xi[i][j]=0.0;
107
108 /* Iterate */
109 for(*iterNr=1; ; (*iterNr)++) {
110 if(verbose>2) printf(" iteration %d\n", *iterNr);
111 fp=*fret; ibig=0; del=0.0; /* largest function decrease */
112
113 /* In each iteration, loop over all directions in the set */
114 for(i=0; i<parNr; i++) {
115 if(fixed[i]) continue; /* do nothing with fixed parameters */
116 for(j=0; j<parNr; j++) if(fixed[j]) xit[j]=0.0; else xit[j]=xi[j][i];
117 fptt=*fret;
118 /* minimize along direction xit */
119 pbIterNr=POWELL_LINMIN_MAXIT;
120 _powell_linmin(p, xit, parNr, fret, &pbIterNr);
121 if(verbose>3) printf("iterNr in _powell_linmin() with p%d: %d\n",
122 i, pbIterNr);
123 if(fabs(fptt-(*fret))>del) {del=fabs(fptt-(*fret)); ibig=i;}
124 }
125 if(verbose>20) printf("fret=%g fp=%g\n", *fret, fp);
126
127 /* Check if done */
128#if(0)
129 if(2.0*fabs(fp-(*fret)) <= ftol*(fabs(fp)+fabs(*fret))) break;
130#else
131 if(2.0*fabs(fp-(*fret)) <= ftol*(fabs(fp)+fabs(*fret))) {
132 if(ftol_reached>0 || (*iterNr)>=iterMax) break; else ftol_reached++;
133 } else ftol_reached=0;
134#endif
135 if((*iterNr)>=iterMax) {
136 if(verbose>0) printf("max iterations nr exceeded in powell().\n");
137 break;
138 }
139 /* Construct the extrapolated point and the average direction moved */
140 for(j=0; j<parNr; j++) {
141 ptt[j]=2.0*p[j]-pt[j]; xit[j]=p[j]-pt[j];
142 pt[j]=p[j]; /* save the old starting point */
143 }
144 fptt=(*_powellFunc)(parNr, ptt, _powellFuncData); _powell_func_calls++;
145 if(fptt<fp) {
146 t=2.0*(fp-2.0*(*fret)+fptt)*_powell_sqr(fp-(*fret)-del)-del*_powell_sqr(fp-fptt);
147 if(t<0.0) {
148 pbIterNr=POWELL_LINMIN_MAXIT;
149 _powell_linmin(p, xit, parNr, fret, &pbIterNr);
150 if(verbose>3) printf("iterNr in _powell_linmin(): %d\n", pbIterNr);
151 for(j=0; j<parNr; j++) {
152 xi[j][ibig]=xi[j][parNr-1]; xi[j][parNr-1]=xit[j];}
153 }
154 }
155 } /* next iteration */
156 if(verbose>1) {
157 printf("iterNr := %d\n", *iterNr);
158 printf("nr of function calls := %d\n", _powell_func_calls);
159 }
160
161 if(isnan(*fret) || !isfinite(*fret)) {
162 if(verbose>10) printf("powell() fails and returns the initial point.\n");
163 if(verbose>11) {
164 if(isnan(*fret)) printf(" fret := NaN\n");
165 if(isfinite(*fret)) printf(" fret := overflow/underflow\n");
166 }
167 // if failed, then return initial guess
168 for(j=0; j<parNr; j++) p[j]=origp[j];
169 // and call function again so that any data saved there is correct
170 *fret=(*_powellFunc)(parNr, p, _powellFuncData);
171 return(3);
172 }
173 // and call function again so that any data saved there is correct
174 *fret=(*_powellFunc)(parNr, p, _powellFuncData);
175 if((*iterNr)>=iterMax) return(1);
176 if(verbose>0) printf("out of powell() in good order.\n");
177 return(0);
178}
#define MAX_PARAMETERS
Definition libtpcmodel.h:31
int POWELL_LINMIN_MAXIT
Definition powell.c:11

Referenced by bootstrap(), and tgo().

◆ qr()

int qr ( double ** A,
int m,
int n,
double * B,
double * X,
double * rnorm,
double * tau,
double * res,
double ** wws,
double * ws )
extern

Algorithm QR.

Solves a matrix form least square problem min||A x - b|| => A x =~ b (A is m*n matrix, m>=n) using the QR decomposition for overdetermined systems. Based on GNU Scientific Library, edited by Kaisa Liukko.

Instead of pointers for working space, NULL can be given to let this function to allocate and free the required memory.

Returns
Function returns 0 if successful and 1 in case of invalid problem dimensions or memory allocation error.
See also
qr_decomp, qr_solve, qrLH
Parameters
AOn entry, a[m][n] contains the m by n matrix A. On exit, a[][] contains the QR factorization.
mDimensions of matrix A are a[m][n].
nDimensions of matrix A are a[m][n].
BB[] is an m-size vector containing the right-hand side vector b.
XOn exit, x[] will contain the solution vector x (size of n).
rnormOn exit, rnorm (pointer to double) contains the squared Euclidean norm of the residual vector (R^2); enter NULL if not needed.
tauOn exit, tau[] will contain the householder coefficients (size of n); enter NULL, if not needed.
resAn m-size array of working space, res[]. On output contains residual b - Ax. Enter NULL to let qr() to handle it.
wwsm*n array of working space. Enter NULL to let qr() to handle it.
ws2m-array of working space. Enter NULL to let qr() to handle it.

Definition at line 346 of file qr.c.

371 {
372 int i;
373 double *qrRes, *qrTau, **qrWws, *qrWs, *chain;
374
375 /* Check the parameters and data */
376 if(m<=0 || n<=0 || A==NULL || B==NULL || X==NULL) return(1);
377 if(m<n) return(1);
378
379 /* Allocate memory for working space, if required */
380 if(tau!=NULL) qrTau=tau; else qrTau=(double*)calloc(n, sizeof(double));
381 if(res!=NULL) qrRes=res; else qrRes=(double*)calloc(m, sizeof(double));
382 if(wws!=NULL) {
383 qrWws=wws; chain=(double*)NULL;
384 } else {
385 qrWws=(double**)malloc(m * sizeof(double*));
386 chain=(double*)malloc(m*n * sizeof(double));
387 for(i=0; i<m; i++) qrWws[i]=chain + i*n;
388 }
389 if(ws!=NULL) qrWs=ws; else qrWs=(double*)calloc(2*m, sizeof(double));
390 if(qrTau==NULL || qrRes==NULL || qrWws==NULL || qrWs==NULL) return(1);
391
392 /* Form the householder decomposition and solve the least square problem */
393 if(qr_decomp(A, m, n, qrTau, qrWws, qrWs)) return(2);
394 if(qr_solve(A, m, n, qrTau, B, X, qrRes, rnorm, qrWws, qrWs)) return(3);
395
396 /* Free working space, if it was allocated here */
397 if(tau==NULL) free(qrTau);
398 if(res==NULL) free(qrRes);
399 if(wws==NULL) {free(qrWws); free(chain);}
400 if(ws==NULL) free(qrWs);
401 for(i=0; i<n; i++) if(isnan(X[i])) return(4);
402 return(0);
403} /* qr */
int qr_solve(double **QR, int M, int N, double *tau, double *b, double *x, double *residual, double *resNorm, double **cchain, double *chain)
Definition qr.c:492
int qr_decomp(double **a, int M, int N, double *tau, double **cchain, double *chain)
Definition qr.c:427

◆ qr_decomp()

int qr_decomp ( double ** a,
int M,
int N,
double * tau,
double ** cchain,
double * chain )
extern

Factorise a general M x N matrix A into A = Q R , where Q is orthogonal (M x M) and R is upper triangular (M x N).

Q is stored as a packed set of Householder vectors in the strict lower triangular part of the input matrix A and a set of coefficients in vector tau.

R is stored in the diagonal and upper triangle of the input matrix.

The full matrix for Q can be obtained as the product Q = Q_1 Q_2 .. Q_k and it's transform as the product Q^T = Q_k .. Q_2 Q_1 , where k = min(M,N) and Q_i = (I - tau_i * h_i * h_i^T) and where h_i is a Householder vector h_i = [1, A(i+1,i), A(i+2,i), ... , A(M,i)]. This storage scheme is the same as in LAPACK.

NOTICE! The calling program must take care that pointer tau is of size N or M, whichever is smaller.

Returns
Function returns 0 if ok.
See also
qr_solve
Parameters
acontains coefficient matrix A (m*n) as input and factorisation QR as output.
Mnr of rows in matrix A.
Nnr of columns in matrix A.
tauVector for householder coefficients, of length N or M, whichever is smaller.
cchainm*n matrix of working space.
chainm size array of working space.

Definition at line 427 of file qr.c.

440 {
441 //printf("qr_decomp()\n");
442 int i, m, n, MNmin;
443 double *subvector, **submatrix;
444
445 /* Local variables */
446 if(M<N) MNmin=M; else MNmin=N;
447 if(MNmin<1 || a==NULL || tau==NULL || cchain==NULL || chain==NULL) return(1);
448
449 subvector=chain;
450 submatrix=cchain;
451
452 for(i=0; i<MNmin; i++) {
453 //printf("i=%d (MNmin=%d)\n", i, MNmin);
454 /* Compute the Householder transformation to reduce the j-th column of the matrix A to
455 a multiple of the j-th unit vector. Householder vector h_i is saved in the lower triangular
456 part of the column and Householder coefficient tau_i in the vector tau. */
457 for(m=i; m<M; m++) subvector[m-i]=a[m][i];
458 tau[i] = householder_transform(subvector, M-i);
459 for(m=i; m<M; m++) a[m][i]=subvector[m-i];
460
461 /* Apply the transformation to the remaining columns to get upper triangular part of matrix R */
462 if(i+1 < N) {
463 for(m=i; m<M; m++)
464 for(n=i+1; n<N; n++)
465 submatrix[m-i][n-i-1]=a[m][n];
466 if(householder_hm(tau[i], subvector, submatrix, M-i, N-i)) return(2);
467 for(m=i; m<M; m++)
468 for(n=i+1; n<N; n++)
469 a[m][n]=submatrix[m-i][n-i-1];
470 }
471 }
472
473 return(0);
474}
int householder_hm(double tau, double *vector, double **matrix, int rowNr, int columnNr)
Definition hholder.c:68
double householder_transform(double *v, int N)
Definition hholder.c:23

Referenced by qr().

◆ qr_solve()

int qr_solve ( double ** QR,
int M,
int N,
double * tau,
double * b,
double * x,
double * residual,
double * resNorm,
double ** cchain,
double * chain )
extern

Find the least squares solution to the overdetermined system

A x = b

for m >= n using the QR factorisation A = Q R. qr_decomp() must be used prior to this function in order to form the QR factorisation of A. Solution is formed in the following order: QR x = b => R x = Q^T b => x = R^-1 (Q^T b)

NOTICE! The calling program must take care that pointers b, x and residual are of the right size.

Returns
Function returns 0 if ok.
Precondition
qr_decomp
Parameters
QRm*n matrix containing householder vectors of A.
Mnr of rows in matrix A.
Nnr of columns in matrix A.
tauvector containing householder coefficients tau; length is M or N, whichever is smaller.
bContains m-size vector b of A x = b.
xsolution vector x of length n.
residualresidual vector of length m.
resNormnorm^2 of the residual vector; enter NULL if not needed.
cchainm*n matrix of the working space.
chain2m length array of the working space.

Definition at line 492 of file qr.c.

513 {
514 //printf("qr_solve()\n");
515 if(QR==NULL || tau==NULL || b==NULL || x==NULL || residual==NULL) return(1);
516 if(cchain==NULL || chain==NULL) return(1);
517 if(M<1 || N<1) return(2);
518
519 int MNmin; if(M<N) MNmin=M; else MNmin=N;
520
521 int m, n;
522 double **Rmatrix=cchain;
523 double *h=chain;
524 double *w=chain+M;
525
526 /* Get matrix R from the upper triangular part of QR
527 First the rows N - M-1 are eliminated from R matrix*/
528 for(m=0; m<N; m++) for(n=0; n<N; n++) Rmatrix[m][n]=QR[m][n];
529 for(m=0; m<M; m++) residual[m]=b[m];
530
531 /* Compute b = Q^T b */
532 /* Form the product Q^T residual from householder vectors saved in the lower triangle of
533 QR matrix and householder coefficients saved in vector tau. */
534 for(int i=0; i<MNmin; i++) {
535 for(m=i; m<M; m++) h[m-i]=QR[m][i];
536 for(m=i; m<M; m++) w[m-i]=residual[m];
537 if(householder_hv(tau[i], M-i, h, w)) return(2);
538 for(m=i; m<M; m++) residual[m]=w[m-i];
539 }
540
541 /* Solve R x = b by computing x = R^-1 b */
542 for(n=0; n<N; n++) x[n]=residual[n];
543 /* back-substitution */
544 x[N-1]=x[N-1]/Rmatrix[N-1][N-1];
545 for(int i=N-2; i>=0; i--) {
546 for(int j=i+1; j<N; j++) x[i]-=Rmatrix[i][j]*x[j];
547 x[i]/=Rmatrix[i][i];
548 }
549
550 /* Compute residual = b - A x = Q (Q^T b - R x) */
551 for(n=0; n<N; n++) residual[n]=0.0;
552 /* Compute residual= Q*residual */
553 /* Form the product Q*residual from householder vectors saved in the lower triangle
554 of QR matrix and householder coefficients saved in vector tau. */
555 for(int i=MNmin-1; i>=0; i--) {
556 for(int m=i; m<M; m++) h[m-i]=QR[m][i];
557 for(int m=i; m<M; m++) w[m-i]=residual[m];
558 if(householder_hv(tau[i], M-i, h, w)) return(2);
559 for(int m=i; m<M; m++) residual[m]=w[m-i];
560 }
561
562 /* Compute norm^2 of the residual vector, if needed */
563 if(resNorm!=NULL)
564 for(m=0, *resNorm=0.0; m<M; m++) *resNorm +=residual[m]*residual[m];
565
566 return(0);
567}
int householder_hv(double tau, int size, double *v, double *w)
Definition hholder.c:107

Referenced by qr().

◆ qr_weight()

int qr_weight ( int N,
int M,
double ** A,
double * b,
double * weight,
double * ws )
extern

Algorithm for weighting the problem that is given to QR algorithm.

Square roots of weights are used because in QR the difference w*A-w*b is squared.

Returns
Algorithm returns zero if successful, otherwise <>0.
Parameters
NDimensions of matrix A are a[m][n].
MDimensions of matrix A are a[m][n]; size of vector B is m.
AMatrix a[m][n] for QR, contents will be weighted here.
bB[] is an m-size vector for QR, contents will be weighted here.
weightPointer to array of size m, which contains sample weights, used here to weight matrix A and vector b.
wsm-sized vector for working space; enter NULL to allocate locally.

Definition at line 576 of file qr.c.

590 {
591 int n, m;
592 double *w;
593
594 /* Check the arguments */
595 if(N<1 || M<1 || A==NULL || b==NULL || weight==NULL) return(1);
596
597 /* Allocate memory, if necessary */
598 if(ws==NULL) {
599 w=(double*)malloc(M*sizeof(double)); if(w==NULL) return(2);
600 } else {
601 w=ws;
602 }
603
604 /* Check that weights are not zero and get the square roots of them to w[]. */
605 for(m=0; m<M; m++) {
606 if(weight[m]<=1.0e-100) w[m]=1.0e-50;
607 else w[m]=sqrt(weight[m]);
608 }
609
610 /* Multiply rows of matrix A and elements of vector b with weights. */
611 for(m=0; m<M; m++) {
612 for(n=0; n<N; n++) A[m][n]*=w[m];
613 b[m]*=w[m];
614 }
615
616 if(ws==NULL) free(w);
617 return(0);
618}

◆ qrLH()

int qrLH ( const unsigned int m,
const unsigned int n,
double * a,
double * b,
double * x,
double * r2 )
extern

Solve over-determined least-squares problem A x ~ b using successive Householder rotations.

This routine is based on the text and Fortran code in C.L. Lawson and R.J. Hanson, Solving Least Squares Problems, Prentice-Hall, Englewood Cliffs, New Jersey, 1974, and Fortran code by R.L. Parker and P.B. Stark.

Returns
Returns 0 when successful, 1 if system is singular, and 2 in case of other errors, including that system is under-determined.
Parameters
mNumber of samples in matrix A and the length of vector b.
nNumber of parameters in matrix A and the length of vector x. The n must be smaller or equal to m.
aPointer to matrix A; matrix must be given as an n*m array, containing n consecutive m-length vectors. Contents of A are modified in this routine.
bPointer to vector b of length n. Contents of b are modified in this routine.
xPointer to the result vector x of length n.
r2Pointer to a double value, in where the sum of squared residuals is written.

Definition at line 633 of file qr.c.

650 {
651 /* Check the input */
652 if(a==NULL || b==NULL || x==NULL || r2==NULL) return(2);
653 if(n<1 || m<n) {*r2=nan(""); return(2);}
654
655 /* Initiate output to zeroes, in case of exit because of singularity */
656 for(unsigned int ni=0; ni<n; ni++) x[ni]=0.0;
657 *r2=0.0;
658
659 /* Rotates matrix A into upper triangular form */
660 for(unsigned int ni=0; ni<n; ni++) {
661 /* Find constants for rotation and diagonal entry */
662 double sq=0.0;
663 for(unsigned int mi=ni; mi<m; mi++) sq+=a[mi + ni*m]*a[mi + ni*m];
664 if(sq==0.0) return(1);
665 double qv1=-copysign(sqrt(sq), a[ni + ni*m]);
666 double u1=a[ni + ni*m] - qv1;
667 a[ni + ni*m]=qv1;
668 unsigned int ni1=ni+1;
669 /* Rotate the remaining columns of sub-matrix. */
670 for(unsigned int nj=ni1; nj<n; nj++) {
671 double dot=u1*a[ni + nj*m];
672 for(unsigned int mi=ni1; mi<m; mi++)
673 dot+=a[mi + nj*m] * a[mi + ni*m];
674 double c=dot/fabs(qv1*u1);
675 for(unsigned int mi=ni1; mi<m; mi++)
676 a[mi + nj*m]-=c*a[mi + ni*m];
677 a[ni + nj*m]-=c*u1;
678 }
679 /* Rotate vector B */
680 double dot=u1*b[ni];
681 for(unsigned int mi=ni1; mi<m; mi++)
682 dot+=b[mi]*a[mi + ni*m];
683 double c=dot/fabs(qv1*u1);
684 b[ni]-=c*u1;
685 for(unsigned int mi=ni1; mi<m; mi++)
686 b[mi]-=c*a[mi + ni*m];
687 } // end of rotation loop
688
689 /* Solve triangular system by back-substitution. */
690 for(unsigned int ni=0; ni<n; ni++) {
691 int k=n-ni-1;
692 double s=b[k];
693 for(unsigned int nj=k+1; nj<n; nj++)
694 s-=a[k + nj*m] * x[nj];
695 if(a[k + k*m]==0.0) return(1);
696 x[k]=s/a[k + k*m];
697 }
698
699 /* Calculate the sum of squared residuals. */
700 *r2=0.0;
701 for(unsigned int mi=n; mi<m; mi++)
702 *r2 += b[mi]*b[mi];
703
704 return(0);
705}

Referenced by bvls().

◆ qrLSQ()

int qrLSQ ( double ** mat,
double * rhs,
double * sol,
const unsigned int rows,
const unsigned int cols,
double * r2 )
extern

QR least-squares solving routine.

Solves a matrix form least square problem min||A x - b|| => A x =~ b (A is m*n matrix, m>=n) using the QR decomposition for overdetermined systems

Author
: Michael Mazack License: Public Domain. Redistribution and modification without restriction is granted. If you find this code helpful, please let the author know (https://mazack.org). Small editions by Vesa Oikonen when added to tpcclib.
See also
nnls, qr
Todo
Check that modification in one subroutine is ok, and add possibility to provide working space for the main and sub-functions.
Returns
Returns 0 if ok.
Parameters
matPointer to the row-major matrix (2D array), A[rows][cols]; not modified.
rhsVector b[rows]; modified to contain the computed (fitted) b[], that is, matrix-vector product A*x.
solSolution vector x[cols]; solution x corresponds to the solution of both the modified and original systems A and B.
rowsNumber of rows (samples) in matrix A and length of vector B.
colsNumber of cols (parameters) in matrix A and length of vector X.
r2Pointer to value where R^2, the difference between original and computed right hand side (b); enter NULL if not needed.

Definition at line 54 of file qr.c.

70 {
71 if(rows<1 || cols<1) return(1);
72 if(mat==NULL || rhs==NULL || sol==NULL) return(2);
73
74 unsigned int i, j, max_loc;
75 unsigned int *p=NULL;
76 double *buf=NULL, *ptr, *v=NULL, *orig_b=NULL, **A=NULL;
77
78 /* Allocate memory for index vector and Householder transform vector */
79 /* and original data matrix and vector. */
80 p=malloc(sizeof(unsigned int)*cols);
81 A=malloc(sizeof(double*)*rows);
82 buf=malloc(sizeof(double)*(rows*cols+rows+rows));
83 if(p==NULL || A==NULL || buf==NULL) {
84 free(p); free(A); free(buf);
85 return(3);
86 }
87 ptr=buf;
88 for(i=0; i<rows; i++) {A[i]=ptr; ptr+=cols;}
89 v=ptr; ptr+=rows; orig_b=ptr;
90 /* copy the original data */
91 for(i=0; i<rows; i++) {
92 orig_b[i]=rhs[i];
93 for(j=0; j<cols; j++) A[i][j]=mat[i][j];
94 }
95
96 /* Initial permutation vector. */
97 for(i=0; i<cols; i++) p[i]=i;
98
99 /* Apply rotators to make R and Q'*b */
100 for(i=0; i<cols; i++) {
101 if(qr_get_next_col(A, rows, cols, i, p, &max_loc)==0)
102 qr_swap_cols(p, i, max_loc);
103 qr_householder(A, rows, cols, i, p[i], v);
104 qr_apply_householder(A, rhs, rows, cols, v, i, p);
105 }
106
107 /* Back solve Rx = Q'*b */
108 qr_back_solve(A, rhs, rows, cols, sol, p);
109
110 /* Compute fitted b[] (matrix-vector product A*x) using non-modified A */
111 for(i=0; i<rows; i++) {
112 rhs[i]=0.0;
113 for(j=0; j<cols; j++) rhs[i]+=mat[i][j]*sol[j];
114 }
115
116 /* Compute R^2, if requested */
117 if(r2!=NULL) {
118 double ss=0, d;
119 for(i=0; i<rows; i++) {
120 d=orig_b[i]-rhs[i];
121 ss+=d*d;
122 }
123 *r2=ss;
124 }
125
126 /* Collect garbage. */
127 free(p); free(A); free(buf);
128 return(0);
129}

◆ quadratic()

int quadratic ( double a,
double b,
double c,
double * m1,
double * m2 )
extern

Finds the real roots of a*x^2 + b*x + c = 0

Returns
Returns the nr of roots, and the roots in m1 and m2.
Parameters
aInput A
bInput B
cInput C
m1Output: Root 1
m2Output: Root 2

Definition at line 490 of file llsqwt.c.

501 {
502 double discriminant, r, r1, r2, sgnb, temp;
503
504 if(a==0) {if(b==0) return(0); else {*m1=*m2=-c/b; return(1);}}
505 discriminant=b*b - 4*a*c;
506 if(discriminant>0) {
507 if(b==0) {r=fabs(0.5*sqrt(discriminant)/a); *m1=-r; *m2=r;}
508 else {
509 sgnb=(b>0 ? 1:-1); temp=-0.5*(b + sgnb*sqrt(discriminant));
510 r1=temp/a; r2=c/temp; if(r1<r2) {*m1=r1; *m2=r2;} else {*m1=r2; *m2=r1;}
511 }
512 return(2);
513 } else if(discriminant==0) {
514 *m1=-0.5*b/a; *m2=-0.5*b/a;
515 return(2);
516 } else {
517 return(0);
518 }
519}

Referenced by llsqperp().

◆ rand_range()

int rand_range ( int nr,
double * d,
double low,
double up,
int type )
extern

Fills the double array with random numbers between specified limits. Set seed for random number generator before calling this routine, for example with srand(time(NULL));

Returns
Returns 0 when successful, otherwise <> 0.
Parameters
nrNr of values in double array
dPointer to allocated double array
lowLower limit for random values
upUpper limit for random values
typeDistribution: 0=even, 1=square-root transformation

Definition at line 159 of file gaussdev.c.

170 {
171 int i;
172 double dif, v, stl, stu;
173
174 if(nr<1) return 0;
175 if(d==NULL || type<0 || type>1) return 1;
176
177 dif=up-low; if(dif<0.0) return 2;
178 if(dif==0.0) {
179 for(i=0; i<nr; i++) d[i]=low;
180 return 0;
181 }
182
183 if(type==0) {
184 for(i=0; i<nr; i++) d[i] = drand()*dif + low;
185 } else if(type==1) {
186 stl=copysign(sqrt(fabs(low)),low); if(!isnormal(stl)) stl=0.0;
187 stu=copysign(sqrt(fabs(up)), up); if(!isnormal(stu)) stu=0.0;
188 dif=stu-stl;
189 for(i=0; i<nr; i++) {v=drand()*dif+stl; d[i]=copysign(v*v, v);}
190 }
191
192 return 0;
193}

◆ random_shuffle()

void random_shuffle ( int * array,
int n )
extern

Random shuffle: arrange the n elements of array in random order. Only effective if N is much smaller than RAND_MAX.

Definition at line 13 of file shuffle.c.

14{
15 if(n<=1 || array==NULL) return;
16 int i, j, tmp;
17 for(i=0; i<n-1; i++) {
18 j=i+rand()/(RAND_MAX/(n-i)+1);
19 tmp=array[j]; array[j]=array[i]; array[i]=tmp;
20 }
21}

Referenced by randperm().

◆ randperm()

void randperm ( int * array,
int n,
int a )
extern

Random permutation: given (allocated) array of length n is filled with random permutation of numbers in the range [a:n+a-1]; that is, each number once in random order.

Definition at line 29 of file shuffle.c.

30{
31 if(n<1 || array==NULL) return;
32 int i;
33 for(i=0; i<n; i++) array[i]=i+a;
34 random_shuffle(array, n);
35}
void random_shuffle(int *array, int n)
Definition shuffle.c:13

◆ regr_line()

int regr_line ( double * x,
double * y,
int n,
double * m,
double * c )
extern

Calculates regression line slope (m) and y axis intercept.

Data (x and y data) may contain NaN's.

See also
highest_slope, pearson, imgsegmPearson
Returns
Returns 0 if ok.
Parameters
xAn array of x axis values.
yAn array of y axis values.
nThe number of values in x and y arrays.
mPointer where calculated slope is written.
cPointer where calculated y axis intercept is written.

Definition at line 387 of file pearson.c.

398 {
399 double xsum=0.0, ysum=0.0, x2sum=0.0, xysum=0.0, delta;
400 int i, nn=0;
401
402 /* Check the data */
403 if(x==NULL || y==NULL) return(1);
404 if(n<2) return(2);
405
406 /* Compute */
407 for(i=0, nn=0; i<n; i++) {
408 if(isnan(x[i]) || isnan(y[i])) continue;
409 xsum+=x[i]; ysum+=y[i]; x2sum+=x[i]*x[i]; xysum+=x[i]*y[i]; nn++;
410 }
411 if(nn<2) return(2);
412 delta=(double)nn*x2sum - xsum*xsum; if(delta==0.0) return(3);
413 *m=((double)nn*xysum - xsum*ysum)/delta;
414 *c=(x2sum*ysum - xsum*xysum)/delta;
415 return(0);
416}

Referenced by highest_slope(), and highest_slope_after().

◆ residuals()

int residuals ( double * d1,
double * d2,
int Nr,
int * Rnr,
int * Nminus,
int * Nplus )
extern

Residuals function calculates the nr of runs (a sequence of consecutive positive or negative residuals) and nr of negative and positive residuals for two data arrays.

Returns
Returns 0, if ok.
Parameters
d1double array with data points
d2double array with data points
Nrnumber of data points in both arrays
Rnrnr of runs
Nminusnr of negative residuals
Nplusnr of positive residuals

Definition at line 56 of file runs_test.c.

69 {
70 if(d1==NULL || d2==NULL || Nr<1 || Rnr==NULL || Nminus==NULL || Nplus==NULL) return(1);
71
72 int i, *sign;
73 double *res;
74
75 /* Allocate memory for residuals */
76 res=(double*)malloc((Nr)*sizeof(double));
77 sign=(int*)malloc((Nr)*sizeof(int));
78 if(res==NULL || sign==NULL) return(2);
79
80 /* get residuals into res, nr of negative residuals in Nminus */
81 /* nr of positive residuals into Nplus */
82 /* Sign of each residual is saved into sign */
83 /* and if sign is different from the last residual, increase runs nr */
84 *Nminus=0; *Nplus=0; *Rnr=1;
85 for(i=0; i<Nr; i++) {
86 res[i]=d1[i]-d2[i];
87 if(res[i]<0.0) {
88 *Nminus+=1; sign[i]=-1;
89 } else {
90 *Nplus+=1; sign[i]=1;
91 }
92 if(i>0) if(sign[i]!=sign[i-1]) *Rnr+=1;
93 }
94 free(res); free(sign);
95 return(0);
96}

Referenced by runs_test().

◆ runs_test()

int runs_test ( double * data1,
double * data2,
int N,
double alpha,
double * p )
extern

Runs_test function tests if residuals of two data arrays are independent.

Returns
Returns 0, if residuals are independent, -1, if residuals are dependent and >0 in case of an error.
Parameters
data1double array with data points
data2double array with data points
Nnumber of data points in both arrays
alphasignificance level percentage (set to negative value to use default 5%)
pcalculated probability p; enter NULL if not needed

Definition at line 12 of file runs_test.c.

23 {
24 int R=1, Nneg=0, Npos=0, NN;
25 double expect, var, Z, pvalue=0.0, a, b;
26 if(alpha<=0.0) alpha=5.0;
27
28 residuals(data1, data2, N, &R, &Nneg, &Npos);
29 //printf("* R=%d Nneg=%d Npos=%d\n", R, Nneg, Npos);
30
31 /* Expectation value for R. See Cobelli p. 262*/
32 NN=2*Nneg*Npos;
33 if(NN<1) {if(p!=NULL) *p=pvalue; return -1;}
34 expect=(double)NN/(double)N + 1.0;
35
36 /* Variance for R. See Cobelli Eq 8.6.4 p. 262*/
37 a=(double)NN*(double)(NN-N); b=(double)(N-1)*(double)N*(double)N;
38 var=a/b;
39
40 /* R->Z that tends to _standardized_ normal distribution */
41 Z=((double)R-expect)/sqrt(var); // printf(" Z=%g\n", Z);
42 /* Get propability of getting value Z from normal distribution*/
43 pvalue=ndtr(Z); if(p!=NULL) *p=pvalue;
44
45 if (pvalue<0.01*alpha) return -1;
46 else return 0;
47}
double ndtr(double a)
Definition normaldistr.c:17
int residuals(double *d1, double *d2, int Nr, int *Rnr, int *Nminus, int *Nplus)
Definition runs_test.c:56

◆ simC1()

int simC1 ( double * t,
double * ca,
int nr,
double k1,
double k2,
double * ct )
extern

Simulates tissue TAC using 1 tissue compartment model plasma TAC, at plasma TAC times.

Memory for ct must be allocated in the calling program.

The units of rate constants must be related to the time unit; 1/min and min, or 1/sec and sec.

Returns
Function returns 0 when successful, else a value >= 1.
See also
simC3s, simC3p, simC3vs, simC3vp, simC2l, simC2vl, simC3vpKLoss, simRTCM, simSRTM, simTRTM, simHuangmet, simTPCMOD0009c, simMBF, simC3DIvs, simC4DIvp, simC4DIvs, simDispersion, simOxygen
Parameters
tArray of time values
caArray of arterial activities
nrNumber of values in TACs
k1Rate constant of the model
k2Rate constant of the model
ctPointer for TAC array to be simulated; must be allocated

Definition at line 1317 of file simulate.c.

1330 {
1331 int i;
1332 double dt2;
1333 double cai, ca_last, t_last;
1334 double ct1, ct1_last;
1335 double ct1i, ct1i_last;
1336
1337
1338 /* Check for data */
1339 if(nr<2) return 1;
1340 if(ct==NULL) return 2;
1341
1342 /* Check actual parameter number */
1343 if(k1<0.0) return 3;
1344
1345 /* Calculate curves */
1346 t_last=0.0; if(t[0]<t_last) t_last=t[0];
1347 cai=ca_last=0.0;
1348 ct1_last=ct1i_last=0.0;
1349 ct1=ct1i=0.0;
1350 for(i=0; i<nr; i++) {
1351 /* delta time / 2 */
1352 dt2=0.5*(t[i]-t_last);
1353 /* calculate values */
1354 if(dt2<0.0) {
1355 return 5;
1356 } else if(dt2>0.0) {
1357 /* arterial integral */
1358 cai+=(ca[i]+ca_last)*dt2;
1359 /* tissue compartment and its integral */
1360 ct1 = (k1*cai - k2*(ct1i_last+dt2*ct1_last)) / (1.0 + dt2*k2);
1361 ct1i = ct1i_last + dt2*(ct1_last+ct1);
1362 }
1363 /* copy values to argument arrays; set very small values to zero */
1364 ct[i]=ct1; if(fabs(ct[i])<1.0e-12) ct[i]=0.0;
1365 /* prepare to the next loop */
1366 t_last=t[i]; ca_last=ca[i];
1367 ct1_last=ct1; ct1i_last=ct1i;
1368 }
1369
1370 return 0;
1371}

Referenced by bf_srtm(), bfIrr2TCM(), bfRadiowater(), and simDispersion().

◆ simC2l()

int simC2l ( double * t,
double * ca,
int nr,
double k1,
double k2,
double k3,
double kLoss,
double * ct,
double * cta,
double * ctb )
extern

Simulates tissue TAC using 2 tissue compartment model (in series) and plasma TAC, at plasma TAC times. In contrary to the common model, kLoss represents a direct loss rate from the 2nd tissue compartment to venous plasma.

Memory for ct must be allocated in the calling program. To retrieve the separate tissue compartment TACs, pointer to allocated memory for cta and ctb can be given; if compartmental TACs are not required, NULL pointer can be given instead.

The units of rate constants must be related to the time unit; 1/min and min, or 1/sec and sec.

Returns
Function returns 0 when successful, else a value >= 1.
See also
simC3s, simC3p, simC3vs, simC3vp, simC2vl, simC3vpKLoss, simRTCM, simSRTM, simTRTM, simHuangmet, simTPCMOD0009c, simMBF, simC1, simC3DIvs, simC4DIvp, simC4DIvs, simDispersion, simOxygen
Parameters
tArray of time values
caArray of arterial activities
nrNumber of values in TACs
k1Rate constant of the model
k2Rate constant of the model
k3Rate constant of the model
kLossRate constant of the model
ctPointer for TAC array to be simulated; must be allocated
ctaPointer for 1st compartment TAC to be simulated, or NULL
ctbPointer for 2nd compartment TAC to be simulated, or NULL

Definition at line 500 of file simulate.c.

521 {
522 int i;
523 double b, c, dt2;
524 double cai, ca_last, t_last;
525 double ct1, ct1_last, ct2, ct2_last;
526 double ct1i, ct1i_last, ct2i, ct2i_last;
527
528
529 /* Check for data */
530 if(nr<2) return 1;
531 if(ct==NULL) return 2;
532
533 /* Check actual parameter number */
534 if(k1<0.0) return 3;
535
536 /* Calculate curves */
537 t_last=0.0; if(t[0]<t_last) t_last=t[0];
538 cai=ca_last=0.0;
539 ct1_last=ct2_last=ct1i_last=ct2i_last=ct1=ct2=ct1i=ct2i=0.0;
540 for(i=0; i<nr; i++) {
541 /* delta time / 2 */
542 dt2=0.5*(t[i]-t_last);
543 /* calculate values */
544 if(dt2<0.0) {
545 return 5;
546 } else if(dt2>0.0) {
547 /* arterial integral */
548 cai+=(ca[i]+ca_last)*dt2;
549 /* partial results */
550 b=ct1i_last+dt2*ct1_last;
551 c=ct2i_last+dt2*ct2_last;
552 /* 1st tissue compartment and its integral */
553 ct1 = (k1*cai - (k2+k3)*b) / (1.0 + (k2+k3)*dt2 );
554 ct1i = ct1i_last + dt2*(ct1_last+ct1);
555 /* 2nd tissue compartment and its integral */
556 ct2 = (k3*ct1i - kLoss*c) / (1.0 + kLoss*dt2);
557 ct2i = ct2i_last + dt2*(ct2_last+ct2);
558 }
559 /* copy values to argument arrays; set very small values to zero */
560 ct[i]=ct1+ct2; if(fabs(ct[i])<1.0e-12) ct[i]=0.0;
561 if(cta!=NULL) {cta[i]=ct1; if(fabs(cta[i])<1.0e-12) cta[i]=0.0;}
562 if(ctb!=NULL) {ctb[i]=ct2; if(fabs(ctb[i])<1.0e-12) ctb[i]=0.0;}
563 /* prepare to the next loop */
564 t_last=t[i]; ca_last=ca[i];
565 ct1_last=ct1; ct1i_last=ct1i;
566 ct2_last=ct2; ct2i_last=ct2i;
567 }
568
569 return 0;
570}

◆ simC2vl()

int simC2vl ( double * t,
double * ca,
double * cb,
int nr,
double k1,
double k2,
double k3,
double kL,
double f,
double vb,
double fa,
double * cpet,
double * cta,
double * ctb,
double * ctab,
double * ctvb )
extern

Simulates tissue TAC using 2 tissue compartment model and plasma TAC, at plasma TAC times, considering also arterial and venous vasculature. The efflux from 2nd tissue compartment (at rate kL) goes directly to blood.

Memory for cpet must be allocated in the calling program. To retrieve the separate tissue compartment TACs, pointer to allocated memory for cta, ctb, ctab and/or ctvb can be given; if compartmental TACs are not required, NULL pointer can be given instead.

The units of rate constants must be related to the time unit; 1/min and min, or 1/sec and sec.

If blood flow is set to 0, function assumes that f>>k1, and Cvb=Cab.,

Returns
Function returns 0 when successful, else a value >= 1.
See also
simC3s, simC3p, simC3vs, simC3vp, simC2l, simC3vpKLoss, simRTCM, simSRTM, simTRTM, simHuangmet, simTPCMOD0009c, simMBF, simC1, simC3DIvs, simC4DIvp, simC4DIvs, simDispersion, simOxygen
Parameters
tArray of time values
caArray of arterial plasma activities
cbArray of arterial blood activities
nrNumber of values in TACs
k1Rate constant of the model
k2Rate constant of the model
k3Rate constant of the model
kLRate constant of the model
fBlood flow; if 0, function assumes that f>>k1, and Cvb=Cab.
vbVascular volume fraction
faArterial fraction of vascular volume
cpetPointer for TAC array to be simulated; must be allocated
ctaPointer for 1st compartment TAC to be simulated, or NULL
ctbPointer for 2nd compartment TAC to be simulated, or NULL
ctabPointer for arterial TAC in tissue, or NULL
ctvbPointer for venous TAC in tissue, or NULL

Definition at line 592 of file simulate.c.

625 {
626 int i;
627 double dt2, b, c, va, vv;
628 double cai, ca_last, t_last, dct, cvb;
629 double ct1, ct1_last, ct2, ct2_last;
630 double ct1i, ct1i_last, ct2i, ct2i_last;
631
632
633 /* Check for data */
634 if(nr<2) return 1;
635 if(cpet==NULL) return 2;
636
637 /* Check parameters */
638 if(k1<0.0) return 3;
639 if(vb<0.0 || vb>=1.0) return 4;
640 if(fa<=0.0 || fa>1.0) return 5;
641 va=fa*vb; vv=(1.0-fa)*vb;
642
643 /* Calculate curves */
644 t_last=0.0; if(t[0]<t_last) t_last=t[0];
645 cai=ca_last=0.0;
646 ct1_last=ct2_last=ct1i_last=ct2i_last=ct1=ct2=ct1i=ct2i=0.0;
647 for(i=0; i<nr; i++) {
648 /* delta time / 2 */
649 dt2=0.5*(t[i]-t_last);
650 /* calculate values */
651 if(dt2<0.0) {
652 return 5;
653 } else if(dt2>0.0) {
654 /* arterial integral */
655 cai+=(ca[i]+ca_last)*dt2;
656 /* Calculate partial results */
657 b=ct1i_last+dt2*ct1_last;
658 c=ct2i_last+dt2*ct2_last;
659 /* 1st tissue compartment and its integral */
660 ct1 = (k1*cai - (k2+k3)*b) / (1.0 + (k2+k3)*dt2 );
661 ct1i = ct1i_last + dt2*(ct1_last+ct1);
662 /* 2nd tissue compartment and its integral */
663 ct2 = (k3*ct1i - kL*c) / (1.0 + kL*dt2);
664 ct2i = ct2i_last + dt2*(ct2_last+ct2);
665 }
666 /* Venous curve */
667 if(f>0.) {dct = k1*ca[i] - k2*ct1 - kL*ct2; cvb = cb[i] - dct/f;}
668 else cvb=cb[i];
669 /* copy values to argument arrays; set very small values to zero */
670 cpet[i]= va*cb[i] + vv*cvb + (1.0-vb)*(ct1+ct2);
671 if(fabs(cpet[i])<1.0e-12) cpet[i]=0.0;
672 if(cta!=NULL) {cta[i]=(1.0-vb)*ct1; if(fabs(cta[i])<1.0e-12) cta[i]=0.0;}
673 if(ctb!=NULL) {ctb[i]=(1.0-vb)*ct2; if(fabs(ctb[i])<1.0e-12) ctb[i]=0.0;}
674 if(ctab!=NULL) {ctab[i]=va*cb[i]; if(fabs(ctab[i])<1.0e-12) ctab[i]=0.0;}
675 if(ctvb!=NULL) {ctvb[i]=vv*cvb; if(fabs(ctvb[i])<1.0e-12) ctvb[i]=0.0;}
676 /* prepare to the next loop */
677 t_last=t[i]; ca_last=ca[i];
678 ct1_last=ct1; ct1i_last=ct1i;
679 ct2_last=ct2; ct2i_last=ct2i;
680 }
681
682 return 0;
683}

◆ simC3DIvs()

int simC3DIvs ( double * t,
double * ca1,
double * ca2,
double * cb,
int nr,
double k1,
double k2,
double k3,
double k4,
double k5,
double k6,
double k1b,
double k2b,
double f,
double vb,
double fa,
double * scpet,
double * sct1,
double * sct2,
double * sct3,
double * sct1b,
double * sctab,
double * sctvb )
extern

Simulates tissue TAC using dual-input tissue compartment model (1-3 compartments in series for tracer1, and 1 compartment for tracer2) at plasma TAC times, considering also contribution of arterial and venous vasculature, but no exchange between compartments for tracer1 and tracer2. The units of rate constants must be related to the time unit; 1/min and min, or 1/sec and sec. If blood flow is set to 0, function assumes that f>>k1, and Cvb=Cab.

Returns
Function returns 0 when successful, else a value >= 1.
See also
simC3s, simC3p, simC3vs, simC3vp, simC2l, simC2vl, simC3vpKLoss, simRTCM, simSRTM, simTRTM, simHuangmet, simTPCMOD0009c, simMBF, simC1, simC4DIvp, simC4DIvs, simDispersion, simOxygen
Parameters
tArray of time values
ca1Array of arterial plasma activities of tracer1
ca2Array of arterial plasma activities of tracer2
cbArray of arterial blood activities
nrNumber of values in TACs
k1Rate constant of the model for tracer1 (from plasma to C1)
k2Rate constant of the model for tracer1 (from C1 to plasma)
k3Rate constant of the model for tracer1 (from C1 to C2)
k4Rate constant of the model for tracer1 (from C2 to C1)
k5Rate constant of the model for tracer1 (from C2 to C3)
k6Rate constant of the model for tracer1 (from C3 to C2)
k1bRate constant of the model for tracer2 (from plasma to C4)
k2bRate constant of the model for tracer2 (from C4 to plasma)
fBlood flow; if 0, function assumes that f>>k1, and Cvb=Cab.
vbVascular volume fraction
faArterial fraction of vascular volume
scpetPointer for TAC array to be simulated; must be allocated
sct1Pointer for 1st tracer1 compartment TAC, or NULL if not needed
sct2Pointer for 2nd tracer1 compartment TAC, or NULL if not needed
sct3Pointer for 3rd tracer1 compartment TAC, or NULL if not needed
sct1bPointer for 1st tracer2 compartment TAC, or NULL if not needed
sctabPointer for arterial TAC in tissue, or NULL if not needed
sctvbPointer for venous TAC in tissue, or NULL if not needed

Definition at line 1387 of file simulate.c.

1434 {
1435 int i;
1436 double b, c, d, e, w, z, dt2, va, vv;
1437 double ca1i, ca1_last, ca2i, ca2_last, t_last, dct, cvb;
1438 double ct1, ct1_last, ct2, ct2_last, ct3, ct3_last;
1439 double ct1i, ct1i_last, ct2i, ct2i_last, ct3i, ct3i_last;
1440 double ct1b, ct1b_last, ct1bi, ct1bi_last;
1441
1442
1443 /* Check for data */
1444 if(nr<2) return 1;
1445 if(scpet==NULL) return 2;
1446
1447 /* Check parameters */
1448 if(k1<0.0) return 3;
1449 if(vb<0.0 || vb>=1.0) return 4;
1450 if(fa<=0.0 || fa>1.0) return 5;
1451 va=fa*vb; vv=(1.0-fa)*vb;
1452
1453 /* Calculate curves */
1454 t_last=0.0; if(t[0]<t_last) t_last=t[0];
1455 ca1i=ca1_last=ca2i=ca2_last=0.0;
1456 ct1_last=ct2_last=ct3_last=ct1i_last=ct2i_last=ct3i_last=0.0;
1457 ct1b_last=ct1bi_last=0.0;
1458 ct1=ct2=ct3=ct1b=ct1i=ct2i=ct3i=ct1bi=0.0;
1459 for(i=0; i<nr; i++) {
1460 /* delta time / 2 */
1461 dt2=0.5*(t[i]-t_last);
1462 /* calculate values */
1463 if(dt2<0.0) {
1464 return 5;
1465 } else if(dt2>0.0) {
1466 /* arterial integrals */
1467 ca1i+=(ca1[i]+ca1_last)*dt2;
1468 ca2i+=(ca2[i]+ca2_last)*dt2;
1469 /* partial results */
1470 b=ct1i_last+dt2*ct1_last;
1471 c=ct2i_last+dt2*ct2_last;
1472 d=ct3i_last+dt2*ct3_last;
1473 e=ct1bi_last+dt2*ct1b_last;
1474 w=k4 + k5 - (k5*k6*dt2)/(1.0+k6*dt2);
1475 z=1.0+w*dt2;
1476 /* 1st tissue compartment and its integral */
1477 ct1 = (
1478 + k1*z*ca1i + (k3*k4*dt2 - (k2+k3)*z)*b
1479 + k4*c + k4*k6*dt2*d/(1.0+k6*dt2)
1480 ) / ( z*(1.0 + dt2*(k2+k3)) - k3*k4*dt2*dt2 );
1481 ct1i = ct1i_last + dt2*(ct1_last+ct1);
1482 ct1b = (k1b*ca2i - k2b*e) / (1.0 + dt2*k2b);
1483 ct1bi = ct1bi_last + dt2*(ct1b_last+ct1b);
1484 /* 2nd tissue compartment and its integral */
1485 ct2 = (k3*ct1i - w*c + k6*d/(1.0+k6*dt2)) / z;
1486 ct2i = ct2i_last + dt2*(ct2_last+ct2);
1487 /* 3rd tissue compartment and its integral */
1488 ct3 = (k5*ct2i - k6*d) / (1.0 + k6*dt2);
1489 ct3i = ct3i_last + dt2*(ct3_last+ct3);
1490 }
1491 /* Venous curve */
1492 if(f>0.) {
1493 dct = k1*ca1[i] - k2*ct1 + k1b*ca2[i] - k2b*ct1b;
1494 cvb = cb[i] - dct/f;
1495 } else cvb=cb[i];
1496 /* copy values to argument arrays; set very small values to zero */
1497 scpet[i]= va*cb[i] + vv*cvb + (1.0-vb)*(ct1+ct2+ct3+ct1b);
1498 if(fabs(scpet[i])<1.0e-12) scpet[i]=0.0;
1499 if(sct1!=NULL) {sct1[i]=(1.0-vb)*ct1; if(fabs(sct1[i])<1.0e-12) sct1[i]=0.0;}
1500 if(sct2!=NULL) {sct2[i]=(1.0-vb)*ct2; if(fabs(sct2[i])<1.0e-12) sct2[i]=0.0;}
1501 if(sct3!=NULL) {sct3[i]=(1.0-vb)*ct3; if(fabs(sct3[i])<1.0e-12) sct3[i]=0.0;}
1502 if(sct1b!=NULL) {
1503 sct1b[i]=(1.0-vb)*ct1b; if(fabs(sct1b[i])<1.0e-12) sct1b[i]=0.0;}
1504 if(sctab!=NULL) {sctab[i]=va*cb[i]; if(fabs(sctab[i])<1.0e-12) sctab[i]=0.0;}
1505 if(sctvb!=NULL) {sctvb[i]=vv*cvb; if(fabs(sctvb[i])<1.0e-12) sctvb[i]=0.0;}
1506 /* prepare to the next loop */
1507 t_last=t[i]; ca1_last=ca1[i]; ca2_last=ca2[i];
1508 ct1_last=ct1; ct1i_last=ct1i;
1509 ct2_last=ct2; ct2i_last=ct2i;
1510 ct3_last=ct3; ct3i_last=ct3i;
1511 ct1b_last=ct1b; ct1bi_last=ct1bi;
1512 }
1513
1514 return 0;
1515}

◆ simC3p()

int simC3p ( double * t,
double * ca,
int nr,
double k1,
double k2,
double k3,
double k4,
double k5,
double k6,
double * ct,
double * cta,
double * ctb,
double * ctc )
extern

Simulates tissue TAC using 1-3 tissue compartment model (2nd and 3rd compartments in parallel) and plasma TAC, at plasma TAC times.

Memory for ct must be allocated in the calling program. To retrieve the separate tissue compartment TACs, pointer to allocated memory for cta, ctb and/or ctc can be given; if compartmental TACs are not required, NULL pointer can be given instead.

The units of rate constants must be related to the time unit; 1/min and min, or 1/sec and sec.

Returns
Function returns 0 when successful, else a value >= 1.
See also
simC3s, simC3vs, simC3vp, simC2l, simC2vl, simC3vpKLoss, simRTCM, simSRTM, simTRTM, simHuangmet, simTPCMOD0009c, simMBF, simC1, simC3DIvs, simC4DIvp, simC4DIvs, simDispersion, simOxygen
Parameters
tArray of time values
caArray of arterial activities
nrNumber of values in TACs
k1Rate constant of the model
k2Rate constant of the model
k3Rate constant of the model
k4Rate constant of the model
k5Rate constant of the model
k6Rate constant of the model
ctPointer for TAC array to be simulated; must be allocated
ctaPointer for 1st compartment TAC to be simulated, or NULL
ctbPointer for 2nd compartment TAC to be simulated, or NULL
ctcPointer for 3rd compartment TAC to be simulated, or NULL

Definition at line 136 of file simulate.c.

163 {
164 int i;
165 double dt2, r, s, u, v, w;
166 double cai, ca_last, t_last;
167 double ct1, ct1_last, ct2, ct2_last, ct3, ct3_last;
168 double ct1i, ct1i_last, ct2i, ct2i_last, ct3i, ct3i_last;
169
170
171 /* Check for data */
172 if(nr<2) return 1;
173 if(ct==NULL) return 2;
174
175 /* Check parameters */
176 if(k1<0.0) return 3;
177
178 /* Calculate curves */
179 t_last=0.0; if(t[0]<t_last) t_last=t[0];
180 cai=ca_last=0.0;
181 ct1_last=ct2_last=ct3_last=ct1i_last=ct2i_last=ct3i_last=0.0;
182 ct1=ct2=ct3=ct1i=ct2i=ct3i=0.0;
183 for(i=0; i<nr; i++) {
184 /* delta time / 2 */
185 dt2=0.5*(t[i]-t_last);
186 /* calculate values */
187 if(dt2<0.0) {
188 return 5;
189 } else if(dt2>0.0) {
190 /* arterial integral */
191 cai+=(ca[i]+ca_last)*dt2;
192 /* Calculate partial results */
193 r=1.0+k4*dt2;
194 s=1.0+k6*dt2;
195 u=ct1i_last+dt2*ct1_last;
196 v=ct2i_last+dt2*ct2_last;
197 w=ct3i_last+dt2*ct3_last;
198 /* 1st tissue compartment and its integral */
199 ct1 = ( k1*cai - (k2 + (k3/r) + (k5/s))*u + (k4/r)*v + (k6/s)*w )
200 / ( 1.0 + dt2*(k2 + (k3/r) + (k5/s)) );
201 ct1i = ct1i_last + dt2*(ct1_last+ct1);
202 /* 2nd tissue compartment and its integral */
203 ct2 = (k3*ct1i - k4*v) / r;
204 ct2i = ct2i_last + dt2*(ct2_last+ct2);
205 /* 3rd tissue compartment and its integral */
206 ct3 = (k5*ct1i - k6*w) / s;
207 ct3i = ct3i_last + dt2*(ct3_last+ct3);
208 }
209 /* copy values to argument arrays; set very small values to zero */
210 ct[i]=ct1+ct2+ct3; if(fabs(ct[i])<1.0e-12) ct[i]=0.0;
211 if(cta!=NULL) {cta[i]=ct1; if(fabs(cta[i])<1.0e-12) cta[i]=0.0;}
212 if(ctb!=NULL) {ctb[i]=ct2; if(fabs(ctb[i])<1.0e-12) ctb[i]=0.0;}
213 if(ctc!=NULL) {ctc[i]=ct3; if(fabs(ctc[i])<1.0e-12) ctc[i]=0.0;}
214 /* prepare to the next loop */
215 t_last=t[i]; ca_last=ca[i];
216 ct1_last=ct1; ct1i_last=ct1i;
217 ct2_last=ct2; ct2i_last=ct2i;
218 ct3_last=ct3; ct3i_last=ct3i;
219 }
220
221 return 0;
222}

◆ simC3s()

int simC3s ( double * t,
double * ca,
int nr,
double k1,
double k2,
double k3,
double k4,
double k5,
double k6,
double * ct,
double * cta,
double * ctb,
double * ctc )
extern

Simulates tissue TAC using 1-3 tissue compartment model (in series) and plasma TAC, at plasma TAC times.

Memory for ct must be allocated in the calling program. To retrieve the separate tissue compartment TACs, pointer to allocated memory for cta, ctb and/or ctc can be given; if compartmental TACs are not required, NULL pointer can be given instead.

The units of rate constants must be related to the time unit; 1/min and min, or 1/sec and sec.

Returns
Function returns 0 when successful, else a value >= 1.
See also
simC3p, simC3vs, simC3vp, simC2l, simC2vl, simC3vpKLoss, simRTCM, simSRTM, simTRTM, simHuangmet, simTPCMOD0009c, simMBF, simC1, simC3DIvs, simC4DIvp, simC4DIvs, simDispersion, simOxygen
Parameters
tArray of time values
caArray of arterial activities
nrNumber of values in TACs
k1Rate constant of the model
k2Rate constant of the model
k3Rate constant of the model
k4Rate constant of the model
k5Rate constant of the model
k6Rate constant of the model
ctPointer for TAC array to be simulated; must be allocated
ctaPointer for 1st compartment TAC to be simulated, or NULL
ctbPointer for 2nd compartment TAC to be simulated, or NULL
ctcPointer for 3rd compartment TAC to be simulated, or NULL

Definition at line 27 of file simulate.c.

54 {
55 double b, c, d, w, z, dt2;
56 double cai, ca_last, t_last;
57 double ct1, ct1_last, ct2, ct2_last, ct3, ct3_last;
58 double ct1i, ct1i_last, ct2i, ct2i_last, ct3i, ct3i_last;
59
60
61 /* Check for data */
62 if(nr<2) return 1;
63 if(ct==NULL) return 2;
64
65 /* Check actual parameter number */
66 if(k1<0.0) return 3;
67 if(k3<=0.0) {k3=0.0; if(k2<=0.0) {k2=0.0;}}
68 else if(k5<=0.0) {k5=0.0; if(k4<=0.0) {k4=0.0;}}
69 else if(k6<=0.0) {k6=0.0;}
70
71 /* Calculate curves */
72 t_last=0.0; if(t[0]<t_last) t_last=t[0];
73 cai=ca_last=0.0;
74 ct1_last=ct2_last=ct3_last=ct1i_last=ct2i_last=ct3i_last=0.0;
75 ct1=ct2=ct3=ct1i=ct2i=ct3i=0.0;
76 for(int i=0; i<nr; i++) {
77 /* delta time / 2 */
78 dt2=0.5*(t[i]-t_last);
79 /* calculate values */
80 if(dt2<0.0) {
81 return 5;
82 } else if(dt2>0.0) {
83 /* arterial integral */
84 cai+=(ca[i]+ca_last)*dt2;
85 /* partial results */
86 b=ct1i_last+dt2*ct1_last;
87 c=ct2i_last+dt2*ct2_last;
88 d=ct3i_last+dt2*ct3_last;
89 w=k4 + k5 - (k5*k6*dt2)/(1.0+k6*dt2);
90 z=1.0+w*dt2;
91 /* 1st tissue compartment and its integral */
92 ct1 = (
93 + k1*z*cai + (k3*k4*dt2 - (k2+k3)*z)*b
94 + k4*c + k4*k6*dt2*d/(1.0+k6*dt2)
95 ) / ( z*(1.0 + dt2*(k2+k3)) - k3*k4*dt2*dt2 );
96 ct1i = ct1i_last + dt2*(ct1_last+ct1);
97 /* 2nd tissue compartment and its integral */
98 ct2 = (k3*ct1i - w*c + k6*d/(1.0+k6*dt2)) / z;
99 ct2i = ct2i_last + dt2*(ct2_last+ct2);
100 /* 3rd tissue compartment and its integral */
101 ct3 = (k5*ct2i - k6*d) / (1.0 + k6*dt2);
102 ct3i = ct3i_last + dt2*(ct3_last+ct3);
103 }
104 /* copy values to argument arrays; set very small values to zero */
105 ct[i]=ct1+ct2+ct3; if(fabs(ct[i])<1.0e-12) ct[i]=0.0;
106 if(cta!=NULL) {cta[i]=ct1; if(fabs(cta[i])<1.0e-12) cta[i]=0.0;}
107 if(ctb!=NULL) {ctb[i]=ct2; if(fabs(ctb[i])<1.0e-12) ctb[i]=0.0;}
108 if(ctc!=NULL) {ctc[i]=ct3; if(fabs(ctc[i])<1.0e-12) ctc[i]=0.0;}
109 /* prepare to the next loop */
110 t_last=t[i]; ca_last=ca[i];
111 ct1_last=ct1; ct1i_last=ct1i;
112 ct2_last=ct2; ct2i_last=ct2i;
113 ct3_last=ct3; ct3i_last=ct3i;
114 }
115
116 return 0;
117}

◆ simC3vp()

int simC3vp ( double * t,
double * ca,
double * cb,
int nr,
double k1,
double k2,
double k3,
double k4,
double k5,
double k6,
double f,
double vb,
double fa,
double * cpet,
double * cta,
double * ctb,
double * ctc,
double * ctab,
double * ctvb )
extern

Simulates tissue TAC using 1-3 tissue compartment model (2nd and 3rd compartments in parallel) and plasma TAC, at plasma TAC times, considering also arterial and venous vasculature.

Memory for cpet must be allocated in the calling program. To retrieve the separate tissue compartment TACs, pointer to allocated memory for cta, ctb, ctc, ctab and/or ctvb can be given; if compartmental TACs are not required, NULL pointer can be given instead.

The units of rate constants must be related to the time unit; 1/min and min, or 1/sec and sec.

If blood flow is set to 0, function assumes that f>>k1, and Cvb=Cab.,

Returns
Function returns 0 when successful, else a value >= 1.
See also
simC3s, simC3p, simC3vs, simC2l, simC2vl, simC3vpKLoss, simRTCM, simSRTM, simTRTM, simHuangmet, simTPCMOD0009c, simMBF, simC1, simC3DIvs, simC4DIvp, simC4DIvs, simDispersion, simOxygen
Parameters
tArray of time values
caArray of arterial plasma activities
cbArray of arterial blood activities
nrNumber of values in TACs
k1Rate constant of the model
k2Rate constant of the model
k3Rate constant of the model
k4Rate constant of the model
k5Rate constant of the model
k6Rate constant of the model
fBlood flow; if 0, function assumes that f>>k1, and Cvb=Cab.
vbVascular volume fraction
faArterial fraction of vascular volume
cpetPointer for TAC array to be simulated; must be allocated
ctaPointer for 1st compartment TAC to be simulated, or NULL
ctbPointer for 2nd compartment TAC to be simulated, or NULL
ctcPointer for 3rd compartment TAC to be simulated, or NULL
ctabPointer for arterial TAC in tissue, or NULL
ctvbPointer for venous TAC in tissue, or NULL

Definition at line 373 of file simulate.c.

412 {
413 int i;
414 double dt2, r, s, u, v, w, va, vv;
415 double cai, ca_last, t_last, dct, cvb;
416 double ct1, ct1_last, ct2, ct2_last, ct3, ct3_last;
417 double ct1i, ct1i_last, ct2i, ct2i_last, ct3i, ct3i_last;
418
419
420 /* Check for data */
421 if(nr<2) return 1;
422 if(cpet==NULL) return 2;
423
424 /* Check parameters */
425 if(k1<0.0) return 3;
426 if(vb<0.0 || vb>=1.0) return 4;
427 if(fa<=0.0 || fa>1.0) return 5;
428 va=fa*vb; vv=(1.0-fa)*vb;
429
430 /* Calculate curves */
431 t_last=0.0; if(t[0]<t_last) t_last=t[0];
432 cai=ca_last=0.0;
433 ct1_last=ct2_last=ct3_last=ct1i_last=ct2i_last=ct3i_last=0.0;
434 ct1=ct2=ct3=ct1i=ct2i=ct3i=0.0;
435 for(i=0; i<nr; i++) {
436 /* delta time / 2 */
437 dt2=0.5*(t[i]-t_last);
438 /* calculate values */
439 if(dt2<0.0) {
440 return 5;
441 } else if(dt2>0.0) {
442 /* arterial integral */
443 cai+=(ca[i]+ca_last)*dt2;
444 /* Calculate partial results */
445 r=1.0+k4*dt2;
446 s=1.0+k6*dt2;
447 u=ct1i_last+dt2*ct1_last;
448 v=ct2i_last+dt2*ct2_last;
449 w=ct3i_last+dt2*ct3_last;
450 /* 1st tissue compartment and its integral */
451 ct1 = ( k1*cai - (k2 + (k3/r) + (k5/s))*u + (k4/r)*v + (k6/s)*w )
452 / ( 1.0 + dt2*(k2 + (k3/r) + (k5/s)) );
453 ct1i = ct1i_last + dt2*(ct1_last+ct1);
454 /* 2nd tissue compartment and its integral */
455 ct2 = (k3*ct1i - k4*v) / r;
456 ct2i = ct2i_last + dt2*(ct2_last+ct2);
457 /* 3rd tissue compartment and its integral */
458 ct3 = (k5*ct1i - k6*w) / s;
459 ct3i = ct3i_last + dt2*(ct3_last+ct3);
460 }
461 /* Venous curve */
462 if(f>0.) {dct = k1*ca[i] - k2*ct1; cvb = cb[i] - dct/f;} else cvb=cb[i];
463 /* copy values to argument arrays; set very small values to zero */
464 cpet[i]= va*cb[i] + vv*cvb + (1.0-vb)*(ct1+ct2+ct3);
465 if(fabs(cpet[i])<1.0e-12) cpet[i]=0.0;
466 if(cta!=NULL) {cta[i]=(1.0-vb)*ct1; if(fabs(cta[i])<1.0e-12) cta[i]=0.0;}
467 if(ctb!=NULL) {ctb[i]=(1.0-vb)*ct2; if(fabs(ctb[i])<1.0e-12) ctb[i]=0.0;}
468 if(ctc!=NULL) {ctc[i]=(1.0-vb)*ct3; if(fabs(ctc[i])<1.0e-12) ctc[i]=0.0;}
469 if(ctab!=NULL) {ctab[i]=va*cb[i]; if(fabs(ctab[i])<1.0e-12) ctab[i]=0.0;}
470 if(ctvb!=NULL) {ctvb[i]=vv*cvb; if(fabs(ctvb[i])<1.0e-12) ctvb[i]=0.0;}
471 /* prepare to the next loop */
472 t_last=t[i]; ca_last=ca[i];
473 ct1_last=ct1; ct1i_last=ct1i;
474 ct2_last=ct2; ct2i_last=ct2i;
475 ct3_last=ct3; ct3i_last=ct3i;
476 }
477
478 return 0;
479}

◆ simC3vpKLoss()

int simC3vpKLoss ( double * t,
double * ca,
double * cb,
int nr,
double k1,
double k2,
double k3,
double k4,
double k5,
double k6,
double kLoss,
double f,
double vb,
double fa,
double * cpet,
double * cta,
double * ctb,
double * ctc,
double * ctab,
double * ctvb )
extern

Simulates tissue TAC using 3 tissue compartmental model with two parallel compartments, and plasma TAC, at plasma TAC sample times, considering also arterial and venous vasculature. The efflux from 3rd tissue compartment (C) goes directly to blood at rate kLoss.

Memory for cpet must be allocated in the calling program. To retrieve the separate tissue compartment TACs, pointer to allocated memory for cta, ctb, ctab and/or ctvb can be given; if compartmental TACs are not required, NULL pointer can be given instead.

The units of rate constants must be related to the time unit; 1/min and min, or 1/sec and sec.

If blood flow is set to 0, function assumes that f>>k1, and Cvb=Cab.,

Returns
Function returns 0 when successful, else a value >= 1.
See also
simC3s, simC3p, simC3vs, simC3vp, simC2l, simC2vl, simRTCM, simSRTM, simTRTM, simHuangmet, simTPCMOD0009c, simMBF, simC1, simC3DIvs, simC4DIvp, simC4DIvs, simDispersion, simOxygen
Parameters
tArray of sample times
caArray of arterial plasma activities
cbArray of arterial blood activities
nrNumber of sample values in TACs
k1Rate constant of the model
k2Rate constant of the model
k3Rate constant of the model
k4Rate constant of the model
k5Rate constant of the model
k6Rate constant of the model
kLossRate constant of the model
fBlood flow; if 0, function assumes that f>>k1, and Cvb=Cab.
vbVascular volume fraction
faArterial fraction of vascular volume
cpetPointer for TAC array to be simulated; must be allocated
ctaPointer for 1st tissue compartment TAC to be simulated, or NULL
ctbPointer for 2nd compartment TAC to be simulated, or NULL
ctcPointer for 3rd compartment TAC to be simulated, or NULL
ctabPointer for arterial TAC in tissue, or NULL
ctvbPointer for venous TAC in tissue, or NULL

Definition at line 707 of file simulate.c.

748 {
749 int i;
750 double dt2, b, c, d, w, z, u, va, vv;
751 double cai, ca_last, t_last, dct, cvb;
752 double ct1, ct1_last, ct2, ct2_last, ct3, ct3_last;
753 double ct1i, ct1i_last, ct2i, ct2i_last, ct3i, ct3i_last;
754
755
756 /* Check for data */
757 if(nr<2) return 1;
758 if(cpet==NULL) return 2;
759
760 /* Check parameters */
761 if(k1<0.0) return 3;
762 if(vb<0.0 || vb>=1.0) return 4;
763 if(fa<=0.0 || fa>1.0) return 5;
764 va=fa*vb; vv=(1.0-fa)*vb;
765
766 /* Calculate curves */
767 t_last=0.0; if(t[0]<t_last) t_last=t[0];
768 cai=ca_last=0.0;
769 ct1_last=ct2_last=ct3_last=ct1i_last=ct2i_last=ct3i_last=0.0;
770 ct1=ct2=ct3=ct1i=ct2i=ct3i=0.0;
771 for(i=0; i<nr; i++) {
772 /* delta time / 2 */
773 dt2=0.5*(t[i]-t_last);
774 /* calculate values */
775 if(dt2<0.0) {
776 return 5;
777 } else if(dt2>0.0) {
778 /* arterial integral */
779 cai+=(ca[i]+ca_last)*dt2;
780 /* Calculate partial results */
781 w = 1.0 + k4*dt2;
782 z = 1.0 + dt2*(k6 + kLoss);
783 u = k2 + k3 + k5 - k3*k4*dt2/w - k5*k6*dt2/z;
784 b = ct1i_last+dt2*ct1_last;
785 c = ct2i_last+dt2*ct2_last;
786 d = ct3i_last+dt2*ct3_last;
787 /* 1st tissue compartment and its integral */
788 ct1 = ( k1*cai - u*b + k4*c/w + k6*d/z ) / ( 1.0 + dt2*u);
789 ct1i = ct1i_last + dt2*(ct1_last+ct1);
790 /* 2nd tissue compartment and its integral */
791 ct2 = (k3*ct1i - k4*c) / w;
792 ct2i = ct2i_last + dt2*(ct2_last+ct2);
793 /* 3rd tissue compartment and its integral */
794 ct3 = (k5*ct1i - (k6 + kLoss)*d) / z;
795 ct3i = ct3i_last + dt2*(ct3_last+ct3);
796 }
797 /* Venous curve */
798 if(f>0.) {dct = k1*ca[i] - k2*ct1 - kLoss*ct3; cvb = cb[i] - dct/f;}
799 else cvb=cb[i];
800 /* copy values to argument arrays; set very small values to zero */
801 cpet[i]= va*cb[i] + vv*cvb + (1.0-vb)*(ct1+ct2+ct3);
802 if(fabs(cpet[i])<1.0e-12) cpet[i]=0.0;
803 if(cta!=NULL) {cta[i]=(1.0-vb)*ct1; if(fabs(cta[i])<1.0e-12) cta[i]=0.0;}
804 if(ctb!=NULL) {ctb[i]=(1.0-vb)*ct2; if(fabs(ctb[i])<1.0e-12) ctb[i]=0.0;}
805 if(ctc!=NULL) {ctc[i]=(1.0-vb)*ct3; if(fabs(ctc[i])<1.0e-12) ctc[i]=0.0;}
806 if(ctab!=NULL) {ctab[i]=va*cb[i]; if(fabs(ctab[i])<1.0e-12) ctab[i]=0.0;}
807 if(ctvb!=NULL) {ctvb[i]=vv*cvb; if(fabs(ctvb[i])<1.0e-12) ctvb[i]=0.0;}
808 /* prepare to the next loop */
809 t_last=t[i]; ca_last=ca[i];
810 ct1_last=ct1; ct1i_last=ct1i;
811 ct2_last=ct2; ct2i_last=ct2i;
812 ct3_last=ct3; ct3i_last=ct3i;
813 }
814
815 return 0;
816}

◆ simC3vs()

int simC3vs ( double * t,
double * ca,
double * cb,
int nr,
double k1,
double k2,
double k3,
double k4,
double k5,
double k6,
double f,
double vb,
double fa,
double * cpet,
double * cta,
double * ctb,
double * ctc,
double * ctab,
double * ctvb )
extern

Simulates tissue TAC using 1-3 tissue compartment model (in series) and plasma TAC, at plasma TAC times, considering also arterial and venous vasculature.

Memory for cpet must be allocated in the calling program. To retrieve the separate tissue compartment TACs, pointer to allocated memory for cta, ctb, ctc, ctab and/or ctvb can be given; if compartmental TACs are not required, NULL pointer can be given instead.

The units of rate constants must be related to the time unit; 1/min and min, or 1/sec and sec.

If blood flow is set to 0, function assumes that f>>k1, and Cvb=Cab.,

Returns
Function returns 0 when successful, else a value >= 1.
See also
simC3s, simC3p, simC3vp, simC2l, simC2vl, simC3vpKLoss, simRTCM, simSRTM, simTRTM, simHuangmet, simTPCMOD0009c, simMBF, simC1, simC3DIvs, simC4DIvp, simC4DIvs, simDispersion, simOxygen
Parameters
tArray of time values
caArray of arterial plasma activities
cbArray of arterial blood activities
nrNumber of values in TACs
k1Rate constant of the model
k2Rate constant of the model
k3Rate constant of the model
k4Rate constant of the model
k5Rate constant of the model
k6Rate constant of the model
fBlood flow; if 0, function assumes that f>>k1, and Cvb=Cab.
vbVascular volume fraction
faArterial fraction of vascular volume
cpetPointer for TAC array to be simulated; must be allocated
ctaPointer for 1st compartment TAC to be simulated, or NULL
ctbPointer for 2nd compartment TAC to be simulated, or NULL
ctcPointer for 3rd compartment TAC to be simulated, or NULL
ctabPointer for arterial TAC in tissue, or NULL
ctvbPointer for venous TAC in tissue, or NULL

Definition at line 243 of file simulate.c.

282 {
283 int i;
284 double b, c, d, w, z, dt2, va, vv;
285 double cai, ca_last, t_last, dct, cvb;
286 double ct1, ct1_last, ct2, ct2_last, ct3, ct3_last;
287 double ct1i, ct1i_last, ct2i, ct2i_last, ct3i, ct3i_last;
288
289
290 /* Check for data */
291 if(nr<2) return 1;
292 if(cpet==NULL) return 2;
293
294 /* Check parameters */
295 if(k1<0.0) return 3;
296 if(vb<0.0 || vb>=1.0) return 4;
297 if(fa<=0.0 || fa>1.0) return 5;
298 va=fa*vb; vv=(1.0-fa)*vb;
299
300 /* Calculate curves */
301 t_last=0.0; if(t[0]<t_last) t_last=t[0];
302 cai=ca_last=0.0;
303 ct1_last=ct2_last=ct3_last=ct1i_last=ct2i_last=ct3i_last=0.0;
304 ct1=ct2=ct3=ct1i=ct2i=ct3i=0.0;
305 for(i=0; i<nr; i++) {
306 /* delta time / 2 */
307 dt2=0.5*(t[i]-t_last);
308 /* calculate values */
309 if(dt2<0.0) {
310 return 5;
311 } else if(dt2>0.0) {
312 /* arterial integral */
313 cai+=(ca[i]+ca_last)*dt2;
314 /* partial results */
315 b=ct1i_last+dt2*ct1_last;
316 c=ct2i_last+dt2*ct2_last;
317 d=ct3i_last+dt2*ct3_last;
318 w=k4 + k5 - (k5*k6*dt2)/(1.0+k6*dt2);
319 z=1.0+w*dt2;
320 /* 1st tissue compartment and its integral */
321 ct1 = (
322 + k1*z*cai + (k3*k4*dt2 - (k2+k3)*z)*b
323 + k4*c + k4*k6*dt2*d/(1.0+k6*dt2)
324 ) / ( z*(1.0 + dt2*(k2+k3)) - k3*k4*dt2*dt2 );
325 ct1i = ct1i_last + dt2*(ct1_last+ct1);
326 /* 2nd tissue compartment and its integral */
327 ct2 = (k3*ct1i - w*c + k6*d/(1.0+k6*dt2)) / z;
328 ct2i = ct2i_last + dt2*(ct2_last+ct2);
329 /* 3rd tissue compartment and its integral */
330 ct3 = (k5*ct2i - k6*d) / (1.0 + k6*dt2);
331 ct3i = ct3i_last + dt2*(ct3_last+ct3);
332 }
333 /* Venous curve */
334 if(f>0.) {dct = k1*ca[i] - k2*ct1; cvb = cb[i] - dct/f;} else cvb=cb[i];
335 /* copy values to argument arrays; set very small values to zero */
336 cpet[i]= va*cb[i] + vv*cvb + (1.0-vb)*(ct1+ct2+ct3);
337 if(fabs(cpet[i])<1.0e-12) cpet[i]=0.0;
338 if(cta!=NULL) {cta[i]=(1.0-vb)*ct1; if(fabs(cta[i])<1.0e-12) cta[i]=0.0;}
339 if(ctb!=NULL) {ctb[i]=(1.0-vb)*ct2; if(fabs(ctb[i])<1.0e-12) ctb[i]=0.0;}
340 if(ctc!=NULL) {ctc[i]=(1.0-vb)*ct3; if(fabs(ctc[i])<1.0e-12) ctc[i]=0.0;}
341 if(ctab!=NULL) {ctab[i]=va*cb[i]; if(fabs(ctab[i])<1.0e-12) ctab[i]=0.0;}
342 if(ctvb!=NULL) {ctvb[i]=vv*cvb; if(fabs(ctvb[i])<1.0e-12) ctvb[i]=0.0;}
343 /* prepare to the next loop */
344 t_last=t[i]; ca_last=ca[i];
345 ct1_last=ct1; ct1i_last=ct1i;
346 ct2_last=ct2; ct2i_last=ct2i;
347 ct3_last=ct3; ct3i_last=ct3i;
348 }
349
350 return 0;
351}

◆ simC4DIvp()

int simC4DIvp ( double * t,
double * ca1,
double * ca2,
double * cb,
int nr,
double k1,
double k2,
double k3,
double k4,
double k5,
double k6,
double k7,
double km,
double k1b,
double k2b,
double f,
double vb,
double fa,
double * scpet,
double * sct1,
double * sct2,
double * sct3,
double * sct1b,
double * sctab,
double * sctvb,
int verbose )
extern

Simulates tissue TAC using dual-input tissue compartment model (compartments 2 and 3 in parallel for tracer1, and 1 compartment for tracer2) at plasma TAC sample times, considering also contribution of arterial and venous vasculature, and transfer of tracer1 to tracer2. The units of rate constants must be related to the time unit; 1/min and min, or 1/sec and sec. If blood flow is set to 0, function assumes that f>>k1, and Cvb=Cab. Reference: TPCMOD0001 Appendix C. Tested with program p2t_di -parallel.

Returns
Function returns 0 when successful, else a value >= 1.
See also
simC3s, simC3p, simC3vs, simC3vp, simC2l, simC2vl, simC3vpKLoss, simRTCM, simSRTM, simTRTM, simHuangmet, simTPCMOD0009c, simMBF, simC1, simC3DIvs, simC4DIvs, simDispersion, simOxygen
Parameters
tArray of time values
ca1Array of arterial plasma activities of tracer1 (parent tracer)
ca2Array of arterial plasma activities of tracer2 (metabolite)
cbArray of (total) arterial blood activities
nrNumber of values in TACs
k1Rate constant of the model for tracer1 (from plasma to C1)
k2Rate constant of the model for tracer1 (from C1 to plasma)
k3Rate constant of the model for tracer1 (from C1 to C2)
k4Rate constant of the model for tracer1 (from C2 to C1)
k5Rate constant of the model for tracer1 (from C1 to C3)
k6Rate constant of the model for tracer1 (from C3 to C1)
k7Rate constant of the model for tracer1 (from C3 to plasma)
kmRate constant of the model (from tracer1 in C1 to tracer2 in C4)
k1bRate constant of the model for tracer2 (from plasma to C4)
k2bRate constant of the model for tracer2 (from C4 to plasma)
fBlood flow; if 0, function assumes that f>>k1, and Cvb=Cab
vbVascular volume fraction (0<=Vb<1)
faArterial fraction of vascular volume (0<=fa<=1)
scpetPointer for TAC array to be simulated; must be allocated
sct1Pointer for 1st tracer1 compartment TAC, or NULL if not needed
sct2Pointer for 2nd tracer1 compartment TAC, or NULL if not needed
sct3Pointer for 3rd tracer1 compartment TAC, or NULL if not needed
sct1bPointer for 1st tracer2 compartment TAC, or NULL if not needed
sctabPointer for arterial TAC in tissue, or NULL if not needed
sctvbPointer for venous TAC in tissue, or NULL if not needed
verboseVerbose level; if zero, then nothing is printed into stdout or stderr

Definition at line 1533 of file simulate.c.

1586 {
1587 int i;
1588 double b, c, d, e, pt, qt, dt2, va, vv;
1589 double ca1i, ca1_last, ca2i, ca2_last, t_last, dct, cvb;
1590 double ct1, ct1_last, ct2, ct2_last, ct3, ct3_last;
1591 double ct1i, ct1i_last, ct2i, ct2i_last, ct3i, ct3i_last;
1592 double ct1b, ct1b_last, ct1bi, ct1bi_last;
1593
1594
1595 if(verbose>0) {
1596 printf("simC4DIvp()\n");
1597 if(verbose>1) {
1598 printf(" k1 := %g\n", k1);
1599 printf(" k2 := %g\n", k2);
1600 printf(" k3 := %g\n", k3);
1601 printf(" k4 := %g\n", k4);
1602 printf(" k5 := %g\n", k5);
1603 printf(" k6 := %g\n", k6);
1604 printf(" k7 := %g\n", k7);
1605 printf(" km := %g\n", km);
1606 printf(" k1b := %g\n", k1b);
1607 printf(" k2b := %g\n", k2b);
1608 printf(" vb := %g\n", vb);
1609 printf(" fa := %g\n", fa);
1610 printf(" f := %g\n", f);
1611 }
1612 }
1613
1614 /* Check for data */
1615 if(nr<2) return 1;
1616 if(scpet==NULL) return 2;
1617
1618 /* Check parameters */
1619 if(k1<0.0 || k1b<0.0) return 3;
1620 if(vb<0.0 || vb>=1.0) return 4;
1621 if(fa<0.0 || fa>1.0) return 5;
1622 va=fa*vb; vv=(1.0-fa)*vb;
1623
1624 /* Calculate curves */
1625 t_last=0.0; if(t[0]<t_last) t_last=t[0];
1626 ca1i=ca1_last=ca2i=ca2_last=0.0;
1627 ct1_last=ct2_last=ct3_last=ct1i_last=ct2i_last=ct3i_last=ct1b_last=
1628 ct1bi_last=0.0;
1629 ct1=ct2=ct3=ct1b=ct1i=ct2i=ct3i=ct1bi=0.0;
1630 for(i=0; i<nr; i++) {
1631 /* delta time / 2 */
1632 dt2=0.5*(t[i]-t_last);
1633 /* calculate values */
1634 if(dt2<0.0) {
1635 return 5;
1636 } else if(dt2>0.0) {
1637 /* arterial integrals */
1638 ca1i+=(ca1[i]+ca1_last)*dt2;
1639 ca2i+=(ca2[i]+ca2_last)*dt2;
1640 /* partial results */
1641 b=ct1i_last+dt2*ct1_last;
1642 c=ct2i_last+dt2*ct2_last;
1643 d=ct3i_last+dt2*ct3_last;
1644 e=ct1bi_last+dt2*ct1b_last;
1645 pt=k6+k7;
1646 qt=k2+k3+k5+km-(k3*k4*dt2)/(1.0+k4*dt2)-(k5*k6*dt2)/(1.0+pt*dt2);
1647 /* 1st tissue compartment and its integral */
1648 ct1 = (k1/(1.0+qt*dt2))*ca1i
1649 - (qt/(1.0+qt*dt2))*b
1650 + (k4/((1.0+qt*dt2)*(1.0+k4*dt2)))*c
1651 + (k6/((1.0+qt*dt2)*(1.0+pt*dt2)))*d;
1652 ct1i = ct1i_last + dt2*(ct1_last+ct1);
1653 /* 2nd tissue compartment and its integral */
1654 ct2 = (k3/(1.0+k4*dt2))*ct1i
1655 - (k4/(1.0+k4*dt2))*c;
1656 ct2i = ct2i_last + dt2*(ct2_last+ct2);
1657 /* 3rd tissue compartment and its integral */
1658 ct3 = (k5/(1.0+pt*dt2))*ct1i
1659 - (pt/(1.0+pt*dt2))*d;
1660 ct3i = ct3i_last + dt2*(ct3_last+ct3);
1661 /* 4th tissue compartment (the 1st for tracer 2) and its integral */
1662 ct1b = (k1b/(1.0+k2b*dt2))*ca2i
1663 - (k2b/(1.0+k2b*dt2))*e
1664 + (km/(1.0+k2b*dt2))*ct1i;
1665 ct1bi = ct1bi_last + dt2*(ct1b_last+ct1b);
1666 }
1667 /* Venous curve */
1668 if(f>0.) {
1669 dct = k1*ca1[i] - k2*ct1 - k7*ct3 + k1b*ca2[i] - k2b*ct1b;
1670 cvb = cb[i] - dct/f;
1671 } else cvb=cb[i];
1672 /* copy values to argument arrays; set very small values to zero */
1673 scpet[i]= va*cb[i] + vv*cvb + (1.0-vb)*(ct1+ct2+ct3+ct1b);
1674 if(fabs(scpet[i])<1.0e-12) scpet[i]=0.0;
1675 if(sct1!=NULL) {
1676 sct1[i]=(1.0-vb)*ct1; if(fabs(sct1[i])<1.0e-12) sct1[i]=0.0;}
1677 if(sct2!=NULL) {
1678 sct2[i]=(1.0-vb)*ct2; if(fabs(sct2[i])<1.0e-12) sct2[i]=0.0;}
1679 if(sct3!=NULL) {
1680 sct3[i]=(1.0-vb)*ct3; if(fabs(sct3[i])<1.0e-12) sct3[i]=0.0;}
1681 if(sct1b!=NULL) {
1682 sct1b[i]=(1.0-vb)*ct1b; if(fabs(sct1b[i])<1.0e-12) sct1b[i]=0.0;}
1683 if(sctab!=NULL) {
1684 sctab[i]=va*cb[i]; if(fabs(sctab[i])<1.0e-12) sctab[i]=0.0;}
1685 if(sctvb!=NULL) {
1686 sctvb[i]=vv*cvb; if(fabs(sctvb[i])<1.0e-12) sctvb[i]=0.0;}
1687 /* prepare to the next loop */
1688 t_last=t[i]; ca1_last=ca1[i]; ca2_last=ca2[i];
1689 ct1_last=ct1; ct1i_last=ct1i;
1690 ct2_last=ct2; ct2i_last=ct2i;
1691 ct3_last=ct3; ct3i_last=ct3i;
1692 ct1b_last=ct1b; ct1bi_last=ct1bi;
1693 }
1694
1695 if(verbose>2) {
1696 printf("AUC 0-%g:\n", t_last);
1697 printf(" ca1i := %g\n", ca1i);
1698 printf(" ca2i := %g\n", ca2i);
1699 printf(" ct1i := %g\n", ct1i_last);
1700 printf(" ct2i := %g\n", ct2i_last);
1701 printf(" ct3i := %g\n", ct3i_last);
1702 printf(" ct1bi := %g\n", ct1bi_last);
1703 }
1704
1705 return 0;
1706}

◆ simC4DIvs()

int simC4DIvs ( double * t,
double * ca1,
double * ca2,
double * cb,
int nr,
double k1,
double k2,
double k3,
double k4,
double k5,
double k6,
double k7,
double km,
double k1b,
double k2b,
double f,
double vb,
double fa,
double * scpet,
double * sct1,
double * sct2,
double * sct3,
double * sct1b,
double * sctab,
double * sctvb,
int verbose )
extern

Simulates tissue TAC using dual-input tissue compartment model (1-3 compartments in series for tracer1, and 1 compartment for tracer2) at plasma TAC times, considering also contribution of arterial and venous vasculature, and transfer of tracer1 to tracer2. The units of rate constants must be related to the time unit; 1/min and min, or 1/sec and sec. If blood flow is set to 0, function assumes that f>>k1, and Cvb=Cab. Reference: TPCMOD0001 Appendix B. Tested with program p2t_di -series.

Returns
Function returns 0 when successful, else a value >= 1.
See also
simC3s, simC3p, simC3vs, simC3vp, simC2l, simC2vl, simC3vpKLoss, simRTCM, simSRTM, simTRTM, simHuangmet, simTPCMOD0009c, simMBF, simC1, simC3DIvs, simC4DIvp, simDispersion, simOxygen
Parameters
tArray of time values
ca1Array of arterial plasma activities of tracer1 (parent tracer)
ca2Array of arterial plasma activities of tracer2 (metabolite)
cbArray of (total) arterial blood activities
nrNumber of values in TACs
k1Rate constant of the model for tracer1 (from plasma to C1)
k2Rate constant of the model for tracer1 (from C1 to plasma)
k3Rate constant of the model for tracer1 (from C1 to C2)
k4Rate constant of the model for tracer1 (from C2 to C1)
k5Rate constant of the model for tracer1 (from C2 to C3)
k6Rate constant of the model for tracer1 (from C3 to C2)
k7Rate constant of the model for tracer1 (from C3 to plasma)
kmRate constant of the model (from tracer1 in C1 to tracer2 in C4)
k1bRate constant of the model for tracer2 (from plasma to C4)
k2bRate constant of the model for tracer2 (from C4 to plasma)
fBlood flow; if 0, function assumes that f>>k1, and Cvb=Cab.
vbVascular volume fraction
faArterial fraction of vascular volume
scpetPointer for TAC array to be simulated; must be allocated
sct1Pointer for 1st tracer1 compartment TAC, or NULL if not needed
sct2Pointer for 2nd tracer1 compartment TAC, or NULL if not needed
sct3Pointer for 3rd tracer1 compartment TAC, or NULL if not needed
sct1bPointer for 1st tracer2 compartment TAC, or NULL if not needed
sctabPointer for arterial TAC in tissue, or NULL if not needed
sctvbPointer for venous TAC in tissue, or NULL if not needed
verboseVerbose level; if zero, then nothing is printed into stdout or stderr

Definition at line 1724 of file simulate.c.

1777 {
1778 int i;
1779 double b, c, d, e, pt, qt, rt, dt2, va, vv;
1780 double ca1i, ca1_last, ca2i, ca2_last, t_last, dct, cvb;
1781 double ct1, ct1_last, ct2, ct2_last, ct3, ct3_last;
1782 double ct1i, ct1i_last, ct2i, ct2i_last, ct3i, ct3i_last;
1783 double ct1b, ct1b_last, ct1bi, ct1bi_last;
1784
1785
1786 if(verbose>0) {
1787 printf("simC4DIvs()\n");
1788 if(verbose>1) {
1789 printf(" k1 := %g\n", k1);
1790 printf(" k2 := %g\n", k2);
1791 printf(" k3 := %g\n", k3);
1792 printf(" k4 := %g\n", k4);
1793 printf(" k5 := %g\n", k5);
1794 printf(" k6 := %g\n", k6);
1795 printf(" k7 := %g\n", k7);
1796 printf(" km := %g\n", km);
1797 printf(" k1b := %g\n", k1b);
1798 printf(" k2b := %g\n", k2b);
1799 printf(" vb := %g\n", vb);
1800 printf(" fa := %g\n", fa);
1801 printf(" f := %g\n", f);
1802 }
1803 }
1804
1805 /* Check for data */
1806 if(nr<2) return 1;
1807 if(scpet==NULL) return 2;
1808
1809 /* Check parameters */
1810 if(k1<0.0 || k1b<0.0) return 3;
1811 if(vb<0.0 || vb>=1.0) return 4;
1812 if(fa<0.0 || fa>1.0) return 5;
1813 va=fa*vb; vv=(1.0-fa)*vb;
1814
1815 /* Calculate curves */
1816 t_last=0.0; if(t[0]<t_last) t_last=t[0];
1817 ca1i=ca1_last=ca2i=ca2_last=0.0;
1818 ct1_last=ct2_last=ct3_last=ct1i_last=ct2i_last=ct3i_last=ct1b_last=
1819 ct1bi_last=0.0;
1820 ct1=ct2=ct3=ct1b=ct1i=ct2i=ct3i=ct1bi=0.0;
1821 for(i=0; i<nr; i++) {
1822 /* delta time / 2 */
1823 dt2=0.5*(t[i]-t_last);
1824 /* calculate values */
1825 if(dt2<0.0) {
1826 return 5;
1827 } else if(dt2>0.0) {
1828 /* arterial integrals */
1829 ca1i+=(ca1[i]+ca1_last)*dt2;
1830 ca2i+=(ca2[i]+ca2_last)*dt2;
1831 //printf("ca1[%d]=%g int=%g\n", i, ca1[i], ca1i);
1832 //printf("ca2[%d]=%g int=%g\n", i, ca2[i], ca2i);
1833 /* partial results */
1834 b=ct1i_last+dt2*ct1_last;
1835 c=ct2i_last+dt2*ct2_last;
1836 d=ct3i_last+dt2*ct3_last;
1837 e=ct1bi_last+dt2*ct1b_last;
1838 pt=k6+k7;
1839 qt=k4+k5-(k5*k6*dt2)/(1.0+pt*dt2);
1840 rt=k2+k3+km-(k3*k4*dt2)/(1.0+qt*dt2);
1841 /* 1st tissue compartment and its integral */
1842 ct1 = (k1/(1.0+rt*dt2))*ca1i
1843 - (rt/(1.0+rt*dt2))*b
1844 + (k4/((1.0+qt*dt2)*(1.0+rt*dt2)))*c
1845 + ((k4*k6*dt2)/((1.0+pt*dt2)*(1.0+qt*dt2)*(1.0+rt*dt2)))*d;
1846 ct1i = ct1i_last + dt2*(ct1_last+ct1);
1847 /* 2nd tissue compartment and its integral */
1848 ct2 = (k3/(1.0+qt*dt2))*ct1i
1849 - (qt/(1.0+qt*dt2))*c
1850 + (k6/((1.0+pt*dt2)*(1.0+qt*dt2)))*d;
1851 ct2i = ct2i_last + dt2*(ct2_last+ct2);
1852 /* 3rd tissue compartment and its integral */
1853 ct3 = (k5/(1.0+pt*dt2))*ct2i
1854 - (pt/(1.0+pt*dt2))*d;
1855 ct3i = ct3i_last + dt2*(ct3_last+ct3);
1856 /* 4th tissue compartment (the 1st for tracer 2) and its integral */
1857 ct1b = (k1b/(1.0+k2b*dt2))*ca2i
1858 - (k2b/(1.0+k2b*dt2))*e
1859 + (km/(1.0+k2b*dt2))*ct1i;
1860 ct1bi = ct1bi_last + dt2*(ct1b_last+ct1b);
1861 }
1862 /* Venous curve */
1863 if(f>0.) {
1864 dct = k1*ca1[i] - k2*ct1 - k7*ct3 + k1b*ca2[i] - k2b*ct1b;
1865 cvb = cb[i] - dct/f;
1866 } else cvb=cb[i];
1867 /* copy values to argument arrays; set very small values to zero */
1868 scpet[i]= va*cb[i] + vv*cvb + (1.0-vb)*(ct1+ct2+ct3+ct1b);
1869 if(fabs(scpet[i])<1.0e-12) scpet[i]=0.0;
1870 if(sct1!=NULL) {
1871 sct1[i]=(1.0-vb)*ct1; if(fabs(sct1[i])<1.0e-12) sct1[i]=0.0;}
1872 if(sct2!=NULL) {
1873 sct2[i]=(1.0-vb)*ct2; if(fabs(sct2[i])<1.0e-12) sct2[i]=0.0;}
1874 if(sct3!=NULL) {
1875 sct3[i]=(1.0-vb)*ct3; if(fabs(sct3[i])<1.0e-12) sct3[i]=0.0;}
1876 if(sct1b!=NULL) {
1877 sct1b[i]=(1.0-vb)*ct1b; if(fabs(sct1b[i])<1.0e-12) sct1b[i]=0.0;}
1878 if(sctab!=NULL) {
1879 sctab[i]=va*cb[i]; if(fabs(sctab[i])<1.0e-12) sctab[i]=0.0;}
1880 if(sctvb!=NULL) {
1881 sctvb[i]=vv*cvb; if(fabs(sctvb[i])<1.0e-12) sctvb[i]=0.0;}
1882 /* prepare to the next loop */
1883 t_last=t[i]; ca1_last=ca1[i]; ca2_last=ca2[i];
1884 ct1_last=ct1; ct1i_last=ct1i;
1885 ct2_last=ct2; ct2i_last=ct2i;
1886 ct3_last=ct3; ct3i_last=ct3i;
1887 ct1b_last=ct1b; ct1bi_last=ct1bi;
1888 }
1889
1890 if(verbose>2) {
1891 printf("AUC 0-%g:\n", t_last);
1892 printf(" ca1i := %g\n", ca1i);
1893 printf(" ca2i := %g\n", ca2i);
1894 printf(" ct1i := %g\n", ct1i_last);
1895 printf(" ct2i := %g\n", ct2i_last);
1896 printf(" ct3i := %g\n", ct3i_last);
1897 printf(" ct1bi := %g\n", ct1bi_last);
1898 }
1899
1900 return 0;
1901}

◆ simDispersion()

int simDispersion ( double * x,
double * y,
int n,
double tau1,
double tau2,
double * tmp )
extern

Simulate the effect of dispersion on a time-activity curve.

Returns
Returns 0 when successful, otherwise <>0.
See also
simC3s, simC3p, simC3vs, simC3vp, simC2l, simC2vl, simC3vpKLoss, simRTCM, simSRTM, simTRTM, simHuangmet, simTPCMOD0009c, simMBF, simC1, simC3DIvs, simC4DIvp, simC4DIvs, simOxygen
Parameters
xArray of sample times.
yArray of sample values, which will be replaced here by dispersion added values.
nNr of samples.
tau1First dispersion time constant (zero if no dispersion); in same time unit as sample times.
tau22nd dispersion time constant (zero if no dispersion); in same time unit as sample times.
tmpArray for temporary data, for at least n samples; enter NULL to let function to allocate and free the temporary space.

Definition at line 1911 of file simulate.c.

1925 {
1926 /* Check input */
1927 if(x==NULL || y==NULL || n<2) return 1;
1928 if(tau1<0.0 || tau2<0.0) return 2;
1929
1930 /* Allocate memory if not allocated by user */
1931 double *buf;
1932 if(tmp!=NULL) buf=tmp; else buf=(double*)malloc(n*sizeof(double));
1933 if(buf==NULL) return 3;
1934
1935 /* First dispersion */
1936 if(tau1>0.0) {
1937 double k=1.0/tau1;
1938 int ret=simC1(x, y, n, k, k, buf);
1939 if(ret!=0) {
1940 if(tmp==NULL) free(buf);
1941 return 100+ret;
1942 }
1943 for(int i=0; i<n; i++) y[i]=buf[i];
1944 }
1945
1946 /* Second dispersion */
1947 if(tau2>0.0) {
1948 double k=1.0/tau2;
1949 int ret=simC1(x, y, n, k, k, buf);
1950 if(ret!=0) {
1951 if(tmp==NULL) free(buf);
1952 return 200+ret;
1953 }
1954 for(int i=0; i<n; i++) y[i]=buf[i];
1955 }
1956
1957 if(tmp==NULL) free(buf);
1958 return 0;
1959}
int simC1(double *t, double *ca, int nr, double k1, double k2, double *ct)
Definition simulate.c:1317

Referenced by fitEvaltac().

◆ simHuangmet()

int simHuangmet ( double * t,
double * ctot,
int nr,
double k01,
double k12,
double k21,
double k03,
double k34,
double k43,
double * c0,
double * c1,
double * c3 )
extern

Simulation of TACs of parent tracer, and 1-2 of its metabolites in plasma using Huang's compartmental model.

The units of model parameters must be related to the sample time unit; 1/min and min, or 1/sec and sec.

Pointers to memory for output TACs must be specified, or NULL if TAC is not needed.

Returns
Returns 0, if ok.
See also
simC3s, simC3p, simC3vs, simC3vp, simC2l, simC2vl, simC3vpKLoss, simRTCM, simSRTM, simTRTM, simTPCMOD0009c, simMBF, simC1, simC3DIvs, simC4DIvp, simC4DIvs, simDispersion, simOxygen
Parameters
tInput: Sample times (preferably with short intervals)
ctotInput: Measured total plasma TAC
nrInput: Nr of samples
k01Input: Model parameters
k12Input: Model parameters
k21Input: Model parameters
k03Input: Model parameters
k34Input: Model parameters
k43Input: Model parameters
c0Output: unchanged (parent) tracer TAC
c1Output: TAC of the 1st metabolite
c3Output: TAC of the 2nd metabolite

Definition at line 1054 of file simulate.c.

1079 {
1080 int i;
1081 double dt2, t_last, ictot, ctot_last;
1082 double c0_, c1_, c2_, c3_, c4_;
1083 double ic0_, ic1_, ic2_, ic3_, ic4_;
1084 double c0_last, c1_last, c2_last, c3_last, c4_last;
1085 double ic0_last, ic1_last, ic2_last, ic3_last, ic4_last;
1086 double a, b, am1, am2, am3, am4;
1087
1088
1089 /* Check input */
1090 if(t==NULL || ctot==NULL || nr<2) return(1);
1091 if(k01<0 || k12<0 || k21<0 || k03<0 || k34<0 || k43<0) return(2);
1092 if(t[0]<0.0) return(3);
1093
1094 /* Compute the TACs */
1095 t_last=0.0; if(t[0]<t_last) t_last=t[0];
1096 ictot=ctot_last=0.0;
1097 c0_=c0_last=ic0_=ic0_last=0.0;
1098 c1_=c1_last=ic1_=ic1_last=0.0;
1099 c2_=c2_last=ic2_=ic2_last=0.0;
1100 c3_=c3_last=ic3_=ic3_last=0.0;
1101 c4_=c4_last=ic4_=ic4_last=0.0;
1102 for(i=0; i<nr; i++) {
1103 /* delta time / 2 */
1104 dt2=0.5*(t[i]-t_last); if(dt2<0.0) return(5);
1105 if(dt2>0.0) {
1106 /* Compute temp constants */
1107 a=k01+k12-(k12*k21*dt2/(1.0+dt2*k21));
1108 b=k03+k34-(k34*k43*dt2/(1.0+dt2*k43));
1109 am1=ic1_last+dt2*c1_last;
1110 am2=ic2_last+dt2*c2_last;
1111 am3=ic3_last+dt2*c3_last;
1112 am4=ic4_last+dt2*c4_last;
1113
1114 /* Compute the "input" i.e. ctot integral */
1115 ictot+=(ctot[i]+ctot_last)*dt2;
1116 /* Compute C1(t) and its integral */
1117 c1_= ( k01*(1.0-k03*dt2/(1.0+dt2*b))*ictot
1118 -(a-k01*k03*dt2/(1.0+dt2*b))*am1
1119 +(k21/(1.0+dt2*k21))*am2
1120 -(k01/(1.0+dt2*b))*am3
1121 -(k01*k43*dt2/((1.0+dt2*b)*(1.0+dt2*k43)))*am4
1122 ) / ( 1.0+dt2*(a-k01*k03*dt2/(1.0+dt2*b)) );
1123 ic1_= ic1_last + dt2*(c1_+c1_last);
1124 /* Compute C2(t) and its integral */
1125 c2_= (k12*ic1_-k21*am2)/(1.0+dt2*k21);
1126 ic2_= ic2_last + dt2*(c2_+c2_last);
1127
1128 /* Compute C3(t) and its integral */
1129 c3_= ( k03*(1.0-k01*dt2/(1.0+dt2*a))*ictot
1130 -(b-k01*k03*dt2/(1.0+dt2*a))*am3
1131 +(k43/(1.0+dt2*k43))*am4
1132 -(k03/(1.0+dt2*a))*am1
1133 -(k03*k21*dt2/((1.0+dt2*a)*(1.0+dt2*k21)))*am2
1134 ) / ( 1.0+dt2*(b-k01*k03*dt2/(1.0+dt2*a)) );
1135 ic3_= ic3_last + dt2*(c3_+c3_last);
1136 /* Compute C4(t) and its integral */
1137 c4_= (k34*ic3_-k43*am4)/(1.0+dt2*k43);
1138 ic4_= ic4_last + dt2*(c4_+c4_last);
1139
1140 /* Compute the C0(t) */
1141 c0_=ctot[i]-c1_-c3_; /*if(c0_<0.0) return(-1);*/
1142 }
1143 /* Set output data */
1144 if(c0) c0[i]=c0_;
1145 if(c1) c1[i]=c1_;
1146 if(c3) c3[i]=c3_;
1147 /* Prepare for the next sample */
1148 c0_last=c0_; c1_last=c1_; c2_last=c2_; c3_last=c3_; c4_last=c4_;
1149 ic0_last=ic0_; ic1_last=ic1_; ic2_last=ic2_; ic3_last=ic3_; ic4_last=ic4_;
1150 ctot_last=ctot[i]; t_last=t[i];
1151 } /* next sample */
1152
1153 return(0);
1154}

◆ simMBF()

int simMBF ( double * t,
double * ci,
int nr,
double k1,
double k2,
double Vfit,
double * ct )
extern

Simulate myocardial tissue TAC using Iida's compartment model. Memory for ct must be allocated in the calling program. The units of rate constants must be related to the time unit; 1/min and min, or 1/sec and sec.

Returns
0 when successful, else a value >= 1.
See also
simC3s, simC3p, simC3vs, simC3vp, simC2l, simC2vl, simC3vpKLoss, simRTCM, simSRTM, simTRTM, simHuangmet, simTPCMOD0009c, simC1, simC3DIvs, simC4DIvp, simC4DIvs, simDispersion, simOxygen
Parameters
tArray of time values
ciInput activities
nrNumber of values in TACs
k1Apparent k1
k2Apparent k2
VfitVfit
ctPointer for TAC array to be simulated; must be allocated

Definition at line 1253 of file simulate.c.

1268 {
1269 int i;
1270 double dt2;
1271 double cii, ci_last, t_last;
1272 double ct_last, cti, cti_last;
1273
1274
1275 /* Check for data */
1276 if(nr<2) return(1);
1277 if(ct==NULL) return(2);
1278
1279 /* Calculate curves */
1280 t_last=0.0; cii=ci_last=0.0;
1281 cti=ct_last=cti_last=0.0;
1282 for(i=0; i<nr; i++) {
1283 /* delta time / 2 */
1284 dt2=0.5*(t[i]-t_last);
1285 /* calculate values */
1286 if(dt2<0.0) {
1287 return(5);
1288 } else if(dt2>0.0) {
1289 /* input integral */
1290 cii+=(ci[i]+ci_last)*dt2;
1291 /* Tissue compartment and its integral */
1292 ct[i] = (Vfit*ci[i] + k1*cii - k2*(cti_last+dt2*ct_last)) / (1.0 + dt2*k2);
1293 cti = cti_last + dt2*(ct_last+ct[i]);
1294 }
1295 /* set very small values to zero */
1296 if(fabs(ct[i])<1.0e-12) ct[i]=0.0;
1297 /* prepare to the next loop */
1298 t_last=t[i]; ci_last=ci[i];
1299 ct_last=ct[i]; cti_last=cti;
1300 }
1301 return(0);
1302}

◆ simOxygen()

int simOxygen ( double * t,
double * ca1,
double * ca2,
double * ca1i,
double * ca2i,
const int n,
const double k1a,
const double k2a,
const double km,
const double k1b,
const double k2b,
const double vb,
const double fa,
double * scpet,
double * sct1,
double * sct2,
double * sctab,
double * sctvb1,
double * sctvb2,
double * scvb1,
double * scvb2,
const int verbose )
extern

Simulate tissue and venous blood TACs using dual-input compartment model for [O-15]O2 (one tissue compartment for [O-15]O2, and another tissue compartment for its metabolite [O-15]H2O).

The units of rate constants must be related to the time unit of the data; 1/min and min, or 1/sec and sec.

Returns
Function returns 0 when successful, else a value >= 1.
Author
Vesa Oikonen
See also
simC3s, simC3p, simC3vs, simC3vp, simC2l, simC2vl, simC3vpKLoss, simRTCM, simSRTM, simTRTM, simHuangmet, simTPCMOD0009c, simMBF, simC1, simC3DIvs, simC4DIvp, simC4DIvs, simDispersion
Parameters
tArray of sample times
ca1Array of arterial blood activities of tracer1 ([O-15]O2)
ca2Array of arterial blood activities of tracer2 ([O-15]H2O)
ca1iArray of AUC 0-t of arterial tracer1 activities; NULL if not available
ca2iArray of AUC 0-t of arterial tracer2 activities; NULL if not available
nNr of samples (array lengths)
k1aRate constant of the model for tracer1 (from blood to C1)
k2aRate constant of the model for tracer1 (from C1 to blood)
kmRate constant of the model (from tracer1 in C1 to tracer2 in C2)
k1bRate constant of the model for tracer2 (from blood to C2)
k2bRate constant of the model for tracer2 (from C2 to blood)
vbVascular volume fraction [0-1)
faArterial fraction of vascular volume [0-1]
scpetPointer for TTAC array to be simulated; allocate in the calling program or set to NULL if not needed
sct1Simulated TAC of tracer1 in tissue; allocate in the calling program or set to NULL if not needed
sct2Simulated TAC of tracer2 in tissue; allocate in the calling program or set to NULL if not needed
sctabTotal arterial contribution to PET TTAC; allocate in the calling program or set to NULL if not needed
sctvb1Venous tracer1 contribution to PET TAC; allocate in the calling program or set to NULL if not needed
sctvb2Venous tarcer1 contribution to PET TAC; allocate in the calling program or set to NULL if not needed
scvb1Venous BTAC of tracer1; allocate in the calling program or set to NULL if not needed
scvb2Venous BTAC of tracer2; allocate in the calling program or set to NULL if not needed
verboseVerbose level; if zero, then nothing is printed into stdout or stderr

Definition at line 1978 of file simulate.c.

2029 {
2030 if(verbose>0) {
2031 printf("simOxygen()\n");
2032 if(verbose>1) {
2033 printf(" k1a := %g\n", k1a);
2034 printf(" k2a := %g\n", k2a);
2035 printf(" km := %g\n", km);
2036 printf(" k1b := %g\n", k1b);
2037 printf(" k2b := %g\n", k2b);
2038 printf(" vb := %g\n", vb);
2039 printf(" fa := %g\n", fa);
2040 printf(" n := %d\n", n);
2041 }
2042 }
2043
2044 /* Check for data */
2045 if(n<2) return 1;
2046 if(t==NULL) return 2;
2047 if(ca1==NULL || ca2==NULL) return 3;
2048
2049 /* Check parameters */
2050 if(k1a<0.0 || k1b<0.0 || k2a<0.0 || k2b<0.0) return(4);
2051 if(vb<0.0 || vb>=1.0) return(5);
2052 if(fa<0.0 || fa>1.0) return(6);
2053 double va=fa*vb; // arterial volume fraction in tissue
2054 double vv=(1.0-fa)*vb; // venous volume fraction in tissue
2055
2056 /* Set initial condition */
2057 double t_last=0.0; // previous sample time
2058 if(t[0]<t_last) t_last=t[0];
2059 /* Concentrations, integrals, and previous values are zero */
2060 double cba1i=0.0, cba1_last=0.0;
2061 double cba2i=0.0, cba2_last=0.0;
2062 double ct1=0.0, ct1_last=0.0, ct1i=0.0, ct1i_last=0.0;
2063 double ct2=0.0, ct2_last=0.0, ct2i=0.0, ct2i_last=0.0;
2064 double cvb1=0.0, cvb2=0.0;
2065
2066 /* Calculate curves */
2067 double p, q;
2068 double dt2; // delta t / 2
2069 for(int i=0; i<n; i++) {
2070 dt2=0.5*(t[i]-t_last);
2071 if(dt2>0.0) {
2072 /* arterial integrals */
2073 if(ca1i!=NULL) cba1i=ca1i[i]; else cba1i+=(ca1[i]+cba1_last)*dt2;
2074 if(ca2i!=NULL) cba2i=ca2i[i]; else cba2i+=(ca2[i]+cba2_last)*dt2;
2075 /* partial results */
2076 p=ct1i_last+dt2*ct1_last;
2077 q=ct2i_last+dt2*ct2_last;
2078 /* 1st tissue compartment and its integral */
2079 ct1 = (k1a*cba1i - (k2a+km)*p) / (1.0 + dt2*(k2a+km));
2080 ct1i = ct1i_last + dt2*(ct1_last+ct1);
2081 /* 2nd tissue compartment and its integral */
2082 ct2 = (km*ct1i + k1b*cba2i - k2b*q) / (1.0 + dt2*k2b);
2083 ct2i = ct2i_last + dt2*(ct2_last+ct2);
2084 }
2085 /* Venous BTACs */
2086 if(k1a>0.0 && k2a>0.0) cvb1=ct1/(k1a/k2a);
2087 else if(k2a>0.0) cvb1=0.0; else cvb1=ca1[i];
2088 if(k1b>0.0 && k2b>0.0) cvb2=ct2/(k1b/k2b);
2089 else if(k2b>0.0) cvb2=0.0; else cvb2=ca2[i];
2090 /* copy values to argument arrays; set very small values to zero */
2091 if(scpet!=NULL) {
2092 scpet[i]= va*(ca1[i]+ca2[i]) + vv*(cvb1+cvb2) + (1.0-vb)*(ct1+ct2);
2093 if(fabs(scpet[i])<1.0e-12) scpet[i]=0.0;
2094 }
2095 if(sct1!=NULL) {
2096 sct1[i]=(1.0-vb)*ct1;
2097 if(fabs(sct1[i])<1.0e-12) sct1[i]=0.0;
2098 }
2099 if(sct2!=NULL) {
2100 sct2[i]=(1.0-vb)*ct2;
2101 if(fabs(sct2[i])<1.0e-12) sct2[i]=0.0;
2102 }
2103 if(sctab!=NULL) {
2104 sctab[i]=va*(ca1[i]+ca2[i]);
2105 if(fabs(sctab[i])<1.0e-12) sctab[i]=0.0;
2106 }
2107 if(sctvb1!=NULL) {
2108 sctvb1[i]=vv*cvb1;
2109 if(fabs(sctvb1[i])<1.0e-12) sctvb1[i]=0.0;
2110 }
2111 if(sctvb2!=NULL) {
2112 sctvb2[i]=vv*cvb2;
2113 if(fabs(sctvb2[i])<1.0e-12) sctvb2[i]=0.0;
2114 }
2115 if(scvb1!=NULL) scvb1[i]=cvb1;
2116 if(scvb2!=NULL) scvb2[i]=cvb2;
2117 /* prepare for the next loop */
2118 t_last=t[i];
2119 cba1_last=ca1[i]; cba2_last=ca2[i];
2120 ct1_last=ct1; ct1i_last=ct1i;
2121 ct2_last=ct2; ct2i_last=ct2i;
2122 } // next sample
2123
2124 if(verbose>2) {
2125 printf("AUC 0-%g:\n", t_last);
2126 printf(" cba1i := %g\n", cba1i);
2127 printf(" cba2i := %g\n", cba2i);
2128 printf(" ct1i := %g\n", ct1i_last);
2129 printf(" ct2i := %g\n", ct2i_last);
2130 }
2131
2132 return 0;
2133}

◆ simplex()

double simplex ( double(* _fun )(double *),
int parNr,
double * par,
double * delta,
double maxerr,
int maxiter,
int verbose )
extern

Downhill simplex function minimization routine.

Note that if any constraints are required for the parameter values they must be set in the function.

Returns
Function returns the least calculated value of func.
See also
powell, tgo, bobyqa, nlopt1D
Parameters
_funPointer to the function to be minimized. It must be defined in main program as: double func(double *p); where p is the parameter array.
parNrThe number of unknown parameters
parThis double array contains the minimized parameters. Initial values must be set.
deltaThis double array contains the initial changes to parameters. To fix a parameter, set the corresponding delta to 0.
maxerrMaximal error allowed (stopping rule #1)
maxiterMaximal nr of iterations allowed (stopping rule #2)
verboseVerbose level; if zero, then only warnings are printed into stderr

Definition at line 27 of file simplex.c.

45 {
46 int i, j, Meas, it;
47 double Max, Min, Max2, Min2, LastChi;
48 int NextBest, New2, Best;
49
50
51 if(verbose>0) printf("%s(func, %d, p[], delta[], %g, %d)\n", __func__, parNr, maxerr, maxiter);
52 /* SetUp */
53 _simplexFunc=_fun;
54 _simplexParNr=parNr; it=0; NewPnt=_simplexParNr+1;
55 for(i=0; i<_simplexParNr; i++) for(Meas=0; Meas<_simplexParNr+3; Meas++) _simplexP[Meas][i]=par[i];
56 if(verbose>1) {
57 for(int i=0; i<_simplexParNr; i++) printf("%12g %12g\n", _simplexP[0][i], delta[i]);
58 printf("ChiSqr of guesses: %f\n", (*_simplexFunc)(_simplexP[0]));
59 }
60 New2=NewPnt+1;
61 for(Meas=0; Meas<=_simplexParNr; Meas++) {
62 it++;
63 _simplexR[Meas] = (*_simplexFunc)(_simplexP[Meas]);
64 for (i=0; i<_simplexParNr; i++) {
65 if(i==Meas) delta[i]= -delta[i];
66 _simplexP[Meas+1][i] = _simplexP[Meas][i] + delta[i];
67 }
68 }
69
70 /* Simplex minimization */
71 LastChi = 1.0E30; NextBest=Best=0;
72 do {
73 for(j=0; j<100; j++) {
74 /* Find the max and min response measured */
75 Max=0.; Min=1.0E30;
76 for (i=0; i<=_simplexParNr; i++) {
77 if(_simplexR[i] > Max) {Max=_simplexR[i]; Worst=i;}
78 if(_simplexR[i] < Min) {Min=_simplexR[i]; Best=i; }
79 }
80 /* Find 2nd best and 2nd worst, too */
81 Max2=0.; Min2=1.0E30;
82 for (i=0; i<=_simplexParNr; i++) {
83 if((_simplexR[i] > Max2) && (_simplexR[i] < Max)) Max2=_simplexR[i];
84 if((_simplexR[i] < Min2) && (_simplexR[i] > Min)) {
85 Min2=_simplexR[i]; NextBest=i;}
86 }
87 /* Calculate centroid of all measurements */
88 for(i=0; i<_simplexParNr; i++) {
89 _simplexC[i]=0.;
90 for(Meas=0; Meas<=_simplexParNr; Meas++)
91 if(Meas!=Worst) _simplexC[i]+=_simplexP[Meas][i];
92 _simplexC[i]/=(double)_simplexParNr;
93 }
94 /* Measure the response at the point reflected away from worst */
95 for(i=0; i<_simplexParNr; i++)
96 _simplexP[NewPnt][i] = 2.*_simplexC[i] - _simplexP[Worst][i];
97 _simplexR[NewPnt]= (*_simplexFunc)(_simplexP[NewPnt]);
98 it++;
99 /* If this one is better than previous best, then expand in this
100 direction */
101 if(_simplexR[NewPnt] < _simplexR[Best]) {
102 _simplexGenNew(New2,2.0); it++;
103 } else {
104 /* If this one is worse than previous worst, measure point halfway
105 between worst and centroid */
106 if(_simplexR[NewPnt] > _simplexR[Worst]) {
107 _simplexGenNew(New2,-0.5); it++;
108 } else {
109 /* If newest response is worse than next best point
110 but better than worst, measure response halfway
111 between centroid and newest point */
112 if((_simplexR[NextBest] < _simplexR[NewPnt]) &&
113 (_simplexR[NewPnt] < _simplexR[Worst])) {
114 _simplexGenNew(New2,0.5); it++;
115 } else {
116 /* If none of the above, keep the new point as best */
117 for(i=0; i<_simplexParNr; i++)
118 _simplexP[Worst][i] = _simplexP[NewPnt][i];
119 _simplexR[Worst] = _simplexR[NewPnt];
120 }
121 }
122 }
123 }
124 if(verbose>1) printf(" it=%i; ChiSqr=%f\n", it, _simplexR[Best]);
125 if(verbose>2)
126 for(i=0; i<_simplexParNr; i++) printf(" %12g\n", _simplexP[Best][i]);
127 /* Check if fitting is not proceeding */
128 if(_simplexR[Best] == LastChi) {
129 for(i=0; i<_simplexParNr; i++) par[i]=_simplexP[Best][i];
130 return _simplexR[Best];
131 }
132 LastChi = _simplexR[Best];
133 } while ((_simplexR[Best]>maxerr) && (it<=maxiter));
134
135 for(i=0; i<_simplexParNr; i++) par[i]=_simplexP[Best][i];
136 return _simplexR[Best];
137}

◆ simRTCM()

int simRTCM ( double * t,
double * cr,
int nr,
double R1,
double k2,
double k3,
double k4,
double * ct,
double * cta,
double * ctb )
extern

Simulates tissue TAC using reference tissue compartment model (original) and reference region TAC, at reference region TAC times.

Memory for ct must be allocated in the calling program. To retrieve the separate tissue compartment TACs, pointer to allocated memory for cf and/or cb can be given; if compartmental TACs are not required, NULL pointer can be given instead.

The units of rate constants must be related to the time unit; 1/min and min, or 1/sec and sec.

Returns
Function returns 0 when successful, else a value >= 1.
See also
simC3s, simC3p, simC3vs, simC3vp, simC2l, simC2vl, simC3vpKLoss, simSRTM, simTRTM, simHuangmet, simTPCMOD0009c, simMBF, simC1, simC3DIvs, simC4DIvp, simC4DIvs, simDispersion, simOxygen
Parameters
tArray of time values
crReference region activities
nrNumber of values in TACs
R1Ratio K1/K1'
k2Rate constant of the model
k3Rate constant of the model
k4Rate constant of the model
ctPointer for TAC array to be simulated; must be allocated
ctaPointer for 1st compartment TAC to be simulated, or NULL
ctbPointer for 2nd compartment TAC to be simulated, or NULL

Definition at line 835 of file simulate.c.

856 {
857 int i;
858 double f, b, w, dt2;
859 double cri, cr_last, t_last;
860 double cf, cf_last, cb, cb_last;
861 double cfi, cfi_last, cbi, cbi_last;
862
863
864 /* Check for data */
865 if(nr<2) return 1;
866 if(ct==NULL) return 2;
867
868 /* Calculate curves */
869 t_last=0.0; if(t[0]<t_last) t_last=t[0];
870 cri=cr_last=0.0; cf_last=cb_last=cfi_last=cbi_last=cf=cb=cfi=cbi=0.0;
871 for(i=0; i<nr; i++) {
872 /* delta time / 2 */
873 dt2=0.5*(t[i]-t_last);
874 /* calculate values */
875 if(dt2<0.0) {
876 return 5;
877 } else if(dt2>0.0) {
878 /* reference integral */
879 cri+=(cr[i]+cr_last)*dt2;
880 /* partial results */
881 f=cfi_last+dt2*cf_last;
882 b=cbi_last+dt2*cb_last;
883 w=k2 + k3 + k2*k4*dt2;
884 /* 1st tissue compartment and its integral */
885 cf = ( (1.0 + k4*dt2)*(R1*cr[i] + k2*cri) + k4*b - w*f ) /
886 ( 1.0 + dt2*(w+k4) );
887 cfi = cfi_last + dt2*(cf_last+cf);
888 /* 2nd tissue compartment and its integral */
889 cb = (k3*cfi - k4*b) / (1.0 + k4*dt2);
890 cbi = cbi_last + dt2*(cb_last+cb);
891 }
892 /* copy values to argument arrays; set very small values to zero */
893 ct[i]=cf+cb; if(fabs(ct[i])<1.0e-12) ct[i]=0.0;
894 if(cta!=NULL) {cta[i]=cf; if(fabs(cta[i])<1.0e-12) cta[i]=0.0;}
895 if(ctb!=NULL) {ctb[i]=cb; if(fabs(ctb[i])<1.0e-12) ctb[i]=0.0;}
896 /* prepare to the next loop */
897 t_last=t[i]; cr_last=cr[i];
898 cf_last=cf; cfi_last=cfi;
899 cb_last=cb; cbi_last=cbi;
900 }
901
902 return 0;
903}

◆ simSRTM()

int simSRTM ( double * t,
double * cr,
int nr,
double R1,
double k2,
double BP,
double * ct )
extern

Simulates tissue TAC using reference tissue compartment model (simplified) and reference region TAC, at reference region TAC times.

Memory for ct must be allocated in the calling program.

The units of rate constants must be related to the time unit; 1/min and min, or 1/sec and sec.

Returns
Function returns 0 when successful, else a value >= 1.
See also
simC3s, simC3p, simC3vs, simC3vp, simC2l, simC2vl, simC3vpKLoss, simRTCM, simTRTM, simHuangmet, simTPCMOD0009c, simMBF, simC1, simC3DIvs, simC4DIvp, simC4DIvs, simDispersion, simOxygen
Parameters
tArray of time values
crReference region activities
nrNumber of values in TACs
R1Ratio K1/K1'
k2Rate constant of the model
BPBinding potential
ctPointer for TAC array to be simulated; must be allocated

Definition at line 919 of file simulate.c.

934 {
935 int i;
936 double dt2;
937 double cri, cr_last, t_last;
938 double ct_last, cti, cti_last;
939
940
941 /* Check for data */
942 if(nr<2) return 1;
943 if(ct==NULL) return 2;
944
945 /* Calculate curves */
946 t_last=0.0; if(t[0]<t_last) t_last=t[0];
947 cri=cr_last=0.0; cti=ct_last=cti_last=0.0;
948 for(i=0; i<nr; i++) {
949 /* delta time / 2 */
950 dt2=0.5*(t[i]-t_last);
951 /* calculate values */
952 if(dt2<0.0) {
953 return 5;
954 } else if(dt2>0.0) {
955 /* reference integral */
956 cri+=(cr[i]+cr_last)*dt2;
957 /* Tissue compartment and its integral */
958 ct[i] = ( R1*cr[i] + k2*cri - (k2/(1.0+BP))*(cti_last+dt2*ct_last) ) /
959 ( 1.0 + dt2*(k2/(1.0+BP)) );
960 cti = cti_last + dt2*(ct_last+ct[i]);
961 }
962 /* set invalid or very small values to zero */
963 if(!(fabs(ct[i])>=1.0e-12)) ct[i]=0.0;
964 /* prepare to the next loop */
965 t_last=t[i]; cr_last=cr[i];
966 ct_last=ct[i]; cti_last=cti;
967 }
968
969 return 0;
970}

◆ simTPCMOD0009c()

int simTPCMOD0009c ( double * t,
double * ctot,
int nr,
double km,
double k1m,
double k2m,
double k3m,
double k4m,
double * ca,
double * cm )
extern

Simulate parent tracer TAC using plasma metabolite model TPCMOD0009C, https://www.turkupetcentre.net/reports/tpcmod0009_app_c.pdf

Returns
Returns 0 if successful.
See also
simC3s, simC3p, simC3vs, simC3vp, simC2l, simC2vl, simC3vpKLoss, simRTCM, simSRTM, simTRTM, simHuangmet, simMBF, simC1, simC3DIvs, simC4DIvp, simC4DIvs, simDispersion, simOxygen
Parameters
tSample times
ctotTotal plasma TAC
nrSample number
kmkm
k1mk1m
k2mk2m
k3mk3m
k4mk4m
caPointer to array where parent tracer TAC will be written; NULL, if not needed.
cmPointer to array where metabolized tracer TAC will be written; NULL, if not needed.

Definition at line 1165 of file simulate.c.

1186 {
1187 int i;
1188 double t_last, dt2;
1189 double ctoti, ctot_last;
1190 double a, b;
1191 double ct1m, ct1mi, ct1m_last, ct1mi_last;
1192 double ct2m, ct2mi, ct2m_last, ct2mi_last;
1193 double cpm, cpmi, cpm_last, cpmi_last;
1194
1195
1196 /* Check for data */
1197 if(nr<2) return 1;
1198 if(t==NULL || ctot==NULL || ca==NULL) return 2;
1199
1200 /* Calculate curves */
1201 t_last=0.0; if(t[0]<t_last) t_last=t[0];
1202 ctoti=ctot_last=0.0;
1203 ct1m_last=ct1mi_last=ct2m_last=ct2mi_last=cpm_last=cpmi_last=0.0;
1204 //ct1=ct2=ct3=ct1i=ct2i=ct3i=0.0;
1205 for(i=0; i<nr; i++) {
1206 /* delta time / 2 */
1207 dt2=0.5*(t[i]-t_last);
1208 /* calculate values */
1209 if(dt2<0.0) {
1210 return 5;
1211 } else {
1212 /* arterial integral */
1213 ctoti+=(ctot[i]+ctot_last)*dt2;
1214 /* partial results */
1215 a=k4m/(1.0+k4m*dt2);
1216 b=(k1m-km)/(1.0+dt2*(k1m+k3m-k3m*a*dt2));
1217 /* 1st tissue compartment and its integral */
1218 ct1m = (km*ctoti - k2m*(1.0-dt2*b)*(ct1mi_last+dt2*ct1m_last)
1219 + b*(cpmi_last+dt2*cpm_last) + a*b*dt2*(ct2mi_last+dt2*ct2m_last)
1220 ) / (1.0 + dt2*k2m*(1.0-dt2*b));
1221 ct1mi = ct1mi_last + dt2*(ct1m_last+ct1m);
1222 /* Metabolite plasma compartment and its integral */
1223 cpm = (k2m*ct1mi + a*(ct2mi_last+dt2*ct2m_last)
1224 - (k1m+k3m-k3m*dt2*a)*(cpmi_last+dt2*cpm_last)
1225 ) / (1.0 + dt2*(k1m+k3m-k3m*dt2*a));
1226 cpmi = cpmi_last + dt2*(cpm_last+cpm);
1227 /* 2nd tissue compartment and its integral */
1228 ct2m = (k3m*cpmi - k4m*(ct2mi_last+dt2*ct2m_last)) / (1.0 + dt2*k4m);
1229 ct2mi = ct2mi_last + dt2*(ct2m_last+ct2m);
1230 }
1231 /* copy values to argument arrays; set very small values to zero */
1232 if(ca!=NULL) {ca[i]=ctot[i]-cpm; if(fabs(ca[i])<1.0e-12) ca[i]=0.0;}
1233 if(cm!=NULL) {cm[i]=cpm; if(fabs(cm[i])<1.0e-12) cm[i]=0.0;}
1234 /* prepare to the next loop */
1235 t_last=t[i]; ctot_last=ctot[i];
1236 ct1m_last=ct1m; ct1mi_last=ct1mi;
1237 ct2m_last=ct2m; ct2mi_last=ct2mi;
1238 cpm_last=cpm; cpmi_last=cpmi;
1239 } // next sample
1240 return 0;
1241}

◆ simTRTM()

int simTRTM ( double * t,
double * cr,
int nr,
double R1,
double k2,
double k3,
double * ct )
extern

Simulates tissue TAC using reference tissue compartment model (transport limited in ref region) and reference region TAC, at reference region TAC times.

Memory for ct must be allocated in the calling program.

The units of rate constants must be related to the time unit; 1/min and min, or 1/sec and sec.

Returns
Function returns 0 when successful, else a value >= 1.
See also
simC3s, simC3p, simC3vs, simC3vp, simC2l, simC2vl, simC3vpKLoss, simRTCM, simSRTM, simHuangmet, simTPCMOD0009c, simMBF, simC1, simC3DIvs, simC4DIvp, simC4DIvs, simDispersion, simOxygen
Parameters
tArray of time values
crReference region activities
nrNumber of values in TACs
R1Ratio K1/K1'
k2Rate constant of the model
k3Rate constant of the model
ctPointer for TAC array to be simulated; must be allocated

Definition at line 986 of file simulate.c.

1001 {
1002 int i;
1003 double dt2;
1004 double cri, cr_last, t_last;
1005 double ct_last, cti, cti_last;
1006
1007
1008 /* Check for data */
1009 if(nr<2) return 1;
1010 if(ct==NULL) return 2;
1011
1012 /* Calculate curves */
1013 t_last=0.0; if(t[0]<t_last) t_last=t[0];
1014 cri=cr_last=0.0; cti=ct_last=cti_last=0.0;
1015 for(i=0; i<nr; i++) {
1016 /* delta time / 2 */
1017 dt2=0.5*(t[i]-t_last);
1018 /* calculate values */
1019 if(dt2<0.0) {
1020 return 5;
1021 } else if(dt2>0.0) {
1022 /* reference integral */
1023 cri+=(cr[i]+cr_last)*dt2;
1024 /* Tissue compartment and its integral */
1025 ct[i] = ( R1*cr[i] + R1*k3*cri - (k2+k3)*(cti_last+dt2*ct_last) ) /
1026 ( 1.0 + dt2*(k2+k3) );
1027 cti = cti_last + dt2*(ct_last+ct[i]);
1028 }
1029 /* set very small values to zero */
1030 if(fabs(ct[i])<1.0e-12) ct[i]=0.0;
1031 /* prepare to the next loop */
1032 t_last=t[i]; cr_last=cr[i];
1033 ct_last=ct[i]; cti_last=cti;
1034 }
1035
1036 return 0;
1037}

◆ tgo()

int tgo ( double * lowlim,
double * uplim,
double(* objf )(int, double *, void *),
void * objfData,
int dim,
int neighNr,
double * fmin,
double * gmin,
int samNr,
int tgoNr,
int verbose )
extern

Topographical minimization algorithm, that searches the global minimum of a function using clusterization. Calls a local minimization algorithm. Based on an algorithm by Aimo Torn and Sami Viitanen.

Returns
Returns 0, if ok.
See also
tgoRandomParameters, powell, simplex, bobyqa, nlopt1D
Parameters
lowlimLower limits for the parameters.
uplimUpper limits for the parameters.
objfThe object function.
objfDataData to objective function; NULL if not needed.
dimDimension = nr of parameters.
neighNrNr of neighbours to investigate; enter large nr relative to samNr (below) if only few local minima are expected.
fminFunction value at global minimum.
gminGlobal minimum = parameter estimates.
samNrNr of points to sample in one iteration; enter larger samNr if nr of iterations (below) is small.
tgoNrNr of TGO iterations; enter 0 to use the default; enter 1 to run TGO just once ie TGO instead of iTGO. Large iteration nr is needed if samNr (above) would otherwise require too much memory.
verboseVerbose level; if zero, then nothing is printed into stdout or stderr.

Definition at line 39 of file tgo.c.

66 {
67 int i, j, k, l, IDmin, itNr, samplNr, topoNr, badNr, nevals=0, ret;
68 double *delta, temp, min, *tempp, deltaf, tol;
69 TGO_POINT *sampled_points;
70 int fixed_n, fitted_n;
71
72
73 if(verbose>0) {printf("in tgo()\n"); fflush(stdout);}
74 if(TGO_LOCAL_OPT==1) {
75 if(verbose>0) printf("local optimization routine: bobyqa\n");
76 } else {
77 if(verbose>0) printf("local optimization routine: powell\n");
78 }
79
80 /* Check input */
81 if(lowlim==NULL || uplim==NULL || objf==NULL || dim<=0) return(1);
82 if(fmin==NULL || gmin==NULL) return(1);
83
84 /* Check if any of parameters is fixed */
85 for(i=0, fixed_n=0; i<dim; i++) if(uplim[i]<=lowlim[i]) fixed_n++;
86 fitted_n=dim-fixed_n;
87 if(verbose>1) printf("%d parameter(s) are fixed.\n", fixed_n);
88 if(fitted_n<1) return(1);
89
90 /* Continue input checking */
91 if(samNr<=0) samplNr=TGO_SAMPLNR; else samplNr=samNr;
92 if(samplNr&1) samplNr++; // If number is odd, then add 1
93 if(neighNr>samplNr-1) neighNr=samplNr-1; // Make sure "neighNr" isn't too big
94 if(tgoNr<1) tgoNr=fitted_n; // Set TGO iteration number, if not set by user
95 if(verbose>1) {
96 printf("samplNr := %d\n", samplNr);
97 printf("neighNr := %d\n", neighNr);
98 printf("tgoNr := %d\n", tgoNr);
99 if(verbose>2) {
100 printf("iTGO limits: [%g,%g]", lowlim[0], uplim[0]);
101 for(i=1; i<dim; i++) printf(" [%g,%g]", lowlim[i], uplim[i]);
102 printf("\n");
103 }
104#ifdef OMP_NUM_THREADS
105 printf("OMP_NUM_THREADS := %d\n", OMP_NUM_THREADS);
106#endif
107 fflush(stdout);
108 }
109
110 /* Allocate memory */
111 sampled_points=(TGO_POINT*)calloc(samplNr, sizeof(TGO_POINT));
112 if(sampled_points==NULL) return(2);
113 for(i=0; i<samplNr; i++) {
114 sampled_points[i].topomin=0;
115 sampled_points[i].fvalue=0.0;
116 }
117 delta=(double*)malloc(dim*sizeof(double));
118 tempp=(double*)malloc(samplNr*sizeof(double));
119 if(delta==NULL || tempp==NULL) {free(sampled_points); return(2);}
120
121 /* Set seed for random number generator */
122 drandSeed(1);
123
124 /*
125 * Iterative TGO, or non-iterative if tgoNr==1
126 */
127 for(l=0; l<tgoNr; l++) {
128
129 if(verbose>2) {printf("TGO Loop # %d: \n", l+1); fflush(stdout);}
130
131 /*
132 * Sample N points in the feasible region and compute the object function
133 * values for those points which do not already have it.
134 */
135 if(TGO_SQUARED_TRANSF==1)
136 tgoRandomParametersST(sampled_points, dim, samplNr, lowlim, uplim);
137 else
138 tgoRandomParameters(sampled_points, dim, samplNr, lowlim, uplim);
139 badNr=0;
140 for(i=0; i<samplNr; i++) if(sampled_points[i].topomin==0) {
141 sampled_points[i].fvalue=objf(dim, sampled_points[i].par, objfData);
142 /* If function return value was not normal then we'll try
143 later (twice) with new guesses */
144 if(!isfinite(sampled_points[i].fvalue)) {
145 badNr++;
146 if(verbose>5) {
147 printf("this point did not give normal return value:\n");
148 for(k=0; k<dim; k++) printf(" %10.2e", sampled_points[i].par[k]);
149 printf("\n");
150 }
151 }
152 }
153 if(verbose>4 && badNr>0) printf("Nr of bad points: %d\n", badNr);
154 /* New guesses for bad points */
155 k=0; while(k<2 && badNr>0) {
156 badNr=0; k++;
157 for(i=0; i<samplNr; i++)
158 if(sampled_points[i].topomin==0 && !isfinite(sampled_points[i].fvalue)) {
159 /* sample a new random point */
160 if(TGO_SQUARED_TRANSF==1)
161 tgoRandomParametersST(sampled_points+i, dim, 1, lowlim, uplim);
162 else
163 tgoRandomParameters(sampled_points+i, dim, 1, lowlim, uplim);
164 /* compute the object function value for that */
165 sampled_points[i].fvalue=objf(dim, sampled_points[i].par, objfData);
166 if(!isfinite(sampled_points[i].fvalue)) badNr++;
167 }
168 if(verbose>4 && badNr>0) printf("Nr of bad points: %d\n", badNr);
169 }
170 /* Print sampled points */
171 if(verbose>6) {
172 printf("Sampled points:\n");
173 for(j=0; j<samplNr; j++) {
174 printf("%d", j+1);
175 for(i=0; i<dim; i++) printf(" %e ", sampled_points[j].par[i]);
176 printf("=>%e\n", sampled_points[j].fvalue);
177 }
178 fflush(stdout);
179 }
180 /* Object functions values must be good for at least NeigNr points */
181 if(l==0 && (samplNr-badNr)<=neighNr) {
182 if(verbose>0) {
183 printf("Error in TGO: invalid function return value from all points.\n");
184 fflush(stdout);
185 }
186 free(sampled_points); free(delta); free(tempp);
187 return(3);
188 }
189
190 /*
191 * For each point i find out if it is a "topografic minimum"
192 * = better than k neighbour points
193 */
194 /* Save the distances to point i in the vector tempp */
195 /* Find the closest neighbour from {x1,..,xn}/{xi} k times, */
196 /* extracting it after comparing */
197 for(i=0, topoNr=0; i<samplNr; i++) {
198 sampled_points[i].topomin=0;
199 /* If function value is not ok, then point cannot be minimum */
200 if(!isfinite(sampled_points[i].fvalue)) continue;
201
202 /* Compute the (scaled) distances */
203 for(j=0; j<samplNr; j++) {
204 tempp[j]=1.0E+99;
205 if(i!=j) {
206 for(k=0, tempp[j]=0.0; k<dim; k++) {
207 deltaf=uplim[k]-lowlim[k]; if(deltaf<=0.0) continue;
208 temp=sampled_points[i].par[k]-sampled_points[j].par[k];
209 if(deltaf>1.0E-20) temp/=deltaf;
210 if(isfinite(temp)) tempp[j] += temp*temp;
211 }
212 /* Distance is computed as square root, but it does not affect
213 the order of distances, and sqrt() is relatively slow */
214 /*tempp=sqrt(tempp);*/
215 }
216 }
217
218 /* Find the closest neighbours */
219 /* At the same time, collect info for max fvalue of the neighbours
220 and for the mean distance to every direction */
221 for(k=0; k<dim; k++) sampled_points[i].delta[k]=0.0; // Init delta array
222 sampled_points[i].fvalrange=sampled_points[i].fvalue;
223 for(j=0; j<neighNr; j++) {
224 min=tempp[0]; IDmin=0;
225 for(k=1; k<samplNr; k++) {if(tempp[k]<min) {min=tempp[k]; IDmin=k;}}
226 tempp[IDmin]=1e+99; // so that this will not be used again
227 /* If point i is worse than any of the closest neighbours, then
228 point i is not a topographic minimum; then stop this loop and go to
229 the next point i+1 */
230 if(isfinite(sampled_points[IDmin].fvalue) &&
231 sampled_points[IDmin].fvalue<sampled_points[i].fvalue) break;
232
233 /* Sum the distances to every direction for delta calculation */
234 for(k=0; k<dim; k++)
235 sampled_points[i].delta[k]+=
236 fabs(sampled_points[i].par[k]-sampled_points[IDmin].par[k]);
237 if(isfinite(sampled_points[IDmin].fvalue) &&
238 sampled_points[IDmin].fvalue>sampled_points[i].fvalrange)
239 sampled_points[i].fvalrange=sampled_points[IDmin].fvalue;
240 } // next neighbour point
241
242 /* If this was NOT a topographic minimum, then continue with the next i */
243 if(j!=neighNr) continue;
244 /* otherwise mark this as topografic minimum (TM) */
245 sampled_points[i].topomin=1; topoNr++;
246
247 /* Compute the mean distance of neighbours from the TM in each
248 dimension; local optimization delta will be based on that */
249 for(k=0; k<dim; k++) sampled_points[i].delta[k]/=(double)neighNr;
250 /* Compute the max range in fvalues */
251 sampled_points[i].fvalrange-=sampled_points[i].fvalue;
252
253 } /* next sample */
254 if(verbose>2) {printf(" %d topographical minima\n", topoNr); fflush(stdout);}
255
256 /* Check that if no topographical minimum was found, then set the smallest */
257 /* minimum as 'topographical' minimum */
258 if(topoNr==0) {
259 min=sampled_points[0].fvalue; IDmin=0;
260 for(k=1; k<samplNr; k++)
261 if(!isfinite(min) || sampled_points[k].fvalue<min) {
262 min=sampled_points[k].fvalue; IDmin=k;}
263 sampled_points[IDmin].topomin=1;
264 for(k=0; k<dim; k++)
265 sampled_points[IDmin].delta[k]=0.1*(uplim[k]-lowlim[k]);
266 sampled_points[i].fvalrange+=100.0*fabs(sampled_points[i].fvalue);
267 if(verbose>2) {
268 printf(" ; therefore minimum was set to point %d at %e\n",
269 IDmin, sampled_points[IDmin].fvalue);
270 fflush(stdout);
271 }
272 topoNr=1;
273 }
274 if(verbose>3) { // Print the best TM
275 for(i=0, min=1e+99, IDmin=0; i<samplNr; i++)
276 if(sampled_points[i].topomin==1) {
277 if(isfinite(sampled_points[i].fvalue) && sampled_points[i].fvalue<min)
278 {
279 min=sampled_points[i].fvalue; IDmin=i;
280 }
281 }
282 printf(" best topographical min:"); fflush(stdout);
283 for(k=0; k<dim; k++) printf(" %e", sampled_points[IDmin].par[k]);
284 printf(" => %e\n", sampled_points[IDmin].fvalue); fflush(stdout);
285 }
286
287 if(TGO_LOCAL_INSIDE==1) {
288 /* Local optimization for each TM */
289 if(verbose>2) printf("local optimization for each TM\n");
290 for(i=0; i<samplNr; i++) if(sampled_points[i].topomin==1) {
291 //tol=sampled_points[IDmin].fvalue*1.0E-02;
292 //for(k=0; k<dim; k++) delta[k]=sampled_points[i].delta[k];
293 for(k=0; k<dim; k++) delta[k]=0.1*sampled_points[i].delta[k];
294 if(verbose>3) printf("point %d: original fvalue=%.2e\n",
295 i+1, sampled_points[i].fvalue);
296 if(TGO_LOCAL_OPT==1) {
297 tol=1.0E-08; //tol=1.0E-09;
298 ret=bobyqa(dim, 0, sampled_points[i].par, lowlim, uplim, delta, 0.0, 1.0E-03,
299 1.0E-10, tol, tol, 2000, &nevals,
300 &sampled_points[i].fvalue, objf, objfData, NULL, verbose-3);
301 if(ret<0 && verbose>0) {
302 printf("bobyqa error %d\n", ret); fflush(stdout);}
303 if(ret<0 && ret!=BOBYQA_ROUNDOFF_LIMITED) {
304 free(sampled_points); free(delta); free(tempp);
305 return(5);
306 }
307 if(verbose>3) {
308 printf(" local opt => %.2e (nr of evals=%d)\n",
309 sampled_points[i].fvalue, nevals);
310 fflush(stdout);
311 }
312 } else {
313 itNr=40; //itNr=100;
314 tol=1.0E-03; //tol=2.0E-03; //tol=1.0E-09;
315 POWELL_LINMIN_MAXIT=30; // 100;
316 ret=powell(sampled_points[i].par, delta, dim, tol, &itNr,
317 &sampled_points[i].fvalue, objf, objfData, verbose-3);
318 if(ret>1 && verbose>0) {printf("powell error %d\n", ret); fflush(stdout);}
319 if(ret>3) {
320 free(sampled_points); free(delta); free(tempp);
321 return(5);
322 }
323 if(verbose>3) {
324 printf(" local opt => %.2e (itNr=%d)\n",
325 sampled_points[i].fvalue, itNr);
326 fflush(stdout);
327 }
328 }
329 }
330 } // end of local optimizations inside this iTGO loop
331
332 } /* end of tgo iterations */
333
334 if(verbose>1) { // Print the final topographical minima
335 if(verbose>2) printf("Final topographical minima and deltas\n");
336 else printf("Final topographical minima\n");
337 for(i=0; i<samplNr; i++) if(sampled_points[i].topomin==1) {
338 k=0; printf(" %3d: %.2e", i, sampled_points[i].par[k]);
339 for(k=1; k<dim; k++) printf(" %.2e", sampled_points[i].par[k]);
340 printf(" => %.2e\n", sampled_points[i].fvalue); fflush(stdout);
341 if(verbose>2) {
342 k=0; printf(" %.2e", sampled_points[i].delta[k]);
343 for(k=1; k<dim; k++) printf(" %.2e", sampled_points[i].delta[k]);
344 printf(" => %.2e\n", sampled_points[i].fvalrange); fflush(stdout);
345 }
346 }
347 }
348
349 if(TGO_LOCAL_INSIDE==0) {
350 /*
351 * Use the points in TM as starting points for local optimization;
352 * this first local opt is done only if not done already inside iTGO
353 */
354 if(verbose>2) {printf("Topographic minima:\n"); fflush(stdout);}
355 for(i=0; i<samplNr; i++) if(sampled_points[i].topomin==1) {
356 //tol=sampled_points[IDmin].fvalue*1.0E-02;
357 for(k=0; k<dim; k++) {
358 if(verbose>2) {printf("%e ", sampled_points[i].par[k]); fflush(stdout);}
359 delta[k]=0.1*sampled_points[i].delta[k];
360 }
361 if(verbose>3) {printf("=> %e ", sampled_points[i].fvalue); fflush(stdout);}
362 if(TGO_LOCAL_OPT==1) {
363 tol=1.0E-09; //tol=1.0E-09;
364 ret=bobyqa(dim, 0, sampled_points[i].par, lowlim, uplim, delta, 0.0, 1.0E-03,
365 1.0E-10, tol, tol, 2000, &nevals,
366 &sampled_points[i].fvalue, objf, objfData, NULL, verbose-3);
367 if(ret<0 && verbose>0) {
368 printf("bobyqa error %d\n", ret); fflush(stdout);}
369 if(ret<0 && ret!=BOBYQA_ROUNDOFF_LIMITED) {
370 free(sampled_points); free(delta); free(tempp);
371 return(5);
372 }
373 if(verbose>2) {
374 printf("local opt 1st round point %d => %e (nr of evals=%d)\n",
375 i+1, sampled_points[i].fvalue, nevals);
376 fflush(stdout);
377 }
378 } else {
379 itNr=50; //itNr=100;
380 tol=1.0E-03; //tol=1.0E-04;
381 POWELL_LINMIN_MAXIT=60; // POWELL_LINMIN_MAXIT=50; // 100;
382 ret=powell(sampled_points[i].par, delta, dim, tol, &itNr,
383 &sampled_points[i].fvalue, objf, objfData, verbose-3);
384 if(ret>1 && verbose>0) {printf("powell error %d\n", ret); fflush(stdout);}
385 if(ret>3) {
386 if(verbose>0) {printf("powell error %d\n", ret); fflush(stdout);}
387 free(sampled_points); free(delta); free(tempp);
388 return(5);
389 }
390 if(verbose>2) {
391 printf("=> %e (itNr=%d) ", sampled_points[i].fvalue, itNr);
392 fflush(stdout);
393 }
394 }
395 }
396 if(verbose>0) { // Print the topographical minima after local optimization
397 printf("Final topographical minima after local optimization\n");
398 for(i=0; i<samplNr; i++) if(sampled_points[i].topomin==1) {
399 k=0; printf(" %3d: %.2e", i, sampled_points[i].par[k]);
400 for(k=1; k<dim; k++) printf(" %.2e", sampled_points[i].par[k]);
401 printf(" => %.2e\n", sampled_points[i].fvalue); fflush(stdout);
402 }
403 }
404 }
405
406 /* Rerun of local optimization with smaller tolerance and delta */
407 for(i=0; i<samplNr; i++) if(sampled_points[i].topomin==1) {
408 //tol=sampled_points[IDmin].fvalue*1.0E-04;
409 for(k=0; k<dim; k++) delta[k]=0.1*sampled_points[i].delta[k];
410 if(TGO_LOCAL_OPT==1) {
411 tol=1.0E-10;
412 ret=bobyqa(dim, 0, sampled_points[i].par, lowlim, uplim, delta, 0.0, 1.0E-05,
413 1.0E-10, tol, tol, 1000, &nevals,
414 &sampled_points[i].fvalue, objf, objfData, NULL, verbose-3);
415 if(ret<0 && verbose>0) {
416 printf("bobyqa error %d\n", ret); fflush(stdout);}
417 if(ret<0 && ret!=BOBYQA_ROUNDOFF_LIMITED) {
418 free(sampled_points); free(delta); free(tempp);
419 return(5);
420 }
421 if(verbose>2) {
422 printf("local opt 2nd round point %d => %e (nr of evals=%d)\n",
423 i+1, sampled_points[i].fvalue, nevals);
424 fflush(stdout);
425 }
426 } else {
427 itNr=40; /*itNr=100;*/
428 tol=1.0E-04; //tol=1.0E-03; //tol=1.0E-08;
429 POWELL_LINMIN_MAXIT=60; // 100;
430 ret=powell(sampled_points[i].par, delta, dim, tol, &itNr,
431 &sampled_points[i].fvalue, objf, objfData, verbose-3);
432 if(ret>1 && verbose>0) {printf("powell error %d\n", ret); fflush(stdout);}
433 if(ret>3) {
434 free(sampled_points); free(delta); free(tempp);
435 return(6);
436 }
437 if(verbose>2) {
438 printf("=> %e (itNr=%d)\n", sampled_points[i].fvalue, itNr);
439 fflush(stdout);
440 }
441 }
442 }
443
444 if(verbose>0) { // Print the topographical minima after 2nd local optimization
445 printf("Final topographical minima after 2nd local optimization\n");
446 for(i=0; i<samplNr; i++) if(sampled_points[i].topomin==1) {
447 k=0; printf(" %3d: %.2e", i, sampled_points[i].par[k]);
448 for(k=1; k<dim; k++) printf(" %.2e", sampled_points[i].par[k]);
449 printf(" => %.2e\n", sampled_points[i].fvalue); fflush(stdout);
450 }
451 }
452
453
454 /*
455 * Find the best locally optimized TM and run local opt again from
456 * this point with better accuracy
457 */
458
459 for(i=0, min=1e+99, IDmin=0; i<samplNr; i++) if(sampled_points[i].topomin==1) {
460 if(isfinite(sampled_points[i].fvalue) && sampled_points[i].fvalue<min) {
461 min=sampled_points[i].fvalue; IDmin=i;}
462 }
463 if(verbose>1) {
464 printf("Best topographical minimum:");
465 for(k=0; k<dim; k++) printf("%e ", sampled_points[IDmin].par[k]);
466 printf("-> %e \n", sampled_points[IDmin].fvalue); fflush(stdout);
467 }
468
469 /* Rerun of local optimization to the best point */
470 deltaf=0.01; tol=5.0E-04; //tol=1.0E-15;
471 do {
472 for(k=0; k<dim; k++) delta[k]=deltaf*sampled_points[IDmin].delta[k];
473 //for(k=0; k<dim; k++) delta[k]=deltaf*(uplim[k]-lowlim[k]);
474 if(TGO_LOCAL_OPT==1) {
475 ret=bobyqa(dim, 0, sampled_points[IDmin].par, lowlim, uplim, delta, 0.0, tol, // !!!
476 1.0E-10, tol, tol, 5000, &nevals,
477 &sampled_points[IDmin].fvalue, objf, objfData, NULL, verbose-3);
478 if(ret<0 && verbose>0) {
479 printf("bobyqa error %d\n", ret); fflush(stdout);}
480 if(ret<0 && ret!=BOBYQA_ROUNDOFF_LIMITED) {
481 free(sampled_points); free(delta); free(tempp);
482 return(5);
483 }
484 if(verbose>2) {
485 printf("local opt of the best point with tol=%g => %e (nr of evals=%d)\n",
486 tol, sampled_points[IDmin].fvalue, nevals);
487 fflush(stdout);
488 }
489 itNr=nevals;
490 deltaf*=0.5; tol*=0.1;
491 } else {
492 itNr=100;
493 POWELL_LINMIN_MAXIT=100; // 100;
494 ret=powell(sampled_points[IDmin].par, delta, dim, tol, &itNr,
495 &sampled_points[IDmin].fvalue, objf, objfData, verbose-3);
496 if(ret>1 && verbose>0) {printf("powell error %d\n", ret); fflush(stdout);}
497 if(ret>3) {
498 free(sampled_points); free(delta); free(tempp);
499 return(7);
500 }
501 if(verbose>1) {
502 printf(" powell once more with %d iteration(s) -> WSS=%e\n",
503 itNr, sampled_points[IDmin].fvalue);
504 fflush(stdout);
505 }
506 //deltaf*=0.5; tol*=0.5;
507 deltaf*=0.5; tol*=0.25;
508 }
509 } while(itNr>1 && deltaf>1.0E-05);
510//} while(itNr>1 && deltaf>1.0E-15);
511
512
513 /* Save best point to gmin */
514 for(k=0; k<dim; k++) gmin[k]=sampled_points[IDmin].par[k];
515 *fmin=sampled_points[IDmin].fvalue;
516 if(!isfinite(sampled_points[IDmin].fvalue)) {
517 if(verbose>0) {printf("TGO error: valid minimum value was not reached.\n");
518 fflush(stdout);}
519 free(sampled_points); free(delta); free(tempp); return(9);
520 }
521
522 /* Exit TGO */
523 free(sampled_points); free(delta); free(tempp);
524 if(verbose>0) {printf("out of tgo\n"); fflush(stdout);}
525 return(0);
526} /* end tgo */
bobyqa_result bobyqa(int n, int npt, double *x, const double *xl, const double *xu, const double *dx, const double rhoend, double xtol_rel, double minf_max, double ftol_rel, double ftol_abs, int maxeval, int *nevals, double *minf, double(*f)(int n, double *x, void *objf_data), void *objf_data, double *working_space, int verbose)
Definition bobyqa.c:40
unsigned int drandSeed(short int seed)
Make and optionally set the seed for rand(), drand, drandRange, and drandGaussian().
Definition gaussdev.c:63
double delta[MAX_PARAMS]
double fvalrange
double par[MAX_PARAMS]
double fvalue
void tgoRandomParameters(TGO_POINT *p, int parNr, int sNr, double *low, double *up)
Definition tgo.c:533
void tgoRandomParametersST(TGO_POINT *p, int parNr, int sNr, double *low, double *up)
Definition tgo.c:564
int TGO_LOCAL_INSIDE
Definition tgo.c:29
#define TGO_SAMPLNR
Definition tgo.c:23
int TGO_LOCAL_OPT
Definition tgo.c:31
int TGO_SQUARED_TRANSF
Definition tgo.c:27

◆ tgoRandomParameters()

void tgoRandomParameters ( TGO_POINT * p,
int parNr,
int sNr,
double * low,
double * up )
extern

Create randomized parameters for TGO.

See also
tgoRandomParametersST
Parameters
pPointer to list of TGO points.
parNrNr of parameters in the point.
sNrNr of TGO points.
lowList of lower limits for each parameter.
upList of upper limits for each parameter.

Definition at line 533 of file tgo.c.

544 {
545 int i, j;
546 double dif;
547
548 for(j=0; j<parNr; j++) {
549 dif=up[j]-low[j];
550 if(dif<=0.0) {
551 for(i=0; i<sNr; i++) if(p[i].topomin==0) p[i].par[j]=low[j];
552 } else {
553 for(i=0; i<sNr; i++) if(p[i].topomin==0) {
554 p[i].par[j]= drand()*dif + low[j];
555 }
556 }
557 }
558}

Referenced by tgo().

◆ tgoRandomParametersST()

void tgoRandomParametersST ( TGO_POINT * p,
int parNr,
int sNr,
double * low,
double * up )
extern

Create randomized parameters for TGO with square-root transformation, that is, parameter distribution is biased towards low absolute value.

See also
tgoRandomParameters
Parameters
pPointer to list of TGO points.
parNrNr of parameters in the point.
sNrNr of TGO points.
lowList of lower limits for each parameter.
upList of upper limits for each parameter.

Definition at line 564 of file tgo.c.

575 {
576 int i, j;
577 double v, stl, stu, dif;
578
579 for(j=0; j<parNr; j++) {
580 dif=up[j]-low[j];
581 if(dif<=0.0) {
582 for(i=0; i<sNr; i++) if(p[i].topomin==0) p[i].par[j]=low[j];
583 } else {
584 stl=copysign(sqrt(fabs(low[j])),low[j]); if(!isnormal(stl)) stl=0.0;
585 stu=copysign(sqrt(fabs(up[j])), up[j]); if(!isnormal(stu)) stu=0.0;
586 dif=stu-stl;
587 for(i=0; i<sNr; i++) if(p[i].topomin==0) {
588 v=drand()*dif + stl;
589 p[i].par[j]=copysign(v*v, v);
590 }
591 }
592 }
593}

Referenced by tgo().

Variable Documentation

◆ GAUSSDEV_SEED

long int GAUSSDEV_SEED
extern

Seed for random number generator; declared in gaussdev.c

Seed for random number generator

Definition at line 7 of file gaussdev.c.

Referenced by init_gaussdev().

◆ TGO_LOCAL_INSIDE

int TGO_LOCAL_INSIDE
extern

Local optimization outside (0) or inside (1) iTGO

Definition at line 29 of file tgo.c.

Referenced by tgo().

◆ TGO_LOCAL_OPT

int TGO_LOCAL_OPT
extern

Local optimization method is Powell-Brent (0) or Bobyqa (1)

Local optimization is done using Powell-Brent (0) or Bobyqa (1).

Definition at line 31 of file tgo.c.

Referenced by tgo().

◆ TGO_SQUARED_TRANSF

int TGO_SQUARED_TRANSF
extern

Biased (1) or even (0) parameter distribution

Definition at line 27 of file tgo.c.

Referenced by tgo().