Although this is probably is a simple question, I could not find the solution in the manual. I have to fit many datasets with a simple guassian (y=0) peak. However, only a part of the signal is useable for this. So, I ask the user to estimate the beginning and end of the useable part and also to estimate the center. Then, I loop through all the worksheets and try to fit the data in it.
How can I use only the points that satisfy startx < x < stopx ?
// Retrieve estimates from user
double startx = InputBox(1.0, "Left limit.");
double stopx = InputBox(10.0, "Right limit.");
double peakx = InputBox((startx+stopx)/2,"Peak location.");
// Let's fill the start fitting parameters
// @todo Make sure y0 is fixed
vector vParams(4);
vParams[0] = 0; // y0
vParams[1] = peakx; // xc
vParams[2] = (stopx-startx)/2; // w
vParams[3] = 1; // A
// Start the FitSession
NLFitSession FitSession;
if( !FitSession.SetFunction("Gauss")) {
out_str("invalid fit function");
return;
}
// Initialize aggregate vectors
int sheets = book.Layers.Count();
vector xx, xcResults, wResults, y0Results, AResults;
xx.SetSize( sheets ); // The part we are varying per measurement
xcResults.SetSize( sheets ); // xc's from fits
wResults.SetSize( sheets ); // w's from fits
y0Results.SetSize( sheets ); // y0's from fits
AResults.SetSize( sheets ); // A's from fits
// Initialize some working variables
vector vParamValues, vErrors;
int index = 0, location, nOutcome;
string desc;
// Loop through all worksheets in the workbook
foreach ( Layer layer in book.Layers ) {
Worksheet worksheet = layer;
desc = worksheet.GetName();
// Acquire data ranges
vector vX = worksheet.Columns(1).GetDataObject();
vector vY = worksheet.Columns(2).GetDataObject();
if( !FitSession.SetData(vY, vX)) {
out_str("fail to set data");
return;
}
// Set the parameters to start values
if( !FitSession.ParamsInitValues()) {
out_str("fail to initialize parameter");
return;
}
if( 0 != FitSession.SetParamValues( vParams ) ) {
out_str("fail to set parameters");
return;
}
FitSession.GetChiSqr();
// Now, we fit!
if( !FitSession.Fit(&nOutcome) ) {
printf("Fail to do fitting for %s\n", desc);
continue;
}
printf("Fitted %s Succesfully\n", desc);
FitSession.GetFitResultsParams(vParamValues, vErrors);
// The xx value is in the name of the sheet
location = desc.ReverseFind(' ');
xx[index] = atof(desc.Mid( location + 1));
// We obtained y0, xc, w, A (in that order)
y0Results[index] = vParamValues[0];
xcResults[index] = vParamValues[1];
wResults[index] = vParamValues[2];
AResults[index] = vParamValues[3];
index++;
}
// Create a new workbook
WorksheetPage bookFitResults;
bookFitResults.Create( NULL, CREATE_VISIBLE | CREATE_EMPTY );
bookFitResults.SetName( "FitResult" );
bookFitResults.SetLongName( "Fit results" );
// Create a new worksheet
Worksheet fitSheet;
fitSheet = bookFitResults.Layers.Item( bookFitResults.AddLayer( "FitResults" ) );
fitSheet.SetSize( sheets, 5 );
// Save
// @todo This part isn't correct yet
fitSheet.Columns(0).SetType(OKDATAOBJ_DESIGNATION_X);
fitSheet.Columns(1).SetType(OKDATAOBJ_DESIGNATION_Y);
fitSheet.Columns(2).SetType(OKDATAOBJ_DESIGNATION_Y);
fitSheet.Columns(3).SetType(OKDATAOBJ_DESIGNATION_Y);
fitSheet.Columns(4).SetType(OKDATAOBJ_DESIGNATION_Y);
fitSheet.Columns(0).SetName("xx");
fitSheet.Columns(1).SetName("y0");
fitSheet.Columns(2).SetName("xc");
fitSheet.Columns(3).SetName("w");
fitSheet.Columns(4).SetName("A");
fitSheet.Columns(0).SetLongName("XX");
fitSheet.Columns(1).SetLongName("Amplitude");
fitSheet.Columns(2).SetLongName("Center location");
fitSheet.Columns(3).SetLongName("Width");
fitSheet.Columns(4).SetLongName("Area");
// @todo Cannot use more than 3 parameters per datarange?
// @todo Order is incorrect and depends on first parameter?
DataRange rangeOutput1;
rangeOutput1.Add("Z", fitSheet, 0, 0, -1, 0);
rangeOutput1.Add("X", fitSheet, 0, 1, -1, 1);
rangeOutput1.Add("Y", fitSheet, 0, 2, -1, 2);
rangeOutput1.SetData(&xx, &y0Results, &xcResults );
DataRange rangeOutput2;
rangeOutput2.Add(NULL, fitSheet, 0, 3, -1, 3);
rangeOutput2.Add(NULL, fitSheet, 0, 4, -1, 4);
rangeOutput2.SetData(&wResults, &AResults);