/* * Gaussian parameters calculation y=A/sqrt(2*pi*sigma^2) exp(-(x-x_0)^2/2/sigma^2), * which approximates the points set pts * Parameters A_, sigma_, x0_ may be NULL (if you don't need any of them) */ void gauss_fit(Points *pts, double *C_, double *A_, double *sigma_, double *x0_){ // VVVV lower parameters may be formed as a structure to change as function argument double epsabs = 1e-8,// absolute error epsrel = 1e-5,// relative error chi_max = 0.01;// max chi value for iterations criteria int max_iter = 300; // limit iterations number of gsl_multifit_fdfsolver size_t N_MIN = 10; // minimum points for approximation double x_init[4]; // AAAA upper parameters may be formed as a structure to change as function argument /* x_init, the best approximations: * x0 - not far from real (the nearest is the better) * sigma - not far from real (the nearest is the better) * A - not large ~10 (it has a weak effect) */ const gsl_multifit_fdfsolver_type *T; gsl_multifit_fdfsolver *s; int status; #ifdef EBUG int appNo = 0; #endif int iter; size_t i, j, n = pts->n, oldn; const size_t p = 4; gsl_matrix *covar = gsl_matrix_alloc (p, p); #ifdef EBUG double t0; #endif double *x, *y, *dy, chi, C, A, sigma, x0; if(n < 1) return; x = malloc(n * sizeof(double)); y = malloc(n * sizeof(double)); dy = malloc(n * sizeof(double)); struct data d = {n, x, y, dy}; gsl_multifit_function_fdf f; gsl_vector_view xx = gsl_vector_view_array(x_init, p); const gsl_rng_type *type; gsl_rng *r; gsl_rng_env_setup(); type = gsl_rng_default; r = gsl_rng_alloc (type); f.f = &gauss_f; f.df = &gauss_df; f.fdf = &gauss_fdf; f.n = n; f.p = p; f.params = &d; // fill data structure. Don't forget Okkam's razor!!! { Point *pt = pts->data; double *px = x, *py = y, *pdy = dy, sum = 0.; for(i = 0; i < n; i++, pt++){ *pdy++ = 1.; // I have no idea what is it, so init by 1 *px++ = pt->x; *py++ = pt->y; sum += pt->y; //DBG("point %d: (%g, %g)", i, pt->x, pt->y); } // fill x_init: x0, sigma, C, A (it can be a funtion parameter) x_init[3] = (*(--px) + *x) / 2.; x_init[2] = fabs((*x - *px) / 4.); x_init[0] = sum/(double)n; x_init[1] = sum; DBG("\nInitial parameters: x0=%.1f, sigma=%.1f, A=%.1f, C=%.1f", x_init[3], x_init[2], x_init[1], x_init[0]); } T = gsl_multifit_fdfsolver_lmder; // or also gsl_multifit_fdfsolver_lmsder s = gsl_multifit_fdfsolver_alloc(T, n, p); #ifdef EBUG t0 = dtime(); #endif do{ double dof, tres, c; DBG("\n************ Approximation %d ******************\n", appNo++); iter = 0; gsl_multifit_fdfsolver_set(s, &f, &xx.vector); do{ iter++; status = gsl_multifit_fdfsolver_iterate(s); if(status) break; status = gsl_multifit_test_delta(s->dx, s->x, epsabs, epsrel); }while(status == GSL_CONTINUE && iter < max_iter); DBG("time=%g\n", dtime()-t0); gsl_multifit_covar(s->J, 0.0, covar); chi = gsl_blas_dnrm2(s->f); dof = n - p; tres = chi; c = chi / sqrt(dof); // GSL_MAX_DBL(1., chi / sqrt(dof)); C = FIT(0), A = FIT(1), sigma = FIT(2), x0 = FIT(3); DBG("Number of iteratons = %d\n", iter); DBG("chi = %g, chi/dof = %g\n", chi, chi / sqrt(dof)); DBG("C = %.5f +/- %.5f\n", C, c*ERR(0)); DBG("A = %.5f +/- %.5f\n", A, c*ERR(1)); DBG("sigma = %.5f +/- %.5f\n", sigma, c*ERR(2)); DBG("x0 = %.5f +/- %.5f\n", x0, c*ERR(3)); j = 0; oldn = n; if(c < chi_max) break; // throw out bad (by chi) data for(i = 0; i < n; i++){ if(fabs(FN(i)) < tres){ if(i != j){ x[j] = x[i]; y[j] = y[i]; dy[j] = dy[i]; } j++; continue; } } if(j != n){ DBG("Chi tresholding %g, %zd points of %zd\n", tres, j, n); n = j; d.n = n; } }while(chi > chi_max && n != oldn && n > N_MIN); if(C_) *C_ = C; if(A_) *A_ = A; if(sigma_) *sigma_ = sigma; if(x0_) *x0_ = x0; //printf ("status = %s\n", gsl_strerror (status)); gsl_multifit_fdfsolver_free(s); gsl_matrix_free(covar); gsl_rng_free(r); free(x); free(y); free(dy); }
/******************************************************************************* * fit_gaussian * Fit data to a guassian and return the results. Ideally, this should give the * same results as scipy.optimize.curve_fit. * Input: * hist: Histogram to fit the gaussian to * Output: * chisq: Chi^2 of the histogram * ndf: Number of degrees of freedom of the fit * fit_params: Fit parameters ******************************************************************************/ gsl_vector *fit_gaussian(gsl_histogram *hist, double *chisq, long *ndf, gsl_matrix *covar){ double tol; double *hbin, *hrange, bin_width, xdata, min, max; double magnitude, mean, sigma; double error, ythr; int status; long gpars, nonzero, nbins; long i; gsl_vector *pars, *fit_params; gsl_multifit_fdfsolver *gfit; gsl_multifit_function_fdf gaus; const gsl_multifit_fdfsolver_type *ftype; /* Allowed relative error is what scipy uses */ /* tol = 1.49012e-8; scipy least squares default */ tol = 1e-14; /* get number of bins containing data */ nbins = hist -> n; hbin = hist -> bin; hrange = hist -> range; nonzero = 0; for (i=0; i<nbins; i++){ if (hbin[i]) nonzero++; } /* Set the function */ gaus.f = &gaus_f; gaus.df = &gaus_df; gaus.fdf = &gaus_fdf; gaus.n = nonzero; gaus.p = 3; gaus.params = hist; /* Initialize the solver */ gpars = 3; pars = gsl_vector_alloc(gpars); gsl_vector_set_all(pars, 1.0); ftype = gsl_multifit_fdfsolver_lmsder; gfit = gsl_multifit_fdfsolver_alloc(ftype, nonzero, gpars); gsl_multifit_fdfsolver_set(gfit, &gaus, pars); /* loop the solver and solve this thing */ do { status = gsl_multifit_fdfsolver_iterate(gfit); status = gsl_multifit_test_delta(gfit -> dx, gfit -> x, 0, tol); } while (status == GSL_CONTINUE); magnitude = gsl_vector_get(gfit -> x, 0); mean = gsl_vector_get(gfit -> x, 1); /* The fitted sigma might be negative, but it is squared when computing the * gaussian, so taking the absolute value of sigma is ok */ sigma = fabs(gsl_vector_get(gfit -> x, 2)); /* Compute the chi^2 */ min = hrange[0]; max = hrange[nbins]; bin_width = (max - min) / nbins; *chisq = 0; for (i = 0; i<nbins; i++){ if (hbin[i]){ xdata = hrange[i] + bin_width/2.0; error = sqrt(hbin[i]); ythr = gaussian(xdata, magnitude, mean, sigma); *chisq += pow((hbin[i] - ythr)/error, 2); } } *ndf = nonzero - gpars; /* Copy results to return vector */ fit_params = gsl_vector_alloc(gpars); gsl_vector_memcpy(fit_params, gfit -> x); /* Compute the covariance matrix */ gsl_multifit_covar(gfit -> J, 0.0, covar); /* Free the solver's memory */ gsl_vector_free(pars); gsl_multifit_fdfsolver_free(gfit); /* Return the results of the fit */ return fit_params; }
int K_minimize_lm(ok_kernel* k, int maxiter, double params[]) { double min_chi_par = 1e-4; K_calculate(k); double prev_chi2 = k->chi2; bool high_df = false; int max_iter_at_scale = 200; double initial_st = 1.; int max_kt = 1; for (int i = 0; i < k->ndata; i++) if (k->compiled[i][T_FLAG] == T_TIMING) { high_df = true; max_kt = 2; max_iter_at_scale = 500; break; } if (params != NULL) { int i = 0; while (true) { if (params[i] == DONE) break; if (params[i] == OPT_LM_MINCHI_PAR) min_chi_par = params[i+1]; else if (params[i] == OPT_LM_HIGH_DF) high_df = !((int) params[i+1] == 0); else if (params[i] == OPT_LM_MAX_ITER_AT_SCALE) max_iter_at_scale = (int) params[i+1]; else if (params[i] == OPT_LM_INITIAL_SCALE) initial_st = params[i+1]; i+=2; } } unsigned int npars = 0; // Count all the parameters to minimize on for (int i = 1; i < k->system->nplanets + 1; i++) for (int j = 0; j < ELEMENTS_SIZE; j++) npars += (MIGET(k->plFlags, i, j) & MINIMIZE ? 1 : 0); for (int i = 0; i < k->parFlags->size; i++) npars += (VIGET(k->parFlags, i) & MINIMIZE ? 1 : 0); if (npars == 0) return 0; // Create a pointer table (flat array -> matrices) double** pars = (double**) malloc(sizeof(double*) * npars); double prevpars[npars]; double* steps = (double*) malloc(npars * sizeof(double)); double* stepscale = (double*) malloc(npars * sizeof(double)); int* parstype = (int*) malloc(npars * sizeof(int)); gsl_vector* x = gsl_vector_alloc(npars); int idx = 0; for (int i = 1; i < k->system->nplanets + 1; i++) for (int j = 0; j < ELEMENTS_SIZE; j++) if (MIGET(k->plFlags, i, j) & MINIMIZE) { pars[idx] = gsl_matrix_ptr(k->system->elements, i, j); x->data[idx] = MGET(k->system->elements, i, j); prevpars[idx] = x->data[idx]; steps[idx] = stepscale[idx] = MGET(k->plSteps, i, j); parstype[idx] = j; if (steps[idx] < 1e-10) { printf("Warning: step for element %d of planet %d is <= 0\n", j, i); } idx++; } for (int i = 0; i < k->parFlags->size; i++) if (VIGET(k->parFlags, i) & MINIMIZE) { pars[idx] = gsl_vector_ptr(k->params, i); x->data[idx] = VGET(k->params, i); prevpars[idx] = x->data[idx]; steps[idx] = stepscale[idx] = VGET(k->parSteps, i); parstype[idx] = PARTYPE_PAR; if (steps[idx] < 1e-10) printf("Warning: step for parameter %d is <= 0\n", i); idx++; } gsl_multifit_fdfsolver * s = gsl_multifit_fdfsolver_alloc (gsl_multifit_fdfsolver_lmsder, k->ndata, npars); ok_lm_params sp; sp.k = k; sp.pars = pars; sp.best = (double*) malloc(sizeof(double) * npars); sp.stepscale = stepscale; sp.compiled = k->compiled; sp.f0 = (double*) malloc(sizeof(double)*k->ndata); sp.f1 = (double*) malloc(sizeof(double)*k->ndata); sp.f2 = (double*) malloc(sizeof(double)*k->ndata); sp.f3 = (double*) malloc(sizeof(double)*k->ndata); sp.parstype = parstype; sp.ndata = k->ndata; sp.iterations = 0; sp.maxiterations = maxiter; sp.npars = npars; sp.every = (k->intMethod == KEPLER ? 10 : 1); sp.status = PROGRESS_CONTINUE; sp.high_df = high_df; sp.min_chi = k->chi2; sp.st = initial_st; for (int i = 0; i < npars; i++) sp.best[i] = *(pars[i]); gsl_multifit_function_fdf fdf; fdf.f = &K_lm_f; fdf.df = &K_lm_jac; fdf.fdf = &K_lm_fdf; fdf.n = k->ndata; fdf.p = npars; fdf.params = &sp; gsl_multifit_fdfsolver_set (s, &fdf, x); bool improved = true; int status = 0; int kt = 0; int tot_iter = 0; int iter_at_scale = 0; bool last_ditch = false; while (improved || last_ditch) { k->flags |= NEEDS_SETUP; iter_at_scale = 0; while (true) { double chi2 = sp.min_chi; int status = gsl_multifit_fdfsolver_iterate (s); iter_at_scale++; tot_iter++; if (chi2 - sp.min_chi > min_chi_par) iter_at_scale = 0; if (status || iter_at_scale > max_iter_at_scale) { break; } } gsl_multifit_fdfsolver_set (s, &fdf, x); for (int i = 0; i < npars; i++) { *(pars[i]) = sp.best[i]; x->data[i] = sp.best[i]; } k->flags |= NEEDS_SETUP; K_calculate(k); if (fabs(prev_chi2 - sp.min_chi)/fabs(sp.min_chi) > 1e-2 && iter_at_scale > 1) { kt = 0; last_ditch = false; } else { sp.st *= 0.1; } improved = (kt < max_kt || fabs(sp.min_chi - prev_chi2)/fabs(sp.min_chi) > 1e-2); if (last_ditch) break; if (! improved && kt <= 3) { last_ditch = true; sp.st *= 0.1; } kt++; //printf("-> %d %d %d %e %e, last_ditch=%d\n", iter_at_scale, kt, improved, sp.st, sp.min_chi, last_ditch); prev_chi2 = k->chi2; for (int idx = 0; idx < npars; idx++) stepscale[idx] = steps[idx] * sp.st; if (sp.iterations > maxiter || sp.st < 1e-12) break; } for (int i = 0; i < npars; i++) { *(pars[i]) = sp.best[i]; x->data[i] = sp.best[i]; } k->flags |= NEEDS_SETUP; K_calculate(k); free(sp.stepscale); free(sp.f0); free(sp.f1); free(sp.f2); free(sp.f3); free(sp.pars); free(sp.parstype); free(sp.best); if (sp.status == PROGRESS_STOP) return PROGRESS_STOP; else return status; }
static int MLalgo(struct dataStruct *data) { /* declare solvers */ const gsl_multifit_fdfsolver_type *T; gsl_multifit_fdfsolver *s; gsl_vector_view x = gsl_vector_view_array(data->x_init, data->np); const gsl_rng_type *type; gsl_rng_env_setup(); type = gsl_rng_default; gsl_multifit_function_fdf f; f.f = &gaussian_f; f.df = &gaussian_df; f.fdf = &gaussian_fdf; f.n = data->nValid; f.p = data->np; f.params = data; T = gsl_multifit_fdfsolver_lmsder; s = gsl_multifit_fdfsolver_alloc(T, data->nValid, data->np); gsl_multifit_fdfsolver_set(s, &f, &x.vector); int status, status2; int iter = 0; gsl_vector *gradt = gsl_vector_alloc(data->np); do { iter++; status = gsl_multifit_fdfsolver_iterate(s); if (status) break; status = gsl_multifit_test_delta(s->dx, s->x, data->eAbs, data->eRel); gsl_multifit_gradient(s->J, s->f, gradt); status2 = gsl_multifit_test_gradient(gradt, data->eAbs); } while ((status == GSL_CONTINUE || status2 == GSL_CONTINUE) && iter < data->maxIter); gsl_vector_free(gradt); int i; for (i=0; i<data->np; ++i) { data->prmVect[data->estIdx[i]] = gsl_vector_get(s->x, i); } data->prmVect[3] = fabs(data->prmVect[3]); /* copy residuals */ data->residuals = gsl_vector_alloc(data->nValid); gsl_vector_memcpy(data->residuals, s->f); /* copy Jacobian */ data->J = gsl_matrix_alloc(data->nValid, data->np); gsl_matrix_memcpy(data->J, s->J); gsl_multifit_fdfsolver_free(s); return 0; }
void test_fdf (const char * name, gsl_multifit_function_fdf * f, double x0[], double x_final[], double f_sumsq, double sigma[]) { const gsl_multifit_fdfsolver_type *T; gsl_multifit_fdfsolver *s; const size_t n = f->n; const size_t p = f->p; int status; size_t iter = 0; gsl_vector_view x = gsl_vector_view_array (x0, p); T = gsl_multifit_fdfsolver_lmsder; s = gsl_multifit_fdfsolver_alloc (T, n, p); gsl_multifit_fdfsolver_set (s, f, &x.vector); do { status = gsl_multifit_fdfsolver_iterate (s); #ifdef DEBUG printf("iter = %d status = %d |f| = %.18e x = \n", iter, status, gsl_blas_dnrm2 (s->f)); gsl_vector_fprintf(stdout, s->x, "%.8e"); #endif status = gsl_multifit_test_delta (s->dx, s->x, 0.0, 1e-7); iter++; } while (status == GSL_CONTINUE && iter < 1000); { size_t i; gsl_matrix * covar = gsl_matrix_alloc (p, p); gsl_multifit_covar (s->J, 0.0, covar); for (i = 0 ; i < p; i++) { gsl_test_rel (gsl_vector_get (s->x, i), x_final[i], 1e-5, "%s, lmsder, x%u", name, i); } { double s2 = pow(gsl_blas_dnrm2 (s->f), 2.0); gsl_test_rel (s2, f_sumsq, 1e-5, "%s, lmsder, |f|^2", name); for (i = 0; i < p; i++) { double ei = sqrt(s2/(n-p))*sqrt(gsl_matrix_get(covar,i,i)); gsl_test_rel (ei, sigma[i], 1e-4, "%s, sigma(%d)", name, i) ; } } gsl_matrix_free (covar); } gsl_multifit_fdfsolver_free (s); }
f_all_sol do_fit_duplex(f_info *f, int n, real *t_min, real *t_max, bool bVerbose, bool bUpdate) { int i,j,k; int iter=0; int tot_points=0; int status; int tot_abs=0; int tot_inv_t=0; real inv_t=0; real tss_inv=0; real mean_inv_t=0; real abs_t=0; real mean_abs_t=0; real tss_abs=0; real tss_tot=0; f_all_sol fit; f_info *local_f; snew(local_f,n); // count points within boundaries, allocate // and copy to new array. Only copy the xp (derivative) // as is the one that matters for the fitting for(i=0; i<n; i++){ for(j=0; j<f[i].nts; j++){ if( f[i].xp[0][j] >= t_min[i] && f[i].xp[0][j] <= t_max[i] ) { local_f[i].nts++ ; } } snew(local_f[i].xp[0],local_f[i].nts); snew(local_f[i].xp[1],local_f[i].nts); } // now copy the data // not only the derivatives of the absorbance, also the conc k=0; for(i=0; i<n; i++){ local_f[i].conc = f[i].conc ; for(j=0; j<f[i].nts; j++){ if( f[i].xp[0][j] >= t_min[i] && f[i].xp[0][j] <= t_max[i] ) { local_f[i].xp[0][k] = f[i].xp[0][j] ; local_f[i].xp[1][k] = f[i].xp[1][j] ; // we use this loop to compute the TSS, the total sum of squares of the // "y" data, to be used for r_squared after we know chi_sq abs_t += local_f[i].xp[1][k] ; tot_abs++; k++; } } k=0; } // Total number of points to fit size_t pp = 4; const gsl_multifit_fdfsolver_type *T; T = gsl_multifit_fdfsolver_lmsder; gsl_multifit_fdfsolver *s; // do a fit for each triplex curve for (i=0; i<n; i++){ // Total number of points to fit if (bVerbose){printf("Working on curve n %d\n",i);} struct fit_data d = { n,i, local_f}; tot_points = local_f[i].nts ; gsl_matrix *covar = gsl_matrix_alloc (pp, pp); gsl_multifit_function_fdf ff; gsl_vector *x; x = gsl_vector_alloc(pp); gsl_vector_set(x,0,f[i].tm2); gsl_vector_set(x,1,f[i].c); gsl_vector_set(x,2,-70); gsl_vector_set(x,3,-0.1); s = gsl_multifit_fdfsolver_alloc (T, tot_points, pp); // copy data to function ff.f = &eq_fit; ff.df = NULL; ff.fdf = NULL; ff.p = pp; // total number of points is total of points // in the curve plus the number of points for the inv. fit ff.n = tot_points; ff.params = &d; gsl_multifit_fdfsolver_set (s, &ff, x); iter=0; do { iter++; status = gsl_multifit_fdfsolver_iterate (s); if(bVerbose){ printf ("iter: %3u x = % 15.8f % 15.8f %15.8f " "|f(x)| = %g\n",iter, gsl_vector_get (s->x, 0), gsl_vector_get (s->x, 1), gsl_vector_get (s->x, 2), gsl_blas_dnrm2 (s->f)); } if (status) break; status = gsl_multifit_test_delta (s->dx, s->x, 1e-8, 1e-8); } while (status == GSL_CONTINUE && iter < 500); gsl_multifit_covar (s->J, 0.0, covar); gsl_matrix_free (covar); gsl_vector_free(x); // copy tm2 data adjusted from each curve local_f[i].tm2 = gsl_vector_get(s->x, 0); } //free first solver gsl_multifit_fdfsolver_free (s); // do the 1/tm vs ln(ct) fitting const gsl_multifit_fdfsolver_type *Tl; gsl_multifit_fdfsolver *sl; // fit params in the straight line int ppl = 2; gsl_matrix *covarl = gsl_matrix_alloc (ppl, ppl); struct fit_data dl = { n,i, local_f}; gsl_multifit_function_fdf ffl; gsl_vector *xl; xl = gsl_vector_alloc(ppl); // DH and DS gsl_vector_set(xl,0,-70); gsl_vector_set(xl,1,-0.1); Tl = gsl_multifit_fdfsolver_lmsder; sl = gsl_multifit_fdfsolver_alloc (Tl, n, ppl); // copy data to function ffl.f=&eq_fit_straight; ffl.df = NULL; ffl.fdf = NULL; ffl.p = ppl; // total number of points the number of curves ffl.n = n; ffl.params = &dl; gsl_multifit_fdfsolver_set (sl, &ffl, xl); iter=0; do { iter++; status = gsl_multifit_fdfsolver_iterate (sl); if(bVerbose){ printf ("iter: %3u x = % 15.8f % 15.8f " "|f(x)| = %g\n",iter, gsl_vector_get (sl->x, 0), gsl_vector_get (sl->x, 1), gsl_blas_dnrm2 (sl->f)); } if (status) break; status = gsl_multifit_test_delta (sl->dx, sl->x, 1e-8, 1e-8); } while (status == GSL_CONTINUE && iter < 500); gsl_multifit_covar (sl->J, 0.0, covarl); #define FIT(i) gsl_vector_get(sl->x, i) #define ERR(i) sqrt(gsl_matrix_get(covarl,i,i)) // compute contribution of inverse temperature to TSS for(i=0;i<n;i++){ inv_t += ((real)1.0/(real)local_f[i].tm2); tot_inv_t++; } mean_inv_t = inv_t / (real)tot_inv_t; for(i=0;i<n;i++){ tss_inv += (1.0/(real)local_f[i].tm2 - mean_inv_t ) * (1.0/(real)local_f[i].tm2 - mean_inv_t); } if (bUpdate){ fit.dh2 = gsl_vector_get(sl->x, 0); fit.ds2 = gsl_vector_get(sl->x, 1); fit.dg2 = fit.dh2 - 298.15*fit.ds2; for(i=0; i<n; i++){ f[i].tm2 = local_f[i].tm2 ; } } tss_tot = tss_inv ; double chi = gsl_blas_dnrm2(sl->f); fit.r2 = 1.0 - ( chi*chi / tss_tot ) ; double dof = n - ppl; double c = GSL_MAX_DBL(1, chi / sqrt(dof)); if(bVerbose) { printf ("chisq/dof = %g\n", pow(chi, 2.0) / dof); printf ("r2 = %g\n", fit.r2); printf ("DH3 = %.5f +/- %.5f\n", FIT(0), c*ERR(0)); printf ("DS3 = %.5f +/- %.5f\n", FIT(1), c*ERR(1)); printf ("DG3 = %.5f +/- %.5f\n", FIT(0)-298*FIT(1),c*ERR(1)+c*298*ERR(0)); printf ("status = %s\n", gsl_strerror (status)); } gsl_multifit_fdfsolver_free (sl); gsl_matrix_free (covarl); gsl_vector_free(xl); return fit; }
int OptimizationOptions::gslOptimize( NLSFunction *F, gsl_vector* x_vec, gsl_matrix *v, IterationLogger *itLog ) { const gsl_multifit_fdfsolver_type *Tlm[] = { gsl_multifit_fdfsolver_lmder, gsl_multifit_fdfsolver_lmsder }; const gsl_multimin_fdfminimizer_type *Tqn[] = { gsl_multimin_fdfminimizer_vector_bfgs, gsl_multimin_fdfminimizer_vector_bfgs2, gsl_multimin_fdfminimizer_conjugate_fr, gsl_multimin_fdfminimizer_conjugate_pr }; const gsl_multimin_fminimizer_type *Tnm[] = { gsl_multimin_fminimizer_nmsimplex, gsl_multimin_fminimizer_nmsimplex2, gsl_multimin_fminimizer_nmsimplex2rand }; int gsl_submethod_max[] = { sizeof(Tlm) / sizeof(Tlm[0]), sizeof(Tqn) / sizeof(Tqn[0]), sizeof(Tnm) / sizeof(Tnm[0]) }; int status, status_dx, status_grad, k; double g_norm, x_norm; /* vectorize x row-wise */ size_t max_ind, min_ind; double max_val, min_val, abs_max_val = 0, abs_min_val; if (this->method < 0 || this->method > sizeof(gsl_submethod_max)/sizeof(gsl_submethod_max[0]) || this->submethod < 0 || this->submethod > gsl_submethod_max[this->method]) { throw new Exception("Unknown optimization method.\n"); } if (this->maxiter < 0 || this->maxiter > 5000) { throw new Exception("opt.maxiter should be in [0;5000].\n"); } /* LM */ gsl_multifit_fdfsolver* solverlm; gsl_multifit_function_fdf fdflm = { &(F->_f_ls), &(F->_df_ls), &(F->_fdf_ls), F->getNsq(), F->getNvar(), F }; gsl_vector *g; /* QN */ double stepqn = this->step; gsl_multimin_fdfminimizer* solverqn; gsl_multimin_function_fdf fdfqn = { &(F->_f), &(F->_df), &(F->_fdf), F->getNvar(), F }; /* NM */ double size; gsl_vector *stepnm; gsl_multimin_fminimizer* solvernm; gsl_multimin_function fnm = { &(F->_f), F->getNvar(), F }; /* initialize the optimization method */ switch (this->method) { case SLRA_OPT_METHOD_LM: /* LM */ solverlm = gsl_multifit_fdfsolver_alloc(Tlm[this->submethod], F->getNsq(), F->getNvar()); gsl_multifit_fdfsolver_set(solverlm, &fdflm, x_vec); g = gsl_vector_alloc(F->getNvar()); break; case SLRA_OPT_METHOD_QN: /* QN */ solverqn = gsl_multimin_fdfminimizer_alloc(Tqn[this->submethod], F->getNvar() ); gsl_multimin_fdfminimizer_set(solverqn, &fdfqn, x_vec, stepqn, this->tol); status_dx = GSL_CONTINUE; break; case SLRA_OPT_METHOD_NM: /* NM */ solvernm = gsl_multimin_fminimizer_alloc(Tnm[this->submethod], F->getNvar()); stepnm = gsl_vector_alloc(F->getNvar()); gsl_vector_set_all(stepnm, this->step); gsl_multimin_fminimizer_set( solvernm, &fnm, x_vec, stepnm ); break; } /* optimization loop */ Log::lprintf(Log::LOG_LEVEL_FINAL, "SLRA optimization:\n"); status = GSL_SUCCESS; status_dx = GSL_CONTINUE; status_grad = GSL_CONTINUE; this->iter = 0; switch (this->method) { case SLRA_OPT_METHOD_LM: gsl_blas_ddot(solverlm->f, solverlm->f, &this->fmin); gsl_multifit_gradient(solverlm->J, solverlm->f, g); gsl_vector_scale(g, 2); { gsl_vector *g2 = gsl_vector_alloc(g->size); F->computeFuncAndGrad(x_vec, NULL, g2); gsl_vector_sub(g2, g); if (gsl_vector_max(g2) > 1e-10 || gsl_vector_min(g2) < -1e-10) { Log::lprintf(Log::LOG_LEVEL_NOTIFY, "Gradient error, max = %14.10f, min = %14.10f ...", gsl_vector_max(g2), gsl_vector_min(g2)); print_vec(g2); } gsl_vector_free(g2); } if (itLog != NULL) { itLog->reportIteration(0, solverlm->x, this->fmin, g); } break; case SLRA_OPT_METHOD_QN: this->fmin = gsl_multimin_fdfminimizer_minimum(solverqn); if (itLog != NULL) { itLog->reportIteration(0, solverqn->x, this->fmin, solverqn->gradient); } break; case SLRA_OPT_METHOD_NM: this->fmin = gsl_multimin_fminimizer_minimum( solvernm ); if (itLog != NULL) { itLog->reportIteration(this->iter, solvernm->x, this->fmin, NULL); } break; } while (status_dx == GSL_CONTINUE && status_grad == GSL_CONTINUE && status == GSL_SUCCESS && this->iter < this->maxiter) { if (this->method == SLRA_OPT_METHOD_LM && this->maxx > 0) { if (gsl_vector_max(solverlm->x) > this->maxx || gsl_vector_min(solverlm->x) < -this->maxx ){ break; } } this->iter++; switch (this->method) { case SLRA_OPT_METHOD_LM: /* Levenberg-Marquardt */ status = gsl_multifit_fdfsolver_iterate(solverlm); gsl_multifit_gradient(solverlm->J, solverlm->f, g); gsl_vector_scale(g, 2); /* check the convergence criteria */ if (this->epsabs != 0 || this->epsrel != 0) { status_dx = gsl_multifit_test_delta(solverlm->dx, solverlm->x, this->epsabs, this->epsrel); } else { status_dx = GSL_CONTINUE; } status_grad = gsl_multifit_test_gradient(g, this->epsgrad); gsl_blas_ddot(solverlm->f, solverlm->f, &this->fmin); if (itLog != NULL) { itLog->reportIteration(this->iter, solverlm->x, this->fmin, g); } break; case SLRA_OPT_METHOD_QN: status = gsl_multimin_fdfminimizer_iterate( solverqn ); /* check the convergence criteria */ status_grad = gsl_multimin_test_gradient( gsl_multimin_fdfminimizer_gradient(solverqn), this->epsgrad); status_dx = gsl_multifit_test_delta(solverqn->dx, solverqn->x, this->epsabs, this->epsrel); this->fmin = gsl_multimin_fdfminimizer_minimum(solverqn); if (itLog != NULL) { itLog->reportIteration(this->iter, solverqn->x, this->fmin, solverqn->gradient); } break; case SLRA_OPT_METHOD_NM: status = gsl_multimin_fminimizer_iterate( solvernm ); /* check the convergence criteria */ size = gsl_multimin_fminimizer_size( solvernm ); status_dx = gsl_multimin_test_size( size, this->epsx ); this->fmin = gsl_multimin_fminimizer_minimum( solvernm ); if (itLog != NULL) { itLog->reportIteration(this->iter, solvernm->x, this->fmin, NULL); } break; } } if (this->iter >= this->maxiter) { status = EITER; } switch (this->method) { case SLRA_OPT_METHOD_LM: gsl_vector_memcpy(x_vec, solverlm->x); if (v != NULL) { gsl_multifit_covar(solverlm->J, this->epscov, v); /* ??? Different eps */ } gsl_blas_ddot(solverlm->f, solverlm->f, &this->fmin); break; case SLRA_OPT_METHOD_QN: gsl_vector_memcpy(x_vec, solverqn->x); this->fmin = solverqn->f; break; case SLRA_OPT_METHOD_NM: gsl_vector_memcpy(x_vec, solvernm->x); this->fmin = solvernm->fval; break; } /* print exit information */ if (Log::getMaxLevel() >= Log::LOG_LEVEL_FINAL) { /* unless "off" */ switch (status) { case EITER: Log::lprintf("SLRA optimization terminated by reaching " "the maximum number of iterations.\n" "The result could be far from optimal.\n"); break; case GSL_ETOLF: Log::lprintf("Lack of convergence: " "progress in function value < machine EPS.\n"); break; case GSL_ETOLX: Log::lprintf("Lack of convergence: " "change in parameters < machine EPS.\n"); break; case GSL_ETOLG: Log::lprintf("Lack of convergence: " "change in gradient < machine EPS.\n"); break; case GSL_ENOPROG: Log::lprintf("Possible lack of convergence: no progress.\n"); break; } if (status_grad != GSL_CONTINUE && status_dx != GSL_CONTINUE) { Log::lprintf("Optimization terminated by reaching the convergence " "tolerance for both X and the gradient.\n"); } else { if (status_grad != GSL_CONTINUE) { Log::lprintf("Optimization terminated by reaching the convergence " "tolerance for the gradient.\n"); } else { Log::lprintf("Optimization terminated by reaching the convergence " "tolerance for X.\n"); } } } /* Cleanup */ switch (this->method) { case SLRA_OPT_METHOD_LM: /* LM */ gsl_multifit_fdfsolver_free(solverlm); gsl_vector_free(g); break; case SLRA_OPT_METHOD_QN: /* QN */ gsl_multimin_fdfminimizer_free(solverqn); break; case SLRA_OPT_METHOD_NM: /* NM */ gsl_multimin_fminimizer_free(solvernm); gsl_vector_free(stepnm); break; } return GSL_SUCCESS; /* <- correct with status */ }
int kstfit_general_levenberg_marquardt(const double *const inArrays[], const int inArrayLens[], const double inScalars[], double *outArrays[], int outArrayLens[], double outScalars[], const char* inStrings[], char *outStrings[]) { KST_UNUSED(outStrings); int iReturn = -1; if (inArrayLens[X] >= 2 && inArrayLens[Y] >= 2) { mu::Parser parser; double* pResult[4]; double* pDelete = 0L; double* pInputX; double* pInputY; double *parameters; double tolerance = inScalars[0]; double xvar; char *token; char *toSplit; char *endPtr; int maxIterations = (int)inScalars[1]; int n = inArrayLens[0]; int paramsNumber = 2; int startsNumber = 0; int iLengthData; int i; int j; iLengthData = inArrayLens[X]; if( inArrayLens[Y] > iLengthData ) { iLengthData = inArrayLens[Y]; } if (inArrayLens[X] == iLengthData) { pInputX = (double*)inArrays[X]; } else { pDelete = (double*)malloc(iLengthData * sizeof( double )); pInputX = pDelete; for( i=0; i<iLengthData; i++) { pInputX[i] = interpolate( i, iLengthData, inArrays[X], inArrayLens[X] ); } } if (inArrayLens[Y] == iLengthData) { pInputY = (double*)inArrays[Y]; } else { pDelete = (double*)malloc(iLengthData * sizeof( double )); pInputY = pDelete; for( i=0; i<iLengthData; i++) { pInputY[i] = interpolate( i, iLengthData, inArrays[Y], inArrayLens[Y] ); } } // // count the number of parameter names // toSplit = strdup(inStrings[1]); token = strtok( toSplit, ",;:" ); while( token != NULL ) { paramsNumber++; token = strtok( NULL, ",;:" ); } free(toSplit); if( iLengthData > paramsNumber ) { if( outArrayLens[0] != iLengthData ) { pResult[0] = (double*)realloc( outArrays[0], iLengthData * sizeof( double ) ); } else { pResult[0] = outArrays[0]; } if( outArrayLens[1] != iLengthData ) { pResult[1] = (double*)realloc( outArrays[1], iLengthData * sizeof( double ) ); } else { pResult[1] = outArrays[1]; } if( outArrayLens[2] != paramsNumber ) { pResult[2] = (double*)realloc( outArrays[2], paramsNumber * sizeof( double ) ); } else { pResult[2] = outArrays[2]; } if( outArrayLens[3] != paramsNumber * paramsNumber ) { pResult[3] = (double*)realloc( outArrays[3], paramsNumber * paramsNumber * sizeof( double ) ); } else { pResult[3] = outArrays[3]; } if( pResult[0] != NULL && pResult[1] != NULL && pResult[2] != NULL && pResult[3] != NULL ) { outArrays[0] = pResult[0]; outArrayLens[0] = iLengthData; outArrays[1] = pResult[1]; outArrayLens[1] = iLengthData; outArrays[2] = pResult[2]; outArrayLens[2] = paramsNumber; outArrays[3] = pResult[3]; outArrayLens[3] = paramsNumber * paramsNumber; parameters = new double[paramsNumber]; for (i=0; i<paramsNumber; i++) { parameters[i] = 0.0; } paramsNumber = 0; // // set the parameter names // toSplit = strdup(inStrings[1]); token = strtok( toSplit, ",;:" ); while( token != NULL ) { char *paramName = strdup(token); char *paramPointer = paramName; while (paramPointer[0] == ' ') { paramPointer++; } while (paramPointer[strlen(paramPointer)] == ' ') { paramPointer[strlen(paramPointer)] = '\0'; } try { parser.DefineVar(paramPointer, ¶meters[paramsNumber]); } catch (mu::Parser::exception_type &e) { } paramsNumber++; token = strtok( NULL, ",;:" ); free( paramName ); } free(toSplit); // // set parameter initial guesses // double pInit[paramsNumber]; toSplit = strdup(inStrings[2]); token = strtok( toSplit, ",;:" ); while( token != NULL ) { pInit[startsNumber] = strtod(token, &endPtr); startsNumber++; token = strtok( NULL, ",;:" ); } free(toSplit); for (i=startsNumber; i<paramsNumber; i++) { pInit[i] = 0.0; } if (strstr(inStrings[0], "pi") != 0L) { parser.DefineConst("pi", M_PI); } if (strstr(inStrings[0], "Pi") != 0L) { parser.DefineConst("Pi", M_PI); } if (strstr(inStrings[0], "PI") != 0L) { parser.DefineConst("PI", M_PI); } parser.DefineVar("x", &xvar); parser.SetExpr(inStrings[0]); gsl_vector_view x = gsl_vector_view_array(pInit, paramsNumber); struct fit d = { n, inArrays[0], inArrays[1], outArrays[0], &xvar, parameters, paramsNumber, &parser }; const gsl_multifit_fdfsolver_type *T = gsl_multifit_fdfsolver_lmsder; gsl_multifit_fdfsolver *s = gsl_multifit_fdfsolver_alloc(T, n, paramsNumber); if (s != 0L) { gsl_multifit_function_fdf f; gsl_matrix *covar = gsl_matrix_alloc(paramsNumber, paramsNumber); if (covar != 0L) { f.f = &function_f; f.df = &function_df; f.fdf = &function_fdf; f.n = n; f.p = paramsNumber; f.params = &d; gsl_multifit_fdfsolver_set(s, &f, &x.vector); int status; int iteration = 0; do { iteration++; status = gsl_multifit_fdfsolver_iterate(s); if (status) { break; } status = gsl_multifit_test_delta(s->dx, s->x, tolerance, tolerance); } while (status == GSL_CONTINUE && iteration < maxIterations); gsl_multifit_covar(s->J, 0.0, covar); for( i=0; i<n; i++ ) { xvar = inArrays[0][i]; try { outArrays[0][i] = parser.Eval(); outArrays[1][i] = inArrays[1][i] - outArrays[0][i]; } catch (mu::Parser::exception_type &e) { outArrays[0][i] = 0.0; outArrays[1][i] = 0.0; } } for (i=0; i<paramsNumber; i++) { outArrays[2][i] = parameters[i]; for (j=0; j<paramsNumber; j++) { outArrays[3][(i*paramsNumber)+j] = gsl_matrix_get( covar, i, j ); } } // // determine the value of chi^2/nu // outScalars[0] = gsl_blas_dnrm2( s->f ); iReturn = 0; gsl_matrix_free(covar); } gsl_multifit_fdfsolver_free(s); } } } if( pDelete ) { free( pDelete ); } } return iReturn; }
static void test_fdf(const gsl_multifit_fdfsolver_type * T, const double xtol, const double gtol, const double ftol, const double epsrel, const double x0_scale, test_fdf_problem *problem, const double *wts) { gsl_multifit_function_fdf *fdf = problem->fdf; const size_t n = fdf->n; const size_t p = fdf->p; const size_t max_iter = 1500; gsl_vector *x0 = gsl_vector_alloc(p); gsl_vector_view x0v = gsl_vector_view_array(problem->x0, p); gsl_multifit_fdfsolver *s = gsl_multifit_fdfsolver_alloc (T, n, p); const char *pname = problem->name; char sname[2048]; int status, info; sprintf(sname, "%s/scale=%g%s", gsl_multifit_fdfsolver_name(s), x0_scale, problem->fdf->df ? "" : "/fdiff"); /* scale starting point x0 */ gsl_vector_memcpy(x0, &x0v.vector); test_scale_x0(x0, x0_scale); if (wts) { gsl_vector_const_view wv = gsl_vector_const_view_array(wts, n); gsl_multifit_fdfsolver_wset(s, fdf, x0, &wv.vector); } else gsl_multifit_fdfsolver_set(s, fdf, x0); status = gsl_multifit_fdfsolver_driver(s, max_iter, xtol, gtol, ftol, &info); gsl_test(status, "%s/%s did not converge, status=%s", sname, pname, gsl_strerror(status)); /* check solution */ test_fdf_checksol(sname, pname, epsrel, s, problem); if (wts == NULL) { /* test again with weighting matrix W = I */ gsl_vector *wv = gsl_vector_alloc(n); sprintf(sname, "%s/scale=%g%s/weights", gsl_multifit_fdfsolver_name(s), x0_scale, problem->fdf->df ? "" : "/fdiff"); gsl_vector_memcpy(x0, &x0v.vector); test_scale_x0(x0, x0_scale); gsl_vector_set_all(wv, 1.0); gsl_multifit_fdfsolver_wset(s, fdf, x0, wv); status = gsl_multifit_fdfsolver_driver(s, max_iter, xtol, gtol, ftol, &info); gsl_test(status, "%s/%s did not converge, status=%s", sname, pname, gsl_strerror(status)); test_fdf_checksol(sname, pname, epsrel, s, problem); gsl_vector_free(wv); } gsl_multifit_fdfsolver_free(s); gsl_vector_free(x0); }
gsl_vector* least_square_nl_fit(struct data dat, struct parameters par, gsl_multifit_function_fdf f) { size_t n, p; int status, i, iter = 0; double *x_init; const gsl_rng_type * type; const gsl_multifit_fdfsolver_type *T; gsl_multifit_fdfsolver *s; n = dat.n; p = par.n; gsl_matrix *covar = gsl_matrix_alloc(p,p); x_init = (double *) calloc(par.n, sizeof(double)); for(i=0; i<par.n; i++) x_init[i] = par.guess_p[i]; gsl_vector_view x = gsl_vector_view_array (x_init, p); gsl_rng * r; gsl_rng_env_setup(); type = gsl_rng_default; r = gsl_rng_alloc (type); T = gsl_multifit_fdfsolver_lmsder; s = gsl_multifit_fdfsolver_alloc(T, n, p); gsl_multifit_fdfsolver_set(s, &f, &x.vector); #ifdef PRINT_INFO print_state (iter, s); #endif do { iter++; status = gsl_multifit_fdfsolver_iterate (s); #ifdef PRINT_INFO print_state (iter, s); #endif if (status) break; status = gsl_multifit_test_delta (s->dx, s->x, 1e-6, 1e-6); } while (status == GSL_CONTINUE && iter < 500); #ifdef PRINT_INFO print_state (iter, s); #endif gsl_multifit_covar (s->J, 0.0, covar); { gsl_matrix_free (covar); gsl_rng_free (r); } return s->x; gsl_multifit_fdfsolver_free (s); }
SEXP multifit_cor(SEXP par, SEXP Thalf, SEXP x, SEXP y, SEXP err, SEXP tr, SEXP prec, SEXP N, SEXP max_iter, SEXP no_masses) { int npar, nx, ny, i, iter_max; double p1, p2, m; double *yp, *errp, *parp, *precp, *statep; double chi_square, red_chi_square; int dof; int * xp, *Thalfp, *trp, *Np, *mip, *nmp; SEXP state; const gsl_multifit_fdfsolver_type *solver_type = gsl_multifit_fdfsolver_lmsder; /* Allocate the solver. */ gsl_multifit_fdfsolver *solver; /* Initialize the data structure. */ struct data data_struct; gsl_multifit_function_fdf function_fdf; gsl_matrix *covar; double * para_initial, c=1.; gsl_vector_view para_initial_; int status, iter=0, no_points=0; PROTECT(par = AS_NUMERIC(par)); PROTECT(Thalf = AS_INTEGER(Thalf)); PROTECT(x = AS_INTEGER(x)); PROTECT(y = AS_NUMERIC(y)); PROTECT(err = AS_NUMERIC(err)); PROTECT(tr = AS_INTEGER(tr)); PROTECT(prec = AS_NUMERIC(prec)); PROTECT(N = AS_INTEGER(N)); PROTECT(max_iter = AS_INTEGER(max_iter)); PROTECT(no_masses = AS_INTEGER(no_masses)); xp = INTEGER_POINTER(x); Thalfp = INTEGER_POINTER(Thalf); trp = INTEGER_POINTER(tr); Np = INTEGER_POINTER(N); yp = NUMERIC_POINTER(y); errp = NUMERIC_POINTER(err); parp = NUMERIC_POINTER(par); precp = NUMERIC_POINTER(prec); mip = INTEGER_POINTER(max_iter); nmp = INTEGER_POINTER(no_masses); iter_max = mip[0]; npar = LENGTH(par); nx = LENGTH(x); ny = LENGTH(y); assert(npar == nmp[0]*(Np[0]+1)); PROTECT(state = NEW_NUMERIC(5+npar)); statep = NUMERIC_POINTER(state); /* PROTECT(gradient = allocMatrix(REALSXP, npar, npar)); */ if(Np[0] == 2) no_points = 3*trp[0]; if(Np[0] == 4) no_points = 10*trp[0]; if(Np[0] == 6) no_points = 21*trp[0]; solver = gsl_multifit_fdfsolver_alloc(solver_type, ny, npar); data_struct.x = (double*) malloc(nx*sizeof(double)); data_struct.y = (double*) malloc(ny*sizeof(double)); data_struct.err = (double*) malloc(ny*sizeof(double)); para_initial = (double*) malloc(npar*sizeof(double)); for(i = 0; i < nx; i++) { data_struct.x[i] = (double)xp[i]; } for(i = 0; i < ny; i++) { data_struct.y[i] = yp[i]; data_struct.err[i] = errp[i]; } data_struct.Thalf = Thalfp[0]; data_struct.tr = trp[0]; data_struct.N = Np[0]; data_struct.no_masses = nmp[0]; // The ansatz. function_fdf.f = &exp_f; function_fdf.df = &exp_df; function_fdf.fdf = &exp_fdf; function_fdf.n = ny; function_fdf.p = npar; function_fdf.params = &data_struct; for(i = 0; i < npar; i++) { para_initial[i] = parp[i]; } para_initial_ = gsl_vector_view_array(para_initial, npar); gsl_multifit_fdfsolver_set(solver, &function_fdf, ¶_initial_.vector); // Perform the fit. // Print the initial state. #ifdef _DEBUG Print_State_Mass_Fit_Helper_1(iter, solver); #endif do { iter++; /* Do a solver iteration. */ status = gsl_multifit_fdfsolver_iterate(solver); #ifdef _DEBUG fprintf(stderr, "status = %s.\n", gsl_strerror(status)); Print_State_Mass_Fit_Helper_1(iter, solver); #endif if(status) { break; } status = gsl_multifit_test_delta(solver->dx, solver->x, precp[0], precp[1]); } while(status == GSL_CONTINUE && iter < iter_max); #ifdef _DEBUG fprintf(stderr, "\n"); #endif // ***** // Compute the covariance matrix. covar = gsl_matrix_alloc(npar, npar); gsl_multifit_covar(solver->J, 0.0, covar); // Output. chi_square = pow(gsl_blas_dnrm2(solver->f), 2.0); #ifdef _DEBUG fprintf(stderr, "chi_square = %13.6lf.\n", chi_square); #endif dof = no_points - npar; #ifdef _DEBUG fprintf(stderr, "dof = %d\n", dof); #endif red_chi_square = chi_square / (double)dof; #ifdef _DEBUG fprintf(stderr, "red_chi_square = %13.6lf.\n", red_chi_square); fprintf(stderr, "\n"); #endif p1 = gsl_vector_get(solver->x, 0); p2 = gsl_vector_get(solver->x, 1); m = gsl_vector_get(solver->x, npar-1); if(red_chi_square > 1.0) c = sqrt(red_chi_square); #ifdef _DEBUG fprintf(stderr, "p1 = %+9.6lf +/- %9.6lf.\n", p1, c * sqrt(gsl_matrix_get(covar, 0, 0))); fprintf(stderr, "p2 = %+9.6lf +/- %9.6lf.\n", p2, c * sqrt(gsl_matrix_get(covar, 1, 1))); fprintf(stderr, "m = %+9.6lf +/- %9.6lf.\n", m, c * sqrt(gsl_matrix_get(covar, npar-1, npar-1))); fprintf(stderr, "\n"); fprintf(stderr, "status = %s.\n", gsl_strerror(status)); fprintf(stderr, "\n"); #endif for(i = 0; i < npar; i++) { statep[5+i] = gsl_vector_get(solver->x, i); } statep[0] = chi_square; statep[1] = gsl_blas_dnrm2(solver->f); statep[2] = (double)iter; statep[3] = (double)dof; statep[4] = (double)status; gsl_multifit_fdfsolver_free(solver); #ifdef _DEBUG gsl_matrix_free(covar); #endif free(data_struct.x); free(data_struct.y); free(data_struct.err); free(para_initial); UNPROTECT(11); return(state); }
/** Executes the algorithm * * @throw runtime_error Thrown if algorithm cannot execute */ void Fit1D::exec() { // Custom initialization prepare(); // check if derivative defined in derived class bool isDerivDefined = true; gsl_matrix * M = NULL; try { const std::vector<double> inTest(m_parameterNames.size(),1.0); std::vector<double> outTest(m_parameterNames.size()); const double xValuesTest = 0; JacobianImpl J; M = gsl_matrix_alloc(m_parameterNames.size(),1); J.setJ(M); // note nData set to zero (last argument) hence this should avoid further memory problems functionDeriv(&(inTest.front()), &J, &xValuesTest, 0); } catch (Exception::NotImplementedError&) { isDerivDefined = false; } gsl_matrix_free(M); // Try to retrieve optional properties int histNumber = getProperty("WorkspaceIndex"); const int maxInterations = getProperty("MaxIterations"); // Get the input workspace MatrixWorkspace_const_sptr localworkspace = getProperty("InputWorkspace"); // number of histogram is equal to the number of spectra const size_t numberOfSpectra = localworkspace->getNumberHistograms(); // Check that the index given is valid if ( histNumber >= static_cast<int>(numberOfSpectra) ) { g_log.warning("Invalid Workspace index given, using first Workspace"); histNumber = 0; } // Retrieve the spectrum into a vector const MantidVec& XValues = localworkspace->readX(histNumber); const MantidVec& YValues = localworkspace->readY(histNumber); const MantidVec& YErrors = localworkspace->readE(histNumber); //Read in the fitting range data that we were sent double startX = getProperty("StartX"); double endX = getProperty("EndX"); //check if the values had been set, otherwise use defaults if ( isEmpty( startX ) ) { startX = XValues.front(); modifyStartOfRange(startX); // does nothing by default but derived class may provide a more intelligent value } if ( isEmpty( endX ) ) { endX = XValues.back(); modifyEndOfRange(endX); // does nothing by default but derived class may previde a more intelligent value } int m_minX; int m_maxX; // Check the validity of startX if ( startX < XValues.front() ) { g_log.warning("StartX out of range! Set to start of frame."); startX = XValues.front(); } // Get the corresponding bin boundary that comes before (or coincides with) this value for (m_minX = 0; XValues[m_minX+1] < startX; ++m_minX) {} // Check the validity of endX and get the bin boundary that come after (or coincides with) it if ( endX >= XValues.back() || endX < startX ) { g_log.warning("EndX out of range! Set to end of frame"); endX = XValues.back(); m_maxX = static_cast<int>(YValues.size()); } else { for (m_maxX = m_minX; XValues[m_maxX] < endX; ++m_maxX) {} } afterDataRangedDetermined(m_minX, m_maxX); // create and populate GSL data container warn user if l_data.n < l_data.p // since as a rule of thumb this is required as a minimum to obtained 'accurate' // fitting parameter values. FitData l_data(this,getProperty("Fix")); l_data.n = m_maxX - m_minX; // m_minX and m_maxX are array index markers. I.e. e.g. 0 & 19. if (l_data.n == 0) { g_log.error("The data set is empty."); throw std::runtime_error("The data set is empty."); } if (l_data.n < l_data.p) { g_log.error("Number of data points less than number of parameters to be fitted."); throw std::runtime_error("Number of data points less than number of parameters to be fitted."); } l_data.X = new double[l_data.n]; l_data.sigmaData = new double[l_data.n]; l_data.forSimplexLSwrap = new double[l_data.n]; l_data.parameters = new double[nParams()]; // check if histogram data in which case use mid points of histogram bins const bool isHistogram = localworkspace->isHistogramData(); for (unsigned int i = 0; i < l_data.n; ++i) { if (isHistogram) l_data.X[i] = 0.5*(XValues[m_minX+i]+XValues[m_minX+i+1]); // take mid-point if histogram bin else l_data.X[i] = XValues[m_minX+i]; } l_data.Y = &YValues[m_minX]; // check that no error is negative or zero for (unsigned int i = 0; i < l_data.n; ++i) { if (YErrors[m_minX+i] <= 0.0) { l_data.sigmaData[i] = 1.0; } else l_data.sigmaData[i] = YErrors[m_minX+i]; } // create array of fitted parameter. Take these to those input by the user. However, for doing the // underlying fitting it might be more efficient to actually perform the fitting on some of other // form of the fitted parameters. For instance, take the Gaussian sigma parameter. In practice it // in fact more efficient to perform the fitting not on sigma but 1/sigma^2. The methods // modifyInitialFittedParameters() and modifyFinalFittedParameters() are used to allow for this; // by default these function do nothing. m_fittedParameter.clear(); for (size_t i = 0; i < nParams(); i++) { m_fittedParameter.push_back(getProperty(m_parameterNames[i])); } modifyInitialFittedParameters(m_fittedParameter); // does nothing except if overwritten by derived class for (size_t i = 0; i < nParams(); i++) { l_data.parameters[i] = m_fittedParameter[i]; } // set-up initial guess for fit parameters gsl_vector *initFuncArg; initFuncArg = gsl_vector_alloc(l_data.p); for (size_t i = 0,j = 0; i < nParams(); i++) { if (l_data.active[i]) gsl_vector_set(initFuncArg, j++, m_fittedParameter[i]); } // set-up GSL container to be used with GSL simplex algorithm gsl_multimin_function gslSimplexContainer; gslSimplexContainer.n = l_data.p; // n here refers to number of parameters gslSimplexContainer.f = &gsl_costFunction; gslSimplexContainer.params = &l_data; // set-up GSL least squares container gsl_multifit_function_fdf f; f.f = &gsl_f; f.df = &gsl_df; f.fdf = &gsl_fdf; f.n = l_data.n; f.p = l_data.p; f.params = &l_data; // set-up remaining GSL machinery for least squared const gsl_multifit_fdfsolver_type *T = gsl_multifit_fdfsolver_lmsder; gsl_multifit_fdfsolver *s = NULL; if (isDerivDefined) { s = gsl_multifit_fdfsolver_alloc(T, l_data.n, l_data.p); gsl_multifit_fdfsolver_set(s, &f, initFuncArg); } // set-up remaining GSL machinery to use simplex algorithm const gsl_multimin_fminimizer_type *simplexType = gsl_multimin_fminimizer_nmsimplex; gsl_multimin_fminimizer *simplexMinimizer = NULL; gsl_vector *simplexStepSize = NULL; if (!isDerivDefined) { simplexMinimizer = gsl_multimin_fminimizer_alloc(simplexType, l_data.p); simplexStepSize = gsl_vector_alloc(l_data.p); gsl_vector_set_all (simplexStepSize, 1.0); // is this always a sensible starting step size? gsl_multimin_fminimizer_set(simplexMinimizer, &gslSimplexContainer, initFuncArg, simplexStepSize); } // finally do the fitting int iter = 0; int status; double size; // for simplex algorithm double finalCostFuncVal; double dof = static_cast<double>(l_data.n - l_data.p); // dof stands for degrees of freedom // Standard least-squares used if derivative function defined otherwise simplex Progress prog(this,0.0,1.0,maxInterations); if (isDerivDefined) { do { iter++; status = gsl_multifit_fdfsolver_iterate(s); if (status) // break if error break; status = gsl_multifit_test_delta(s->dx, s->x, 1e-4, 1e-4); prog.report(); } while (status == GSL_CONTINUE && iter < maxInterations); double chi = gsl_blas_dnrm2(s->f); finalCostFuncVal = chi*chi / dof; // put final converged fitting values back into m_fittedParameter for (size_t i = 0, j = 0; i < nParams(); i++) if (l_data.active[i]) m_fittedParameter[i] = gsl_vector_get(s->x,j++); } else { do { iter++; status = gsl_multimin_fminimizer_iterate(simplexMinimizer); if (status) // break if error break; size = gsl_multimin_fminimizer_size(simplexMinimizer); status = gsl_multimin_test_size(size, 1e-2); prog.report(); } while (status == GSL_CONTINUE && iter < maxInterations); finalCostFuncVal = simplexMinimizer->fval / dof; // put final converged fitting values back into m_fittedParameter for (unsigned int i = 0, j = 0; i < m_fittedParameter.size(); i++) if (l_data.active[i]) m_fittedParameter[i] = gsl_vector_get(simplexMinimizer->x,j++); } modifyFinalFittedParameters(m_fittedParameter); // do nothing except if overwritten by derived class // Output summary to log file std::string reportOfFit = gsl_strerror(status); g_log.information() << "Iteration = " << iter << "\n" << "Status = " << reportOfFit << "\n" << "Chi^2/DoF = " << finalCostFuncVal << "\n"; for (size_t i = 0; i < m_fittedParameter.size(); i++) g_log.information() << m_parameterNames[i] << " = " << m_fittedParameter[i] << " \n"; // also output summary to properties setProperty("OutputStatus", reportOfFit); setProperty("OutputChi2overDoF", finalCostFuncVal); for (size_t i = 0; i < m_fittedParameter.size(); i++) setProperty(m_parameterNames[i], m_fittedParameter[i]); std::string output = getProperty("Output"); if (!output.empty()) { // calculate covariance matrix if derivatives available gsl_matrix *covar(NULL); std::vector<double> standardDeviations; std::vector<double> sdExtended; if (isDerivDefined) { covar = gsl_matrix_alloc (l_data.p, l_data.p); gsl_multifit_covar (s->J, 0.0, covar); int iPNotFixed = 0; for(size_t i=0;i<nParams();i++) { sdExtended.push_back(1.0); if (l_data.active[i]) { sdExtended[i] = sqrt(gsl_matrix_get(covar,iPNotFixed,iPNotFixed)); iPNotFixed++; } } modifyFinalFittedParameters(sdExtended); for(size_t i=0;i<nParams();i++) if (l_data.active[i]) standardDeviations.push_back(sdExtended[i]); declareProperty( new WorkspaceProperty<API::ITableWorkspace>("OutputNormalisedCovarianceMatrix","",Direction::Output), "The name of the TableWorkspace in which to store the final covariance matrix" ); setPropertyValue("OutputNormalisedCovarianceMatrix",output+"_NormalisedCovarianceMatrix"); Mantid::API::ITableWorkspace_sptr m_covariance = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace"); m_covariance->addColumn("str","Name"); std::vector<std::string> paramThatAreFitted; // used for populating 1st "name" column for(size_t i=0;i<nParams();i++) { if (l_data.active[i]) { m_covariance->addColumn("double",m_parameterNames[i]); paramThatAreFitted.push_back(m_parameterNames[i]); } } for(size_t i=0;i<l_data.p;i++) { Mantid::API::TableRow row = m_covariance->appendRow(); row << paramThatAreFitted[i]; for(size_t j=0;j<l_data.p;j++) { if (j == i) row << 1.0; else { row << 100.0*gsl_matrix_get(covar,i,j)/sqrt(gsl_matrix_get(covar,i,i)*gsl_matrix_get(covar,j,j)); } } } setProperty("OutputNormalisedCovarianceMatrix",m_covariance); } declareProperty( new WorkspaceProperty<API::ITableWorkspace>("OutputParameters","",Direction::Output), "The name of the TableWorkspace in which to store the final fit parameters" ); declareProperty(new WorkspaceProperty<MatrixWorkspace>("OutputWorkspace","",Direction::Output), "Name of the output Workspace holding resulting simlated spectrum"); setPropertyValue("OutputParameters",output+"_Parameters"); setPropertyValue("OutputWorkspace",output+"_Workspace"); // Save the final fit parameters in the output table workspace Mantid::API::ITableWorkspace_sptr m_result = Mantid::API::WorkspaceFactory::Instance().createTable("TableWorkspace"); m_result->addColumn("str","Name"); m_result->addColumn("double","Value"); if (isDerivDefined) m_result->addColumn("double","Error"); Mantid::API::TableRow row = m_result->appendRow(); row << "Chi^2/DoF" << finalCostFuncVal; for(size_t i=0;i<nParams();i++) { Mantid::API::TableRow row = m_result->appendRow(); row << m_parameterNames[i] << m_fittedParameter[i]; if (isDerivDefined && l_data.active[i]) { // perhaps want to scale standard deviations with sqrt(finalCostFuncVal) row << sdExtended[i]; } } setProperty("OutputParameters",m_result); // Save the fitted and simulated spectra in the output workspace MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace"); int iSpec = getProperty("WorkspaceIndex"); const MantidVec& inputX = inputWorkspace->readX(iSpec); const MantidVec& inputY = inputWorkspace->readY(iSpec); int histN = isHistogram ? 1 : 0; Mantid::DataObjects::Workspace2D_sptr ws = boost::dynamic_pointer_cast<Mantid::DataObjects::Workspace2D> ( Mantid::API::WorkspaceFactory::Instance().create( "Workspace2D", 3, l_data.n + histN, l_data.n) ); ws->setTitle(""); ws->getAxis(0)->unit() = inputWorkspace->getAxis(0)->unit();// UnitFactory::Instance().create("TOF"); for(int i=0;i<3;i++) ws->dataX(i).assign(inputX.begin()+m_minX,inputX.begin()+m_maxX+histN); ws->dataY(0).assign(inputY.begin()+m_minX,inputY.begin()+m_maxX); MantidVec& Y = ws->dataY(1); MantidVec& E = ws->dataY(2); double* lOut = new double[l_data.n]; // to capture output from call to function() modifyInitialFittedParameters(m_fittedParameter); // does nothing except if overwritten by derived class function(&m_fittedParameter[0], lOut, l_data.X, l_data.n); modifyInitialFittedParameters(m_fittedParameter); // reverse the effect of modifyInitialFittedParameters - if any for(unsigned int i=0; i<l_data.n; i++) { Y[i] = lOut[i]; E[i] = l_data.Y[i] - Y[i]; } delete [] lOut; setProperty("OutputWorkspace",boost::dynamic_pointer_cast<MatrixWorkspace>(ws)); if (isDerivDefined) gsl_matrix_free(covar); } // clean up dynamically allocated gsl stuff if (isDerivDefined) gsl_multifit_fdfsolver_free(s); else { gsl_vector_free(simplexStepSize); gsl_multimin_fminimizer_free(simplexMinimizer); } delete [] l_data.X; delete [] l_data.sigmaData; delete [] l_data.forSimplexLSwrap; delete [] l_data.parameters; gsl_vector_free (initFuncArg); return; }
int main(){ const int max_mu_size=601; const int zero_pad_size=pow(2,15); FILE *in; in= fopen("mean.chi", "r"); gsl_matrix *e = gsl_matrix_alloc(max_mu_size, 4); gsl_vector * kvar=gsl_vector_alloc(max_mu_size); gsl_vector * muvar=gsl_vector_alloc(max_mu_size); gsl_vector * mu_0pad=gsl_vector_alloc(zero_pad_size); gsl_vector * r_0pad=gsl_vector_alloc(zero_pad_size/2); //half of lenght gsl_vector * kvar_0pad=gsl_vector_alloc(zero_pad_size); gsl_matrix_fscanf(in, e); fclose(in); gsl_matrix_get_col(kvar,e,0); gsl_matrix_get_col(muvar,e,1); gsl_vector_set_zero(mu_0pad); gsl_matrix_free(e); double dk=gsl_vector_get (kvar, 1)-gsl_vector_get (kvar, 0); double dr=M_PI/float(zero_pad_size-1)/dk; for (int i = 0; i < zero_pad_size; i++) { gsl_vector_set (kvar_0pad, i, dk*i); } for (int i = 0; i < zero_pad_size/2; i++) { gsl_vector_set (r_0pad, i, dr*i); } for (int i = 0; i < max_mu_size; i++) { gsl_vector_set (mu_0pad, i, gsl_vector_get (muvar, i)); } gsl_vector *mu_widowed=gsl_vector_alloc(zero_pad_size); gsl_vector_memcpy (mu_widowed, mu_0pad); double kmin=4.0, kmax=17.0, dwk=0.8; hanning(mu_widowed, kvar_0pad, kmin, kmax, dwk); //FFT transform double *data = (double *) malloc(zero_pad_size*sizeof(double)); //new double [zero_pad_size] ; memcpy(data, mu_widowed->data, zero_pad_size*sizeof(double)); gsl_fft_real_radix2_transform(data, 1, zero_pad_size); //Unpack complex vector gsl_vector_complex *fourier_data = gsl_vector_complex_alloc (zero_pad_size); gsl_fft_halfcomplex_radix2_unpack(data, fourier_data->data, 1, zero_pad_size); gsl_vector *fftR_real = gsl_vector_alloc(fourier_data->size/2); gsl_vector *fftR_imag = gsl_vector_alloc(fourier_data->size/2); gsl_vector *fftR_abs = gsl_vector_alloc(fourier_data->size/2); complex_vector_parts(fourier_data, fftR_real, fftR_imag); complex_vector_abs(fftR_abs, fftR_real, fftR_imag); gsl_vector *first_shell=gsl_vector_alloc(fftR_abs->size); gsl_vector_memcpy (first_shell, fftR_abs); double rmin=0.2, rmax=3.0, dwr=0.1; hanning(first_shell, r_0pad, rmin, rmax, dwr); //feff0001.dat const int path_lines=68; e = gsl_matrix_alloc(path_lines, 7); gsl_vector * k_p =gsl_vector_alloc(path_lines); gsl_vector * phc_p=gsl_vector_alloc(path_lines); gsl_vector * mag_p=gsl_vector_alloc(path_lines); gsl_vector * pha_p=gsl_vector_alloc(path_lines); gsl_vector * lam_p=gsl_vector_alloc(path_lines); in= fopen("feff0001.dat", "r"); gsl_matrix_fscanf(in, e); fclose(in); gsl_matrix_get_col(k_p ,e,0); gsl_matrix_get_col(phc_p,e,1); gsl_matrix_get_col(mag_p,e,2); gsl_matrix_get_col(pha_p,e,3); gsl_matrix_get_col(lam_p,e,5); gsl_matrix_free(e); gsl_interp_accel *acc = gsl_interp_accel_alloc (); gsl_spline *k_spline = gsl_spline_alloc (gsl_interp_cspline, path_lines); gsl_spline *phc_spline = gsl_spline_alloc (gsl_interp_cspline, path_lines); gsl_spline *mag_spline = gsl_spline_alloc (gsl_interp_cspline, path_lines); gsl_spline *pha_spline = gsl_spline_alloc (gsl_interp_cspline, path_lines); gsl_spline *lam_spline = gsl_spline_alloc (gsl_interp_cspline, path_lines); gsl_spline_init (k_spline , k_p->data, k_p->data , path_lines); gsl_spline_init (phc_spline, k_p->data, phc_p->data, path_lines); gsl_spline_init (mag_spline, k_p->data, mag_p->data, path_lines); gsl_spline_init (pha_spline, k_p->data, pha_p->data, path_lines); gsl_spline_init (lam_spline, k_p->data, lam_p->data, path_lines); gsl_vector * mu_p =gsl_vector_alloc(path_lines); //struct fit_params { student_params t; double kshift; double S02; double N; inter_path splines; }; //student_params t = {2.45681867, 0.02776907, -21.28920008, 9.44741797, 0.0, 0.0, 0.0}; splines.acc=acc; splines.phc_spline=phc_spline; splines.mag_spline=mag_spline; splines.pha_spline=pha_spline; splines.lam_spline=lam_spline; fit_params fp = { 2.45681867, 0.02776907, -21.28920008, 9.44741797, 1.0, 0.0}; compute_itegral(k_p, &fp, mu_p); //mu_data_fit params = { k_p, mu_p}; mu_data.k = kvar_0pad; mu_data.mu = mu_0pad; mu_data.mu_ft = first_shell; mu_data.r = r_0pad; mu_data.kmin = kmin; mu_data.kmax = kmax; mu_data.rmin = rmin; mu_data.rmax = rmax; mu_data.dwk = dwk; mu_data.dwr = dwr; // initialize the solver size_t Nparams=6; gsl_vector *guess0 = gsl_vector_alloc(Nparams); gsl_vector_set(guess0, 0, 2.4307); gsl_vector_set(guess0, 1, 0.040969); gsl_vector_set(guess0, 2, 0.001314); gsl_vector_set(guess0, 3, 7835); gsl_vector_set(guess0, 4, 1.0); gsl_vector_set(guess0, 5, 0.0); gsl_vector *fit_r = gsl_vector_alloc(r_0pad->size); compute_itegral_r(&mu_data, fp, fit_r); gsl_matrix *plotting = gsl_matrix_calloc(r_0pad->size, 3); gsl_matrix_set_col (plotting, 0, r_0pad); gsl_matrix_set_col (plotting, 1, first_shell); gsl_matrix_set_col (plotting, 2, fit_r); plot_matplotlib(plotting); gsl_matrix_free (plotting); gsl_multifit_function_fdf fit_mu_k; fit_mu_k.f = &resudial_itegral_r; fit_mu_k.n = MAX_FIT_POINTS; fit_mu_k.p = Nparams; fit_mu_k.params = &mu_data; fit_mu_k.df = NULL; fit_mu_k.fdf = NULL; gsl_multifit_fdfsolver *solver = gsl_multifit_fdfsolver_alloc(gsl_multifit_fdfsolver_lmsder, MAX_FIT_POINTS, Nparams); gsl_multifit_fdfsolver_set(solver, &fit_mu_k, guess0); size_t iter=0, status; do{ iter++; //cout << solver->x->data[0] << " " << solver->x->data[1] <<endl; status = gsl_multifit_fdfsolver_iterate (solver); //printf("%12.4f %12.4f %12.4f\n", solver->J->data[0,0], solver->J->data[1,1], solver->J->data[2,2] ); //gsl_multifit_fdfsolver_dif_df (k_p, &fit_mu_k, mu_p, solver->J); //gsl_multifit_fdfsolver_dif_fdf (k_p, &fit_mu_k, mu_p, solver->J); for (int i =0; i< solver->x->size; i++){ printf("%14.5f", gsl_vector_get (solver->x, i)) ; } printf("\n") ; if (status) break; status = gsl_multifit_test_delta (solver->dx, solver->x, 1e-4, 1e-4); }while (status == GSL_CONTINUE && iter < 100); gsl_vector * mu_fit =gsl_vector_alloc(path_lines); fit_params fitp = { solver->x->data[0], solver->x->data[1],\ solver->x->data[2], solver->x->data[3],\ solver->x->data[4], solver->x->data[5]}; compute_itegral(k_p, &fitp, mu_fit); fp.mu=gsl_vector_get (solver->x, 0); fp.sig=gsl_vector_get (solver->x, 1); fp.skew=gsl_vector_get (solver->x, 2); fp.nu=gsl_vector_get (solver->x, 3); fp.S02=gsl_vector_get (solver->x, 4); fp.kshift=gsl_vector_get (solver->x, 5); compute_itegral_r(&mu_data, fp, fit_r); //gsl_matrix *plotting = gsl_matrix_calloc(r_0pad->size, 3); gsl_matrix_set_col (plotting, 0, r_0pad); gsl_matrix_set_col (plotting, 1, first_shell); gsl_matrix_set_col (plotting, 2, fit_r); int min_r=search_max(r_0pad, 0.); int max_r=search_max(r_0pad, 4.); gsl_matrix_view plotting_lim = gsl_matrix_submatrix (plotting, min_r, 0, max_r-min_r, plotting->size2); plot_matplotlib(&plotting_lim.matrix); gsl_matrix_free (plotting); //cout << gsl_spline_eval (k_spline, 1.333, acc) << endl; //cout << gsl_spline_eval (phc_spline, 1.333, acc) << endl; //cout << data[0] << "\t" << data[1] << "\t" << data[2] << "\t" << endl; //cout << fourier_data->data[0] << "\t" << fourier_data->data[1] << "\t" << fourier_data->data[2] << "\t" << endl; //Plotting /* gsl_matrix *plotting = gsl_matrix_calloc(zero_pad_size, 3); gsl_matrix_set_col (plotting, 0, kvar_0pad); gsl_matrix_set_col (plotting, 1, mu_0pad); gsl_matrix_set_col (plotting, 2, mu_widowed); int max_k=search_max(kvar_0pad, 35.); int min_k=search_max(kvar_0pad, 1.0); gsl_matrix_view plotting_lim = gsl_matrix_submatrix (plotting, min_k, 0, max_k-min_k, 3); plot_matplotlib(&plotting_lim.matrix); gsl_matrix_free (plotting); */ /* gsl_matrix *plotting = gsl_matrix_calloc(zero_pad_size, 2); gsl_matrix_set_col (plotting, 0, r_0pad); gsl_matrix_set_col (plotting, 1, mu_0pad); int max_k=search_max(kvar_0pad, 35.); int min_k=search_max(kvar_0pad, 1.0); gsl_matrix_view plotting_lim = gsl_matrix_submatrix (plotting, min_k, 0, max_k-min_k, 3); plot_matplotlib(&plotting_lim.matrix); gsl_matrix_free (plotting); */ /* gsl_matrix *plotting = gsl_matrix_calloc(r_0pad->size, 5); gsl_matrix_set_col (plotting, 0, r_0pad); gsl_matrix_set_col (plotting, 1, fftR_abs); gsl_matrix_set_col (plotting, 2, fftR_real); gsl_matrix_set_col (plotting, 3, fftR_imag); gsl_matrix_set_col (plotting, 4, first_shell); int min_r=search_max(r_0pad, 0.); int max_r=search_max(r_0pad, 5.); gsl_matrix_view plotting_lim = gsl_matrix_submatrix (plotting, min_r, 0, max_r-min_r, plotting->size2); plot_matplotlib(&plotting_lim.matrix); //plot_matplotlib(plotting); gsl_matrix_free (plotting); */ //cout << "Done" << endl; //cout << data[1] <<"\t" << data[2] << endl; //for (int i = 0; i < kvar->size; i++) //{ // cout << gsl_vector_get (kvar, i) <<"\t" << gsl_vector_get (muvar, i) << endl; //} }
int Cornea::computeCentre(const std::vector<Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d> > &led_pos, // LED locations const std::vector<Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d> > &glint_pos, std::vector<double> &gx_guesses, Eigen::Vector3d ¢re, double &err) { // initialise the cornea tracker create(led_pos, glint_pos); /* * Check out usage and more info about GSL: * http://www.csse.uwa.edu.au/programming/gsl-1.0/gsl-ref_35.html */ const size_t n = 3 * pairsOfTwo(data.size()); // number of functions const size_t p = gx_guesses.size(); // number of parameters // initial guesses gsl_vector_const_view x = gsl_vector_const_view_array(gx_guesses.data(), p); gsl_multifit_function_fdf f; f.f = &my_f; // function f.df = &my_df; // derivative f.fdf = &my_fdf; // both f.n = n; // number of functions f.p = p; // number of parameters f.params = this; // additional parameter const gsl_multifit_fdfsolver_type *T = gsl_multifit_fdfsolver_lmsder; gsl_multifit_fdfsolver *solver = gsl_multifit_fdfsolver_alloc(T, n, p); gsl_multifit_fdfsolver_set(solver, &f, &x.vector); int status; unsigned int iter = 0; do { iter++; status = gsl_multifit_fdfsolver_iterate(solver); if(status) { break; } status = gsl_multifit_test_delta(solver->dx, solver->x, PRECISION, PRECISION); } while(status == GSL_CONTINUE && iter < MAX_ITER); if(iter == MAX_ITER) { printf("Cornea::computeCentre(): iter = MAX_ITER\n"); } gsl_matrix *covar = gsl_matrix_alloc(p, p); gsl_multifit_covar(solver->J, 0.0, covar); // for(int row = 0; row < p; ++row) { // for(int col = 0; col < p; ++col) { // printf("%.2f ", covar->data[row * p + col]); // } // printf("\n"); // } // printf("*****************************\n"); /*********************************************************************** * Compute the fit error **********************************************************************/ err = 0; for(size_t i = 0; i < p; i++) { err += gsl_matrix_get(covar, i, i); } err = std::sqrt(err); Eigen::Vector3d cw(0.0, 0.0, 0.0); // cornea sphere radius const double RHO = trackerSettings.RHO; // remove this double dMaxX = -10.0; for(size_t i = 0; i < data.size(); ++i) { const DATA_FOR_CORNEA_COMPUTATION &cur_data = data[i]; const double gx_guess = gsl_vector_get(solver->x, i); const double B_aux = atan2(gx_guess * tan(cur_data.alpha_aux), (cur_data.l_aux - gx_guess)); // calculate the corneal sphere centers in the auxiliary coordinate systems const Eigen::Vector3d c_aux(gx_guess - RHO * sin((cur_data.alpha_aux - B_aux) / 2.), 0., gx_guess * tan(cur_data.alpha_aux) + RHO * cos((cur_data.alpha_aux - B_aux) / 2.)); const Eigen::Vector3d tmp = cur_data.R * c_aux; cw(0) += tmp(0); cw(1) += tmp(1); cw(2) += tmp(2); if(tmp(0) > dMaxX) { dMaxX = tmp(0); } // printf("%i: centre (mm): %.2f %.2f %.2f\n", (int)i, 1000.0*tmp(0), 1000.0*tmp(1), 1000.0*tmp(2)); } const double nof_samples = (double)data.size(); centre << cw(0) / nof_samples, cw(1) / nof_samples, cw(2) / nof_samples; // printf("Avg: %.2f %.2f %.2f\n", 1000.0*centre(0), 1000.0*centre(1), 1000.0*centre(2)); // printf("*********************************\n"); gsl_multifit_fdfsolver_free(solver); gsl_matrix_free(covar); return (int)iter; }