[Kst] branches/work/kst/portto4/kst/src
Barth Netterfield
netterfield at astro.utoronto.ca
Sun Dec 23 21:56:45 UTC 2012
SVN commit 1329652 by netterfield:
Fix a crash case in plot items (uninitialized variable)
Fix unweighted gaussian fits so that they actually fit.
M +2 -1 libkstapp/plotitem.cpp
M +79 -35 plugins/fits/gaussian_unweighted/fitgaussian_unweighted.cpp
M +2 -3 plugins/fits/non_linear.h
--- branches/work/kst/portto4/kst/src/libkstapp/plotitem.cpp #1329651:1329652
@@ -93,6 +93,7 @@
_fitMenu(0),
_editMenu(0),
_sharedAxisBoxMenu(0),
+ _copyMenu(0),
_sharedBox(0),
_axisLabelsDirty(true),
@@ -4322,9 +4323,9 @@
if (shareBox) {
if (applyX) {
shareBox->zoomXOut(0);
+ }
}
}
-}
/*
--- branches/work/kst/portto4/kst/src/plugins/fits/gaussian_unweighted/fitgaussian_unweighted.cpp #1329651:1329652
@@ -17,7 +17,7 @@
#include "objectstore.h"
#include "ui_fitgaussian_unweightedconfig.h"
-#define NUM_PARAMS 3
+#define NUM_PARAMS 4
#define MAX_NUM_ITERATIONS 500
#include <gsl/gsl_fit.h>
@@ -160,52 +160,93 @@
}
-void function_initial_estimate( const double* pdX, const double* pdY, int iLength, double* pdParameterEstimates ) {
- double dMin;
- double dMax;
+void function_initial_estimate( const double X[], const double Y[], int npts, double P[] ) {
+ double min_y = 1E300;
+ double max_y = -1E300;
+ double min_x = 1E300;
+ double max_x = -1E300;
+ double mean_y = 0.0;
+ double x_at_min_y;
+ double x_at_max_y;
- gsl_stats_minmax( &dMin, &dMax, pdX, 1, iLength );
+ double A, B, C, D;
- pdParameterEstimates[0] = gsl_stats_mean( pdX, 1, iLength );
- pdParameterEstimates[1] = ( dMax - dMin ) / 2.0;
- pdParameterEstimates[2] = gsl_stats_max( pdY, 1, iLength );
+ // find peak, vally, and mean
+ for (int i = 0; i<npts; i++) {
+ if (min_y > Y[i]) {
+ min_y = Y[i];
+ x_at_min_y = X[i];
}
+ if (max_y < Y[i]) {
+ max_y = Y[i];
+ x_at_max_y = X[i];
+ }
+ mean_y += Y[i];
+ if (min_x > X[i]) {
+ min_x = X[i];
+ }
+ if (max_x < X[i]) {
+ max_x = X[i];
+ }
+ }
+ if (npts>0) {
+ mean_y /= double(npts);
+ }
-double function_calculate( double dX, double* pdParameters ) {
- double dMean = pdParameters[0];
- double dSD = pdParameters[1];
- double dScale = pdParameters[2];
- double dY;
+ // Heuristic for finding the sign of the : less time is spent in the peak than
+ // in background if the range covers more than ~+- 2 sigma.
+ // It will fail if you are
+ // really zoomed into the gaussian. Not sure what happens then :-(
+ if (max_y - mean_y > mean_y - min_y) { // positive going gaussian
+ A = max_y - min_y;
+ D = min_y;
+ C = x_at_max_y;
+ } else { // negative going gaussian
+ A = min_y - mean_y;
+ D = max_y;
+ C = x_at_min_y;
+ }
+ // guess that the width of the gaussian is around 1/4 of the x range (?)
+ B = (max_x - min_x)*0.25;
- dY = ( dScale / ( dSD * M_SQRT2 * M_SQRTPI ) );
- dY *= exp( -( ( dX - dMean ) * ( dX - dMean ) ) / ( 2.0 * dSD * dSD ) );
+ P[0] = A;
+ P[1] = 1.0/(sqrt(2.0*B));
+ P[2] = C;
+ P[3] = D;
- return dY;
}
-void function_derivative( double dX, double* pdParameters, double* pdDerivatives ) {
- double dMean = pdParameters[0];
- double dSD = pdParameters[1];
- double dScale = pdParameters[2];
- double dExp;
- double ddMean;
- double ddSD;
- double ddScale;
+double function_calculate(double x, double P[]) {
+ double A = P[0];
+ double B = 0.5/(P[1]*P[1]);
+ double C = P[2];
+ double D = P[3];
- dExp = exp( -( ( dX - dMean ) * ( dX - dMean ) ) / ( 2.0 * dSD * dSD ) );
- ddMean = ( dX - dMean ) * dScale * dExp / ( dSD * dSD * dSD * M_SQRT2 * M_SQRTPI );
- ddSD = dScale * dExp / ( dSD * dSD * M_SQRT2 * M_SQRTPI );
- ddSD *= ( ( dX - dMean ) * ( dX - dMean ) / ( dSD * dSD ) ) - 1.0;
- ddScale = dExp / ( dSD * M_SQRT2 * M_SQRTPI );
+ x -= C;
- pdDerivatives[0] = ddMean;
- pdDerivatives[1] = ddSD;
- pdDerivatives[2] = ddScale;
+ return A*exp(-B*x*x) + D;
}
+void function_derivative( double x, double P[], double dFdP[] ) {
+ double A = P[0];
+ double s = P[1];
+ double B = 0.5/(s*s);
+ double C = P[2];
+ //double D = P[3];
+ x -= C;
+
+ double E = exp(-B*x*x);
+
+ dFdP[0] = E;
+ dFdP[1] = A*x*x*E/(s*s*s);
+ dFdP[2] = 2*A*B*x*E;
+ dFdP[3] = 1.0;
+
+}
+
bool FitGaussianUnweightedSource::algorithm() {
Kst::VectorPtr inputVectorX = _inputVectors[VECTOR_IN_X];
Kst::VectorPtr inputVectorY = _inputVectors[VECTOR_IN_Y];
@@ -290,14 +331,17 @@
QString parameter;
switch (index) {
case 0:
- parameter = "Mean";
+ parameter = "Amplitude";
break;
case 1:
- parameter = "SD";
+ parameter = "\\sigma";
break;
case 2:
- parameter = "Scale";
+ parameter = "x_o";
break;
+ case 3:
+ parameter = "Offset";
+ break;
}
return parameter;
--- branches/work/kst/portto4/kst/src/plugins/fits/non_linear.h #1329651:1329652
@@ -173,11 +173,10 @@
do {
iStatus = gsl_multifit_fdfsolver_iterate( pSolver );
if( iStatus == GSL_SUCCESS ) {
- iStatus = gsl_multifit_test_delta( pSolver->dx, pSolver->x, 1.0e-4, 1.0e-4 );
+ iStatus = gsl_multifit_test_delta( pSolver->dx, pSolver->x, 1.0e-6, 1.0e-6 );
}
iIterations++;
- }
- while( iStatus == GSL_CONTINUE && iIterations < MAX_NUM_ITERATIONS );
+ } while( iStatus == GSL_CONTINUE && iIterations < MAX_NUM_ITERATIONS );
gsl_multifit_covar( pSolver->J, 0.0, pMatrixCovariance );
More information about the Kst
mailing list