~ubuntu-branches/ubuntu/raring/voxbo/raring

« back to all changes in this revision

Viewing changes to utils/fitOneOverF.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Hanke
  • Date: 2010-06-06 11:33:11 UTC
  • Revision ID: james.westby@ubuntu.com-20100606113311-v3c13imdkkd5n7ae
Tags: upstream-1.8.5~svn1172
ImportĀ upstreamĀ versionĀ 1.8.5~svn1172

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
// fitOneOverF.cpp
 
3
// Copyright (c) 1998-2010 by The VoxBo Development Team
 
4
 
 
5
// This file is part of VoxBo
 
6
// 
 
7
// VoxBo is free software: you can redistribute it and/or modify it
 
8
// under the terms of the GNU General Public License as published by
 
9
// the Free Software Foundation, either version 3 of the License, or
 
10
// (at your option) any later version.
 
11
// 
 
12
// VoxBo is distributed in the hope that it will be useful, but
 
13
// WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
// General Public License for more details.
 
16
// 
 
17
// You should have received a copy of the GNU General Public License
 
18
// along with VoxBo.  If not, see <http://www.gnu.org/licenses/>.
 
19
// 
 
20
// For general information on VoxBo, including the latest complete
 
21
// source code and binary distributions, manual, and associated files,
 
22
// see the VoxBo home page at: http://www.voxbo.org/
 
23
// 
 
24
// original version written by Dongbo Hu
 
25
 
 
26
using namespace std;
 
27
 
 
28
#include "fitOneOverF.h"
 
29
 
 
30
double a2fixed = 0;  // global variable defined for two-parameter fitting
 
31
 
 
32
/*************************************************************************
 
33
 * expb_f is the function to be fitted. fittingVar is a gsl vector 
 
34
 * which includes three variables to be fitted. 
 
35
 * In GSL documentation, this variable is named "x", 
 
36
 * which caused some confusion with the input X values. 
 
37
 * 
 
38
 * params is a variable of data type which includes the 
 
39
 * number of elements in the input X and Y, input values of X and Y,
 
40
 * and standard deviation at each point. 
 
41
 *************************************************************************/
 
42
int expb_f (const gsl_vector *fittingVar , void *params, 
 
43
        gsl_vector * f)
 
44
{
 
45
  size_t n = ((struct data *)params)->n;
 
46
  double *inputX = ((struct data *)params)->inputX;
 
47
  double *inputY = ((struct data *)params)->inputY;
 
48
  double *sigma = ((struct data *) params)->sigma;
 
49
  double a0 = gsl_vector_get (fittingVar, 0);
 
50
  double a1 = gsl_vector_get (fittingVar, 1);
 
51
  double a2 = gsl_vector_get (fittingVar, 2);
 
52
 
 
53
  for (size_t i = 0; i < n; i++) {
 
54
    /* Model Yi = 1.0 / (a0 * (Xi + a2)) + a1 */
 
55
    double t = inputX[i];
 
56
    double Yi = 1.0 / (a0 * (t + a2)) + a1;
 
57
    gsl_vector_set (f, i, (Yi - inputY[i])/sigma[i]);
 
58
  }
 
59
 
 
60
  return GSL_SUCCESS;
 
61
}
 
62
 
 
63
/*************************************************************************
 
64
 * expb_df includes the first order partialderivatives of each parameter *
 
65
 *************************************************************************/
 
66
int expb_df (const gsl_vector * fittingVar, void *params, 
 
67
         gsl_matrix * J)
 
68
{
 
69
  size_t n = ((struct data *)params)->n;
 
70
  double *inputX = ((struct data *) params)->inputX;
 
71
  double *sigma = ((struct data *) params)->sigma;
 
72
  double a0 = gsl_vector_get (fittingVar, 0);
 
73
  double a2 = gsl_vector_get (fittingVar, 2);
 
74
 
 
75
  for (size_t i = 0; i < n; i++) {
 
76
    /* Jacobian matrix J(i,j) = dfi / dxj, */
 
77
    /* where fi = (Yi - yi)/sigma[i],      */
 
78
    /*       Yi = 1.0 / (a0 * (Xi + a2)) + a1  */
 
79
    /* and the xj are the parameters (a0, a1, a2) */    
 
80
    double t = inputX[i];
 
81
    double s = 1.0 / sigma[i];
 
82
    double tmp = -1.0 /(a0 * (t + a2));
 
83
 
 
84
    gsl_matrix_set (J, i, 0, tmp / a0 * s); 
 
85
    gsl_matrix_set (J, i, 1, s);
 
86
    gsl_matrix_set (J, i, 2, tmp * s / (t + a2));
 
87
  }
 
88
 
 
89
  return GSL_SUCCESS;
 
90
}
 
91
 
 
92
/************************************************************************
 
93
 * expb_fdf combines expb_f anf expb_df together.                       *
 
94
 ************************************************************************/
 
95
int expb_fdf (const gsl_vector * fittingVar, void *params,
 
96
          gsl_vector * f, gsl_matrix * J)
 
97
{
 
98
  expb_f (fittingVar, params, f);
 
99
  expb_df (fittingVar, params, J);
 
100
  return GSL_SUCCESS;
 
101
}
 
102
 
 
103
/* Print out three parameters */
 
104
void print_state (size_t iter, gsl_multifit_fdfsolver * s)
 
105
{
 
106
  printf ("iter: %3d parameters are: %15.8f %15.8f %15.8f |f(x)| = %g\n", 
 
107
          (int)iter, gsl_vector_get (s->x, 0), gsl_vector_get (s->x, 1), 
 
108
          gsl_vector_get (s->x, 2), gsl_blas_dnrm2 (s->f));
 
109
}
 
110
 
 
111
/*************************************************************************************
 
112
 * curvefit() is the main function to calculate the three fitting parameters.    
 
113
 * This function requires 8 arguments:                                              
 
114
 * #1: vector of x values for fitting
 
115
 * #2: vector of y values for fitting
 
116
 * #3: vector of sigma values at each point (not available in IDL's curvefit function
 
117
 * #4: initial guess for first parameter (steepness)
 
118
 * #5: initial guess for second parameter (y-offset)
 
119
 * #6: initial guess for third parameter (x-shift)
 
120
 * #7: output file's name
 
121
 * #8: print mode (true: print out a summary on stdout; false: no any screen printout 
 
122
 **************************************************************************************/
 
123
VB_Vector *curvefit(VB_Vector *xVec, VB_Vector *yVec, VB_Vector *sigmaVec, double var3min, 
 
124
                    double var1_init, double var2_init, double var3_init, 
 
125
                    const char *outputFile, bool printFlag)
 
126
{
 
127
  /* fittingVec will include 8 elements: fittingStatus, # of iteration, 
 
128
   * three fitting parameters' value, three deviation values 
 
129
   * If status is 1.0, it means fitting is successful. 0 means fitting isn't successful.*/
 
130
  VB_Vector *fittingVec = new VB_Vector(8);
 
131
  size_t N = xVec->getLength();
 
132
  const gsl_multifit_fdfsolver_type *T;
 
133
  gsl_multifit_fdfsolver *s;
 
134
 
 
135
  int status;
 
136
  size_t iter = 0;
 
137
  const size_t n = N;
 
138
  const size_t p = 3;
 
139
  gsl_matrix *covar = gsl_matrix_alloc (p, p);
 
140
 
 
141
  double inputX[N], inputY[N], sigma[N];
 
142
  struct data d = {n, inputX, inputY, sigma};  
 
143
  gsl_multifit_function_fdf f;
 
144
 
 
145
  double fitting_init[3] = { var1_init, var2_init, var3_init };
 
146
  gsl_vector_view fittingVar = gsl_vector_view_array (fitting_init, p);
 
147
  const gsl_rng_type * type;
 
148
  gsl_rng * r;
 
149
 
 
150
  gsl_rng_env_setup();
 
151
  type = gsl_rng_default;
 
152
  r = gsl_rng_alloc (type);
 
153
 
 
154
  f.f = &expb_f;
 
155
  f.df = &expb_df;
 
156
  f.fdf = &expb_fdf;
 
157
  f.n = n;
 
158
  f.p = p;
 
159
  f.params = &d;
 
160
 
 
161
  for (size_t i = 0; i < n; i++) {
 
162
    inputX[i] = xVec->getElement(i);
 
163
    inputY[i] = yVec->getElement(i);
 
164
    
 
165
    /* Set sigma to be 0.1 at each point. This value is completely arbitrary.
 
166
     * It won't change the fitting variables' values, but the deviation of each 
 
167
     * fitting variable (the value after "+/-") will be affected. */
 
168
    sigma[i] = sigmaVec->getElement(i);
 
169
  }
 
170
 
 
171
  T = gsl_multifit_fdfsolver_lmsder;
 
172
  s = gsl_multifit_fdfsolver_alloc (T, n, p);
 
173
  gsl_multifit_fdfsolver_set (s, &f, &fittingVar.vector);
 
174
 
 
175
  if (printFlag)
 
176
    print_state (iter, s);
 
177
 
 
178
  do {
 
179
    iter++;
 
180
    status = gsl_multifit_fdfsolver_iterate (s);
 
181
    if (printFlag) {
 
182
      printf ("status = %s\n", gsl_strerror (status));
 
183
      print_state (iter, s);
 
184
    }
 
185
 
 
186
    // Make sure var3 is always larger than minimum. If not, call curverfit12()
 
187
    if (gsl_vector_get (s->x, 2) <= var3min) {
 
188
      double var3 = var3min * 0.99;
 
189
      printf("******************************************************************\n");
 
190
      printf("x-shift minimum value reached.\n");
 
191
      printf("Arbitrarily set x-shift to %.5f and fit the other two ...\n", var3);
 
192
      printf("******************************************************************\n");
 
193
      gsl_multifit_fdfsolver_free (s);
 
194
      return curvefit12(xVec, yVec, sigmaVec, var3,gsl_vector_get (s->x, 0), 
 
195
                        gsl_vector_get (s->x, 1), outputFile, printFlag);
 
196
    }
 
197
 
 
198
    if (status)
 
199
      break;
 
200
 
 
201
    status = gsl_multifit_test_delta (s->dx, s->x, 1e-4, 1e-4);
 
202
  }
 
203
  while (status == GSL_CONTINUE && iter < 500);
 
204
 
 
205
  gsl_multifit_covar (s->J, 0.0, covar);
 
206
 
 
207
#define FIT(i) gsl_vector_get(s->x, i)
 
208
#define ERR(i) sqrt(gsl_matrix_get(covar, i, i))
 
209
 
 
210
  if (printFlag) {
 
211
    printf("\nElements in covariance matrix are:\n");
 
212
    gsl_matrix_fprintf (stdout, covar, "%g");
 
213
  
 
214
    printf("\nparameter #1: steepness = %.5f +/- %.5f\n", FIT(0), ERR(0));
 
215
    printf("parameter #2: y-offset  = %.5f +/- %.5f\n", FIT(1), ERR(1));
 
216
    printf("parameter #3: x-shift   = %.5f +/- %.5f\n", FIT(2), ERR(2));
 
217
    printf ("status = %s\n\n", gsl_strerror (status));
 
218
  }
 
219
 
 
220
  // Write the fitting result to a file (if output filename is available)
 
221
  if (outputFile != '\0') {
 
222
    FILE * f1 = fopen(outputFile, "w");
 
223
    fprintf (f1, ";VB98\n");
 
224
    fprintf (f1, ";REF1\n");
 
225
    fprintf (f1, "; GSL nonlinear least-squares fitting\n");
 
226
    string myTime, myDate;
 
227
    maketimedate(myTime, myDate);  // maketimedate() is defined in libvoxbo/vbutil.cpp
 
228
    fprintf (f1, "; Date created: %s_%s\n", myTime.data(), myDate.data());
 
229
    fprintf (f1, "; Initial guess: %f, %f, %f\n", var1_init, var2_init, var3_init);
 
230
    fprintf (f1, "; Number of iteration: %d\n", (int)iter);
 
231
    fprintf (f1, "; Status = %s\n", gsl_strerror (status));
 
232
    fprintf (f1, "; Deviation: %f, %f, %f\n\n", ERR(0), ERR(1), ERR(2));
 
233
    fprintf (f1, "%f\n%f\n%f\n", FIT(0), FIT(1), FIT(2));
 
234
    fclose(f1);
 
235
  }
 
236
 
 
237
  // Set elements in fittingVec. If status is 0 (success), set elements one by one.
 
238
  // Otherwise set all elements to be zero.
 
239
  if (status == 0) {
 
240
    fittingVec->setElement(0, 1.0);
 
241
    fittingVec->setElement(1, iter);
 
242
    fittingVec->setElement(2, FIT(0));
 
243
    fittingVec->setElement(3, FIT(1));
 
244
    fittingVec->setElement(4, FIT(2));
 
245
 
 
246
    fittingVec->setElement(5, ERR(0));
 
247
    fittingVec->setElement(6, ERR(1));
 
248
    fittingVec->setElement(7, ERR(2));
 
249
  }
 
250
  else
 
251
    fittingVec->setAll(0);
 
252
  
 
253
  gsl_multifit_fdfsolver_free (s);
 
254
  return fittingVec;
 
255
}
 
256
 
 
257
/* Two parameter version of expb_f */
 
258
int expb_f12 (const gsl_vector *fittingVar, void *params, 
 
259
        gsl_vector *f)
 
260
{
 
261
  size_t n = ((struct data *)params)->n;
 
262
  double *inputX = ((struct data *)params)->inputX;
 
263
  double *inputY = ((struct data *)params)->inputY;
 
264
  double *sigma = ((struct data *) params)->sigma;
 
265
 
 
266
  double a0 = gsl_vector_get (fittingVar, 0);
 
267
  double a1 = gsl_vector_get (fittingVar, 1);
 
268
 
 
269
  for (size_t i = 0; i < n; i++) {
 
270
    /* Model Yi = 1.0 / (a0 * (Xi + var3)) + a1 */
 
271
    double t = inputX[i];
 
272
    double Yi = 1.0 / (a0 * (t + a2fixed)) + a1;
 
273
    gsl_vector_set (f, i, (Yi - inputY[i])/sigma[i]);
 
274
  }
 
275
 
 
276
  return GSL_SUCCESS;
 
277
}
 
278
 
 
279
/***************************************************************************
 
280
 * expb_df12 includes the first order partialderivatives of each parameter *
 
281
 ***************************************************************************/
 
282
int expb_df12 (const gsl_vector * fittingVar, void *params, gsl_matrix *J)
 
283
{
 
284
  size_t n = ((struct data *)params)->n;
 
285
  double *inputX = ((struct data *) params)->inputX;
 
286
  double *sigma = ((struct data *) params)->sigma;
 
287
  double a0 = gsl_vector_get (fittingVar, 0);
 
288
 
 
289
  for (size_t i = 0; i < n; i++) {
 
290
    /* Jacobian matrix J(i,j) = dfi / dxj, */
 
291
    /* where fi = (Yi - yi)/sigma[i],      */
 
292
    /*       Yi = 1.0 / (a0 * (Xi + a2fixed)) + a1  */
 
293
    /* and the xj are the parameters (a0, a1, a2fixed) */ 
 
294
    double t = inputX[i];
 
295
    double s = 1.0 / sigma[i];
 
296
    double tmp = -1.0 /(a0 * (t + a2fixed));
 
297
    gsl_matrix_set (J, i, 0, s * tmp / a0 ); 
 
298
    gsl_matrix_set (J, i, 1, s);    
 
299
  }
 
300
 
 
301
  return GSL_SUCCESS;
 
302
}
 
303
 
 
304
/************************************************************************
 
305
 * expb_fdf combines expb_f anf expb_df together.                       *
 
306
 ************************************************************************/
 
307
int expb_fdf12 (const gsl_vector * fittingVar, void *params,
 
308
          gsl_vector * f, gsl_matrix * J)
 
309
{
 
310
  expb_f12 (fittingVar, params, f);
 
311
  expb_df12 (fittingVar, params, J);
 
312
 
 
313
  return GSL_SUCCESS;
 
314
}
 
315
 
 
316
/* Print out two parameters */
 
317
void print_state12 (size_t iter, gsl_multifit_fdfsolver * s)
 
318
{
 
319
  printf ("iter: %3d parameters are: %15.8f %15.8f |f(x)| = %g\n", (int)iter, 
 
320
          gsl_vector_get (s->x, 0), gsl_vector_get (s->x, 1), gsl_blas_dnrm2 (s->f));
 
321
}
 
322
 
 
323
/* curvefit12() fits the input X and Y vectors based on this equation:
 
324
 * Y = 1.0 / [var1 * (X + var3min * 0.99)] + var2
 
325
 * Note that var3min * 0.99 is a fixed arbitrary value to make sure
 
326
 * that when 1/f function is expanded to a longer range (totalReps * TR / 2000),
 
327
 * the initial value wouldn't be negative and enormously large. */
 
328
VB_Vector *curvefit12 (VB_Vector *xVec, VB_Vector *yVec, VB_Vector *sigmaVec, 
 
329
                      double var3, double var1_init, double var2_init, 
 
330
                      const char *outputFile, bool printFlag)
 
331
{
 
332
  a2fixed = var3;
 
333
  /* fittingVec will include 8 elements: fittingStatus, # of iteration, 
 
334
   * three fitting parameters' value, three deviation values 
 
335
   * If status is 1.0, it means fitting is successful. 0 means fitting isn't successful.*/
 
336
  VB_Vector *fittingVec = new VB_Vector(8);
 
337
  size_t N = xVec->getLength();
 
338
  const gsl_multifit_fdfsolver_type *T;
 
339
  gsl_multifit_fdfsolver *s;
 
340
 
 
341
  int status;
 
342
  size_t iter = 0;
 
343
  const size_t n = N;
 
344
  const size_t p = 2;
 
345
  gsl_matrix *covar = gsl_matrix_alloc (p, p);
 
346
 
 
347
  double inputX[N], inputY[N], sigma[N];
 
348
  struct data d = {n, inputX, inputY, sigma};  
 
349
  gsl_multifit_function_fdf f;
 
350
 
 
351
  double fitting_init[2] = {var1_init, var2_init};
 
352
  gsl_vector_view fittingVar = gsl_vector_view_array (fitting_init, p);
 
353
  const gsl_rng_type * type;
 
354
  gsl_rng * r;
 
355
 
 
356
  gsl_rng_env_setup();
 
357
  type = gsl_rng_default;
 
358
  r = gsl_rng_alloc (type);
 
359
 
 
360
  f.f = &expb_f12;
 
361
  f.df = &expb_df12;
 
362
  f.fdf = &expb_fdf12;
 
363
  f.n = n;
 
364
  f.p = p;
 
365
  f.params = &d;
 
366
 
 
367
  for (size_t i = 0; i < n; i++) {
 
368
    inputX[i] = xVec->getElement(i);
 
369
    inputY[i] = yVec->getElement(i);
 
370
    /* Set sigma to be 0.1 at each point. This value is completely arbitrary.
 
371
     * It won't change the fitting variables' values, but the deviation of each 
 
372
     * fitting variable (the value after "+/-") will be affected. */
 
373
    sigma[i] = sigmaVec->getElement(i);
 
374
  }
 
375
 
 
376
  T = gsl_multifit_fdfsolver_lmsder;
 
377
  s = gsl_multifit_fdfsolver_alloc (T, n, p);
 
378
  gsl_multifit_fdfsolver_set (s, &f, &fittingVar.vector);
 
379
 
 
380
  if (printFlag)
 
381
    print_state12(iter, s);
 
382
 
 
383
  do {
 
384
    iter++;
 
385
    status = gsl_multifit_fdfsolver_iterate (s);
 
386
    
 
387
    if (printFlag) {
 
388
      printf ("status = %s\n", gsl_strerror (status));
 
389
      print_state12(iter, s);
 
390
    }
 
391
 
 
392
    if (status)
 
393
      break;    
 
394
    status = gsl_multifit_test_delta (s->dx, s->x, 1e-4, 1e-4);
 
395
  }
 
396
  while (status == GSL_CONTINUE && iter < 500);
 
397
 
 
398
  gsl_multifit_covar (s->J, 0.0, covar);
 
399
 
 
400
#define FIT(i) gsl_vector_get(s->x, i)
 
401
#define ERR(i) sqrt(gsl_matrix_get(covar, i, i))
 
402
 
 
403
  if (printFlag) {
 
404
    printf("\nElements in covariance matrix are:\n");
 
405
    gsl_matrix_fprintf (stdout, covar, "%g");
 
406
  
 
407
    printf("\nparameter #1: steepness = %.5f +/- %.5f\n", FIT(0), ERR(0));
 
408
    printf("parameter #2: y-offset  = %.5f +/- %.5f\n", FIT(1), ERR(1));
 
409
    printf("parameter #3: x-shift   = %.5f (fixed)\n", var3);
 
410
    printf ("status = %s\n\n", gsl_strerror (status));
 
411
  }
 
412
 
 
413
  // Write the fitting result to a file (if output filename is available)
 
414
  if (outputFile != '\0') {
 
415
    FILE * f1 = fopen(outputFile, "w");
 
416
    fprintf (f1, ";VB98\n");
 
417
    fprintf (f1, ";REF1\n");
 
418
    fprintf (f1, "; GSL nonlinear least-squares fitting\n");
 
419
    string myTime, myDate;
 
420
    maketimedate(myTime, myDate);  // maketimedate() is defined in libvoxbo/vbutil.cpp
 
421
    fprintf (f1, "; Date created: %s_%s\n", myTime.data(), myDate.data());
 
422
    fprintf (f1, "; Initial guess: %f, %f\n", var1_init, var2_init);
 
423
    fprintf (f1, "; Number of iteration: %d\n", (int)iter);
 
424
    fprintf (f1, "; Status = %s\n", gsl_strerror (status));
 
425
    fprintf (f1, "; Deviation: %f, %f\n\n", ERR(0), ERR(1));
 
426
    fprintf (f1, "%f\n%f\n%f\n", FIT(0), FIT(1), var3);
 
427
    fclose(f1);
 
428
  }
 
429
 
 
430
  // Set elements in fittingVec. If status is 0 (success), 
 
431
  // set elements one by one, Otherwise set all elements to zero.
 
432
  if (status == 0) {
 
433
    fittingVec->setElement(0, 1.0);
 
434
    fittingVec->setElement(1, iter);
 
435
    fittingVec->setElement(2, FIT(0));
 
436
    fittingVec->setElement(3, FIT(1));
 
437
    fittingVec->setElement(4, var3);
 
438
    fittingVec->setElement(5, ERR(0));
 
439
    fittingVec->setElement(6, ERR(1));
 
440
    fittingVec->setElement(7, 0);
 
441
  }
 
442
  else
 
443
    fittingVec->setAll(0);
 
444
  
 
445
  gsl_multifit_fdfsolver_free (s);
 
446
  return fittingVec;
 
447
}
 
448
 
 
449
/******************************************************************************************
 
450
 * wrapper function for fitting calculation. It accepts filenames for x, y, sigma values. *
 
451
 * It also accepts filename for initial guess.                                            *
 
452
 ******************************************************************************************/
 
453
VB_Vector * curvefit(const char *xFilename, const char *yFilename, const char *sigmaFilename,
 
454
                     double var3min, const char *initFile, const char *outputFile)          
 
455
{
 
456
  // Check xFilename format
 
457
  VB_Vector * xVec = new VB_Vector();
 
458
  string xString(xFilename);
 
459
  if (xVec->ReadFile(xString)) {
 
460
    printf("Invalid file format for X: %s\n", xFilename);
 
461
    return 0;
 
462
  }
 
463
 
 
464
  // Check yFilename format
 
465
  VB_Vector * yVec = new VB_Vector();
 
466
  string yString(yFilename);
 
467
  if (yVec->ReadFile(yString)) {
 
468
    printf("Invalid file format for Y: %s\n", yFilename);
 
469
    return 0;
 
470
  }
 
471
 
 
472
  // Check sigmaFilename format
 
473
  VB_Vector * sigmaVec = new VB_Vector();
 
474
  string sigmaString(sigmaFilename);
 
475
  if (sigmaVec->ReadFile(sigmaString)) {
 
476
    printf("Invalid file format for sigma: %s\n", sigmaFilename);
 
477
    return 0;
 
478
  }
 
479
 
 
480
  // Check initFile format
 
481
  VB_Vector * initVec = new VB_Vector();
 
482
  string initString(initFile);
 
483
  if (initVec->ReadFile(initString)) {
 
484
    printf("Invalid file format for initialization: %s\n", initFile);
 
485
    return 0;
 
486
  }
 
487
 
 
488
  /* Read the file which has initial values for three parameters */
 
489
  double var1_init = initVec->getElement(0);
 
490
  double var2_init = initVec->getElement(1);
 
491
  double var3_init = initVec->getElement(2);
 
492
 
 
493
  return curvefit(xVec, yVec, sigmaVec, var3min, var1_init, var2_init, var3_init, outputFile);
 
494
}
 
495
 
 
496
 
 
497
/****************************************************************************************** 
 
498
 * Wrapper function for fitting calculation. It accepts filenames for x, y, sigma values. *
 
499
 * input sigma values is a constant at each point.                                        *
 
500
 ******************************************************************************************/
 
501
VB_Vector * curvefit(const char * xFilename, const char * yFilename, double inputSigma, double var3min,
 
502
                     double var1_init, double var2_init, double var3_init, const char *outputFile)
 
503
{
 
504
  /* Read input file for X and Y values */
 
505
  VB_Vector * xVec = new VB_Vector();
 
506
  string xString(xFilename);
 
507
  if (xVec->ReadFile(xString)) {
 
508
    printf("Invalid file format for X: %s\n", xFilename);
 
509
    return 0;
 
510
  }
 
511
 
 
512
  VB_Vector * yVec = new VB_Vector(yFilename);
 
513
  string yString(yFilename);
 
514
  if (yVec->ReadFile(yString)) {
 
515
    printf("Invalid file format for Y: %s\n", yFilename);
 
516
    return 0;
 
517
  }
 
518
 
 
519
  /* Read input file for sigma values */
 
520
  int length = xVec->getLength();
 
521
  VB_Vector * sigmaVec = new VB_Vector(length);
 
522
  sigmaVec->setAll(inputSigma);
 
523
 
 
524
  return  curvefit(xVec, yVec, sigmaVec, var3min, var1_init, var2_init, var3_init, outputFile);
 
525
}
 
526
 
 
527
/****************************************************************************************** 
 
528
 * Wrapper function for fitting calculation. It accepts filenames for x, y, sigma values. *
 
529
 ******************************************************************************************/
 
530
VB_Vector * curvefit(const char *xFilename, const char *yFilename, const char *sigmaFilename,
 
531
                     double var3min, double var1_init, double var2_init, double var3_init, 
 
532
                     const char *outputFile)        
 
533
{
 
534
  // Check xFilename format
 
535
  VB_Vector * xVec = new VB_Vector();
 
536
  string xString(xFilename);
 
537
  if (xVec->ReadFile(xString)) {
 
538
    printf("Invalid file format for X: %s\n", xFilename);
 
539
    return 0;
 
540
  }
 
541
 
 
542
  // Check yFilename format
 
543
  VB_Vector * yVec = new VB_Vector();
 
544
  string yString(yFilename);
 
545
  if (yVec->ReadFile(yString)) {
 
546
    printf("Invalid file format for Y: %s\n", yFilename);
 
547
    return 0;
 
548
  }
 
549
 
 
550
  // Check sigmaFilename format
 
551
  VB_Vector * sigmaVec = new VB_Vector();
 
552
  string sigmaString(sigmaFilename);
 
553
  if (sigmaVec->ReadFile(sigmaString)) {
 
554
    printf("Invalid file format for sigma: %s\n", sigmaFilename);
 
555
    return 0;
 
556
  }
 
557
 
 
558
  return curvefit(xVec, yVec, sigmaVec, var3min, var1_init, var2_init, var3_init, outputFile);
 
559
}
 
560
 
 
561
/************************************************************************************************
 
562
 * This is the generic function to get fitting for a input power spectrum vector.
 
563
 * It has the following arguments:
 
564
 * #1 (psVecIn): input vector which include power spectrum elements 
 
565
 * #2 (ignorePSIn): another vector which defines frequencies ignored (elements which is equal to 0)
 
566
 * #3: input TR value in unit of ms (default is 2000)
 
567
 * #4: input sigma value (default is 0.1)
 
568
 * #5: initial guess for parameter 1 (default is 20.0)
 
569
 * #6: initial guess for parameter 2 (default is 2.0)
 
570
 * #7: initial guess for parameter 3 (default is -0.0001)
 
571
 * #8: output filename (default is empty)
 
572
 * #9: flag to show printout or not (default is yes)
 
573
 ************************************************************************************************/
 
574
VB_Vector * fitOneOverF(VB_Vector *psVecIn, VB_Vector *ignorePSin, double var3min, double TRin, 
 
575
                        double sigma, double var1, double var2, double var3, const char * outputFile, bool printFlag)
 
576
{
 
577
  int cmpStatus = cmpVec(psVecIn, ignorePSin);
 
578
  if (cmpStatus == 2) {
 
579
    printf("Error: The number of elements in ps vector doesn't match ignorePS vector.\n"); 
 
580
    return 0;
 
581
  }
 
582
 
 
583
  double TR = TRin / 1000.0;
 
584
  double var1init = var1, var2init = var2, var3init = var3;
 
585
 
 
586
  int numObs = psVecIn->getLength();
 
587
  double duration = numObs * TR;
 
588
  int sigLen = numObs / 2 - 4;
 
589
  VB_Vector *xVec = new VB_Vector(sigLen);
 
590
  VB_Vector *signal = new VB_Vector(sigLen);
 
591
  VB_Vector *ignoreVec = new VB_Vector(sigLen);
 
592
 
 
593
  for (int i = 0; i < sigLen; i++) {
 
594
    double tmpVal = ignorePSin->getElement(i + 1);
 
595
    ignoreVec->setElement(i, tmpVal);
 
596
    xVec->setElement(i, ((double)i + 1.0)/ duration);
 
597
    tmpVal = sqrt(psVecIn->getElement(i + 1));
 
598
    signal->setElement(i, tmpVal);
 
599
  }
 
600
  var2init = signal->getElement(sigLen - 1);
 
601
 
 
602
  size_t counter = 0;
 
603
  size_t numNonZero = findNonZero(ignoreVec);
 
604
 
 
605
  if (numNonZero == 0) {
 
606
    printf("Error: no freqency found in ignorePS vector\n");
 
607
    return 0;
 
608
  }
 
609
 
 
610
  VB_Vector *subx = new VB_Vector(numNonZero);
 
611
  VB_Vector *subsignal = new VB_Vector(numNonZero);
 
612
  VB_Vector *sigmaVec = new VB_Vector(numNonZero);
 
613
  sigmaVec->setAll(sigma);
 
614
 
 
615
  for (size_t i = 0; i < signal->getLength(); i++) {
 
616
    if (ignoreVec->getElement(i) != 0) {
 
617
      subsignal->setElement(counter, signal->getElement(i));
 
618
      subx->setElement(counter, xVec->getElement(i));
 
619
      counter++;
 
620
    }
 
621
    else 
 
622
      continue;
 
623
  }
 
624
 
 
625
  if (counter == 0) {
 
626
    printf("Error: no freqency found in ignorePS vector\n");
 
627
    return 0;
 
628
  }
 
629
 
 
630
  VB_Vector * newVec = new VB_Vector(8);
 
631
  newVec = curvefit(subx, subsignal, sigmaVec, var3min, var1init, var2init, var3init, outputFile, printFlag);
 
632
 
 
633
  return newVec;
 
634
 
 
635
}
 
636
 
 
637
/******************************************************************************************
 
638
 * Function used by generic fitOneOverF(). 
 
639
 * Returns 0 if 1st vector has same number of elements as 2nd vector does;
 
640
 * Returns 1 if 2nd vector's length is multiple of 1st vector's;
 
641
 * Returns 2 otherwise
 
642
*******************************************************************************************/
 
643
int cmpVec(VB_Vector *shortVec, VB_Vector *longVec)
 
644
{
 
645
  int length_s = shortVec->getLength();
 
646
  int length_l = longVec->getLength();
 
647
 
 
648
  if (length_s == length_l)
 
649
    return 0;
 
650
  else if (length_l % length_s == 0)
 
651
    return 1;
 
652
  else 
 
653
    return 2;
 
654
}
 
655
 
 
656
/******************************************************************************************
 
657
 * Function used by generic fitOneOverF(). 
 
658
 * It returns number of non-zero elements in the input vector.
 
659
 ******************************************************************************************/
 
660
size_t findNonZero(VB_Vector *inputVec)
 
661
{
 
662
  size_t counter = 0;
 
663
  for (size_t i = 0; i < inputVec->getLength(); i++) {
 
664
    if (inputVec->getElement(i) != 0)
 
665
      counter++;
 
666
    else 
 
667
      continue;
 
668
  }
 
669
 
 
670
  return counter;
 
671
}
 
672
 
 
673
/******************************************************************************************
 
674
 * Wrapper function based on generic fitOneOverF().
 
675
 * Only power spectrum vector is specified. 
 
676
 * All elements in ignorePS vector will be set to be 1 (no frequencies will be ignored.) 
 
677
*******************************************************************************************/
 
678
VB_Vector * fitOneOverF(VB_Vector *psVec, double var3min, double TRin, double sigma, double var1, 
 
679
                        double var2, double var3, const char * outputFile, bool printFlag)
 
680
{
 
681
  VB_Vector *ignorePSin = new VB_Vector(psVec->getLength());
 
682
  ignorePSin->setAll(1.0);
 
683
  
 
684
  return fitOneOverF(psVec, ignorePSin, var3min, TRin, sigma, var1, var2, var3, outputFile, printFlag);
 
685
}
 
686
 
 
687
/******************************************************************************************
 
688
 * Wrapper function based on generic fitOneOverF().
 
689
 * It accepts a filename for ps vector. 
 
690
*******************************************************************************************/
 
691
VB_Vector *fitOneOverF(const char *psFile, double var3min, double TRin, double sigma, double var1, 
 
692
                       double var2, double var3, const char * outputFile, bool printFlag)
 
693
{
 
694
  // Check psFile
 
695
  VB_Vector *psVec = new VB_Vector();
 
696
  string psString(psFile);
 
697
  if (psVec->ReadFile(psString)) {
 
698
    printf("Invalid file format for power spectrum: %s\n", psFile);
 
699
    return 0;
 
700
  }
 
701
 
 
702
  VB_Vector *ignorePSin = new VB_Vector(psVec->getLength());
 
703
  ignorePSin->setAll(1.0);
 
704
 
 
705
  return fitOneOverF(psVec, ignorePSin, var3min, TRin, sigma, var1, var2, var3, outputFile, printFlag);
 
706
}
 
707
 
 
708
/******************************************************************************************
 
709
 * Wrapper function based on generic fitOneOverF().
 
710
 * It accepts a filename for reference function.
 
711
 * Reference function will be used to build ignorePS vector
 
712
*******************************************************************************************/
 
713
VB_Vector * fitOneOverF(VB_Vector *psVec, const char *refFunc, double var3min, double TRin, 
 
714
                        double sigma, double var1, double var2, double var3, 
 
715
                        const char * outputFile, bool printFlag)
 
716
{
 
717
  VB_Vector *refLocal = new VB_Vector();
 
718
  tokenlist condKey;
 
719
  int refStat = getCondVec(refFunc, condKey, refLocal);
 
720
  if (refStat == -1) {
 
721
    printf("File not readable: %s\n", refFunc);
 
722
    return 0;
 
723
  }
 
724
  else if (refStat == -2) {
 
725
    printf("Error: different number of keys in header and content: %s\n", refFunc);
 
726
    return 0;
 
727
  }
 
728
  else if (refStat == 1) {
 
729
    printf("Error: different keys in header and content: %s\n", refFunc);
 
730
    return 0;
 
731
  }
 
732
  
 
733
  refLocal->meanCenter();
 
734
  VB_Vector *psRef = new VB_Vector(refLocal->getLength());
 
735
  refLocal->getPS(psRef);
 
736
 
 
737
  VB_Vector *ignorePS = new VB_Vector(refLocal->getLength());
 
738
  ignorePS->setAll(1.0);
 
739
  double refPSmax = psRef->getMaxElement();
 
740
  
 
741
  for (size_t i = 0; i < ignorePS->getLength(); i++) {
 
742
    if (psRef->getElement(i) > refPSmax * 0.01)
 
743
      ignorePS->setElement(i, 0);
 
744
    else continue;
 
745
  }
 
746
 
 
747
  return fitOneOverF(psVec, ignorePS, var3min, TRin, sigma, var1, var2, var3, outputFile, printFlag);
 
748
}
 
749
 
 
750
/******************************************************************************************
 
751
 * Wrapper function based on generic fitOneOverF().
 
752
 * It accepts a filename for reference function.
 
753
 * Reference function will be used to build ignorePS vector
 
754
*******************************************************************************************/
 
755
VB_Vector * fitOneOverF(const char *psFile, const char *refFunc, double var3min, double TRin, 
 
756
                        double sigma, double var1, double var2, double var3, 
 
757
                        const char * outputFile, bool printFlag)
 
758
{
 
759
  VB_Vector *psVec = new VB_Vector();
 
760
  string psString(psFile);
 
761
  if (psVec->ReadFile(psString)) {
 
762
    printf("Invalid file format for power spectrum: %s\n", psFile);
 
763
    return 0;
 
764
  }
 
765
 
 
766
  VB_Vector *refLocal = new VB_Vector();
 
767
  tokenlist condKey;
 
768
  int refStat = getCondVec(refFunc, condKey, refLocal);
 
769
  if (refStat == -1) {
 
770
    printf("File not readable: %s\n", refFunc);
 
771
    return 0;
 
772
  }
 
773
  else if (refStat == -2) {
 
774
    printf("Error: different number of keys in header and content: %s\n", refFunc);
 
775
    return 0;
 
776
  }
 
777
  else if (refStat == 1) {
 
778
    printf("Error: different keys in header and content: %s\n", refFunc);
 
779
    return 0;
 
780
  }
 
781
  
 
782
  refLocal->meanCenter();
 
783
  VB_Vector *psRef = new VB_Vector(refLocal->getLength());
 
784
  refLocal->getPS(psRef);
 
785
 
 
786
  VB_Vector *ignorePS = new VB_Vector(refLocal->getLength());
 
787
  ignorePS->setAll(1.0);
 
788
  double refPSmax = psRef->getMaxElement();
 
789
  
 
790
  for (size_t i = 0; i < ignorePS->getLength(); i++) {
 
791
    if (psRef->getElement(i) > refPSmax * 0.01)
 
792
      ignorePS->setElement(i, 0);
 
793
    else continue;
 
794
  }
 
795
 
 
796
  return fitOneOverF(psVec, ignorePS, var3min, TRin, sigma, var1, var2, var3, outputFile, printFlag);
 
797
}
 
798
 
 
799
/******************************************************************************************
 
800
 * generic function to make time domain representation of the 1/f curve given a set of 
 
801
 * three parameters, number of images and TR (default is 2000 ms)
 
802
 ******************************************************************************************/
 
803
VB_Vector * makeOneOverF(int numImages, double var1, double var2, double var3, double TRin)
 
804
{
 
805
  double TR = TRin / 1000.0;
 
806
  int halfLen = numImages / 2;
 
807
  double xVal, yVal;
 
808
 
 
809
  VB_Vector *freqVec = new VB_Vector(numImages);
 
810
  for (int i = 1; i <= halfLen; i++) {
 
811
    xVal = (double) i / (TR * numImages);
 
812
    yVal = 1.0 / (var1 * (xVal + var3)) + var2;
 
813
    freqVec->setElement(i, yVal);
 
814
  }
 
815
 
 
816
  if (numImages % 2 == 0) {
 
817
    int j = 0;
 
818
    for (int i = halfLen + 1; i < numImages; i++) {      
 
819
      yVal = freqVec->getElement(halfLen - j);
 
820
      freqVec->setElement(i, yVal);
 
821
      j++;
 
822
    }
 
823
  }
 
824
  else {
 
825
    int j = 0;
 
826
    for (int i = halfLen + 2; i < numImages; i++) {      
 
827
      yVal = freqVec->getElement(halfLen - j);
 
828
      freqVec->setElement(i, yVal);
 
829
      j++;
 
830
    }
 
831
    yVal = freqVec->getElement(halfLen + 2);
 
832
    freqVec->setElement(halfLen + 1, yVal);
 
833
  }
 
834
 
 
835
  freqVec->setElement(0, 0);
 
836
 
 
837
  freqVec->scaleInPlace(1.0 / freqVec->getMaxElement());
 
838
  VB_Vector *realPart = new VB_Vector(numImages);
 
839
  VB_Vector *imagPart = new VB_Vector(numImages);
 
840
  imagPart->setAll(0);
 
841
  freqVec->ifft(realPart, imagPart);
 
842
  realPart->normMag();
 
843
 
 
844
  return realPart;
 
845
}
 
846
 
 
847
/**************************************************************************
 
848
 * wrapper function based on generic makeOneOverF() 
 
849
 * It accepts a filename which includes three fitting parameters.
 
850
 **************************************************************************/
 
851
VB_Vector * makeOneOverF(int numImages, const char * paramFile, double TRin)
 
852
{
 
853
  VB_Vector *initGuess = new VB_Vector(paramFile);
 
854
  double var1= initGuess->getElement(0);
 
855
  double var2= initGuess->getElement(1);
 
856
  double var3= initGuess->getElement(2);
 
857
 
 
858
  return makeOneOverF(numImages, var1, var2, var3, TRin);
 
859
}