[Kst] branches/work/kst/portto4/kst/src/plugins/fits/lorentzian_unweighted

Barth Netterfield netterfield at astro.utoronto.ca
Thu Jan 31 23:25:33 UTC 2013


SVN commit 1336646 by netterfield:

fix the Lorentzian fit so that it actually fits Lorentzians.



 M  +80 -36    fitlorentzian_unweighted.cpp  


--- branches/work/kst/portto4/kst/src/plugins/fits/lorentzian_unweighted/fitlorentzian_unweighted.cpp #1336645:1336646
@@ -17,7 +17,7 @@
 #include "objectstore.h"
 #include "ui_fitlorentzian_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, 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 dHW    = pdParameters[1];
-  double dScale = pdParameters[2];
-  double dY;
+  // Heuristic for finding the sign : 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 in.  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;
+    B = x_at_max_y;
+  } else { // negative going gaussian
+    A = min_y - mean_y;
+    D = max_y;
+    B = x_at_min_y;
+  }
 
-  dY  = ( dScale / M_PI ) * ( dHW / 2.0 );
-  dY /= ( ( dX - dMean ) * ( dX - dMean ) )+( ( dHW / 2.0 ) * ( dHW / 2.0 ) );
+  P[0] = A; // amplitude
+  P[1] = B; // x0
+  P[2] = (max_x - min_x)*0.1; // Half Width: guess 1/10 the fit range
+  P[3] = D; // offset
+}
 
-  return dY;
+
+double function_calculate(double x, double P[]) {
+  double A = P[0]; // amplitude
+  double B = P[1]; // x0
+  double C = P[2]; // Half Width
+  double D = P[3]; // offset
+
+  x -= B;
+
+  double Y = A/(1.0 + x*x/(C*C)) + D;
+
+  return Y;
+
 }
 
+void function_derivative(double x, double P[], double dFdP[]) {
 
-void function_derivative( double dX, double* pdParameters, double* pdDerivatives ) {
-  double dMean  = pdParameters[0];
-  double dHW    = pdParameters[1];
-  double dScale = pdParameters[2];
-  double dDenom;  
-  double ddMean;
-  double ddHW;
-  double ddScale;
+  double A = P[0]; // amplitude
+  double B = P[1]; // x0
+  double C = P[2]; // Half Width
 
-  dDenom  = ( ( dX - dMean ) * ( dX - dMean ) ) + ( ( dHW / 2.0 ) * ( dHW / 2.0 ) );
-  ddMean  = ( dScale / M_PI ) * dHW * ( dMean - dX ) / ( dDenom * dDenom );
-  ddHW    = ( dScale / ( 2.0 * M_PI ) ) / ( dDenom * dDenom );
-  ddHW   *= dDenom - ( dHW * dHW / 2.0 );
-  ddScale = ( 1.0 / M_PI ) * ( dHW / 2.0 ) / dDenom;
+  double C2 = C*C;
+  x -= B;
+  double x2 = x*x;
+  double m = (x2 + C2);
 
-  pdDerivatives[0] = ddMean;
-  pdDerivatives[1] = ddHW;
-  pdDerivatives[2] = ddScale;
+
+  dFdP[0] = 1.0/(1.0 + x2/C2); // dF/dA
+  dFdP[1] = 2.0*A*C2*x/(m*m);
+  dFdP[2] = 2.0*A*C*x2/(m*m);
+  dFdP[3] = 1.0;
 }
 
-
 bool FitLorentzianUnweightedSource::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 = "Amplitide";
       break;
     case 1:
-      parameter = "Half-width";
+      parameter = "x_o";
       break;
     case 2:
-      parameter = "Scale";
+      parameter = "Half Width";
       break;
+    case 3:
+      parameter = "Offset";
+      break;
   }
 
   return parameter;


More information about the Kst mailing list