void least_squares_straightline_fit(void) { int i, n = 4; double x[4] = { 1970, 1980, 1990, 2000 }; double y[4] = { 12, 11, 14, 13 }; double w[4] = { 0.1, 0.2, 0.3, 0.4 }; double c0, c1, cov00, cov01, cov11, chisq; gsl_fit_wlinear(x, 1, w, 1, y, 1, n, &c0, &c1, &cov00, &cov01, &cov11, &chisq); printf("# best fit: Y = %g + %g X\n", c0, c1); printf("# covariance matrix:\n"); printf("# [ %g, %g\n# %g, %g]\n", cov00, cov01, cov01, cov11); printf("# chisq = %g\n", chisq); for (i = 0; i < n; i++) printf("data: %g %g %g\n", x[i], y[i], 1 / sqrt(w[i])); printf("\n"); for (i = -30; i < 130; i++) { double xf = x[0] + (i / 100.0) * (x[n - 1] - x[0]); double yf, yf_err; gsl_fit_linear_est(xf, c0, c1, cov00, cov01, cov11, &yf, &yf_err); printf("fit: %g %g\n", xf, yf); printf("hi : %g %g\n", xf, yf + yf_err); printf("lo : %g %g\n", xf, yf - yf_err); } }
static VALUE rb_gsl_fit_linear_est(int argc, VALUE *argv, VALUE obj) { double y, yerr, x, c0, c1, c00, c01, c11; int status; size_t i; switch (argc) { case 2: x = NUM2DBL(argv[0]); if (TYPE(argv[1]) == T_ARRAY) { c0 = NUM2DBL(rb_ary_entry(argv[1], 0)); c1 = NUM2DBL(rb_ary_entry(argv[1], 1)); c00 = NUM2DBL(rb_ary_entry(argv[1], 2)); c01 = NUM2DBL(rb_ary_entry(argv[1], 3)); c11 = NUM2DBL(rb_ary_entry(argv[1], 4)); } else { rb_raise(rb_eTypeError, "argv[1] Array expected"); } break; case 6: for (i = 0; i < 6; i++) Need_Float(argv[i]); x = NUM2DBL(argv[0]); c0 = NUM2DBL(argv[1]); c1 = NUM2DBL(argv[2]); c00 = NUM2DBL(argv[3]); c01 = NUM2DBL(argv[4]); c11 = NUM2DBL(argv[5]); break; default: rb_raise(rb_eArgError, "wrong number of arguments (%d for 2 or 6)", argc); } status = gsl_fit_linear_est(x, c0, c1, c00, c01, c11, &y, &yerr); return rb_ary_new3(3, rb_float_new(y), rb_float_new(yerr), INT2FIX(status)); }
pure_expr* wrap_gsl_fit_linear_est(double x, double c0, double c1, double cov00, double cov01, double cov11) { double y, y_err; gsl_fit_linear_est(x, c0, c1, cov00, cov01, cov11, &y, &y_err); return pure_listl(2, pure_double(y), pure_double(y_err)); }
CAMLprim value ml_gsl_fit_linear_est(value x, value coeffs) { double y,y_err; gsl_fit_linear_est(Double_val(x), Double_field(coeffs, 0), Double_field(coeffs, 1), Double_field(coeffs, 2), Double_field(coeffs, 3), Double_field(coeffs, 4), &y, &y_err); return copy_two_double_arr(y, y_err); }
void Linear::exec() { // Get the input workspace MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace"); // Get the spectrum to fit const int histNumber = getProperty("WorkspaceIndex"); // Check validity if ( histNumber >= static_cast<int>(inputWorkspace->getNumberHistograms()) ) { g_log.error() << "WorkspaceIndex set to an invalid value of " << histNumber << std::endl; throw Exception::IndexError(histNumber,inputWorkspace->getNumberHistograms(),"Linear WorkspaceIndex property"); } // Get references to the data in the chosen spectrum const MantidVec& X = inputWorkspace->dataX(histNumber); const MantidVec& Y = inputWorkspace->dataY(histNumber); const MantidVec& E = inputWorkspace->dataE(histNumber); // Check if this spectrum has errors double errorsCount = 0.0; // Retrieve the Start/EndX properties, if set this->setRange(X,Y); const bool isHistogram = inputWorkspace->isHistogramData(); // If the spectrum to be fitted has masked bins, we want to exclude them (even if only partially masked) const MatrixWorkspace::MaskList * const maskedBins = ( inputWorkspace->hasMaskedBins(histNumber) ? &(inputWorkspace->maskedBins(histNumber)) : NULL ); // Put indices of masked bins into a set for easy searching later std::set<size_t> maskedIndices; if (maskedBins) { MatrixWorkspace::MaskList::const_iterator it; for (it = maskedBins->begin(); it != maskedBins->end(); ++it) maskedIndices.insert(it->first); } progress(0); // Declare temporary vectors and reserve enough space if they're going to be used std::vector<double> XCen, unmaskedY, weights; int numPoints = m_maxX - m_minX; if (isHistogram) XCen.reserve(numPoints); if (maskedBins) unmaskedY.reserve(numPoints); weights.reserve(numPoints); for (int i = 0; i < numPoints; ++i) { // If the current bin is masked, skip it if ( maskedBins && maskedIndices.count(m_minX+i) ) continue; // Need to adjust X to centre of bin, if a histogram if (isHistogram) XCen.push_back( 0.5*(X[m_minX+i]+X[m_minX+i+1]) ); // If there are masked bins present, we need to copy the unmasked Y values if (maskedBins) unmaskedY.push_back(Y[m_minX+i]); // GSL wants the errors as weights, i.e. 1/sigma^2 // We need to be careful if E is zero because that would naively lead to an infinite weight on the point. // Solution taken here is to zero weight if error is zero, which typically means Y is zero // (so it is effectively excluded from the fit). const double& currentE = E[m_minX+i]; weights.push_back( currentE ? 1.0/(currentE*currentE) : 0.0 ); // However, if the spectrum given has all errors of zero, then we should use the gsl function that // doesn't take account of the errors. if ( currentE ) ++errorsCount; } progress(0.3); // If masked bins present, need to recalculate numPoints here if (maskedBins) numPoints = static_cast<int>(unmaskedY.size()); // If no points left for any reason, bail out if (numPoints == 0) { g_log.error("No points in this range to fit"); throw std::runtime_error("No points in this range to fit"); } // Set up pointer variables to pass to gsl, pointing them to the right place const double * const xVals = ( isHistogram ? &XCen[0] : &X[m_minX] ); const double * const yVals = ( maskedBins ? &unmaskedY[0] : &Y[m_minX] ); // Call the gsl fitting function // The stride value of 1 reflects that fact that we want every element of our input vectors const int stride = 1; double *c0(new double),*c1(new double),*cov00(new double),*cov01(new double),*cov11(new double),*chisq(new double); int status; // Unless our spectrum has error values for vast majority of points, // call the gsl function that doesn't use errors if ( errorsCount/numPoints < 0.9 ) { g_log.debug("Calling gsl_fit_linear (doesn't use errors in fit)"); status = gsl_fit_linear(xVals,stride,yVals,stride,numPoints,c0,c1,cov00,cov01,cov11,chisq); } // Otherwise, call the one that does account for errors on the data points else { g_log.debug("Calling gsl_fit_wlinear (uses errors in fit)"); status = gsl_fit_wlinear(xVals,stride,&weights[0],stride,yVals,stride,numPoints,c0,c1,cov00,cov01,cov11,chisq); } progress(0.8); // Check that the fit succeeded std::string fitStatus = gsl_strerror(status); // For some reason, a fit where c0,c1 & chisq are all infinity doesn't report as a // failure, so check explicitly. if ( !gsl_finite(*chisq) || !gsl_finite(*c0) || !gsl_finite(*c1) ) fitStatus = "Fit gives infinities"; if (fitStatus != "success") g_log.error() << "The fit failed: " << fitStatus << "\n"; else g_log.information() << "The fit succeeded, giving y = " << *c0 << " + " << *c1 << "*x, with a Chi^2 of " << *chisq << "\n"; // Set the fit result output properties setProperty("FitStatus",fitStatus); setProperty("FitIntercept",*c0); setProperty("FitSlope",*c1); setProperty("Cov00",*cov00); setProperty("Cov11",*cov11); setProperty("Cov01",*cov01); setProperty("Chi2",*chisq); // Create and fill a workspace2D with the same bins as the fitted spectrum and the value of the fit for the centre of each bin const size_t YSize = Y.size(); MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create(inputWorkspace,1,X.size(),YSize); // Copy over the X bins outputWorkspace->dataX(0).assign(X.begin(),X.end()); // Now loop over the spectrum and use gsl function to calculate the Y & E values for the function for (size_t i = 0; i < YSize; ++i) { const double x = ( isHistogram ? 0.5*(X[i]+X[i+1]) : X[i] ); const int err = gsl_fit_linear_est(x,*c0,*c1,*cov00,*cov01,*cov11,&(outputWorkspace->dataY(0)[i]),&(outputWorkspace->dataE(0)[i])); if (err) g_log.warning() << "Problem in filling the output workspace: " << gsl_strerror(err) << std::endl; } setProperty("OutputWorkspace",outputWorkspace); progress(1); // Clean up delete c0; delete c1; delete cov00; delete cov01; delete cov11; delete chisq; }
int kstfit_linear_unweighted(const double *const inArrays[], const int inArrayLens[], const double inScalars[], double *outArrays[], int outArrayLens[], double outScalars[]) { int i = 0; int iLength; int iReturn = -1; double* pResult[4]; double c0 = 0.0; double c1 = 0.0; double cov00 = 0.0; double cov01 = 0.0; double cov11 = 0.0; double dSumSq = 0.0; double y; double yErr; if (inArrayLens[Y] >= 2 && inArrayLens[X] >= 2) { iLength = inArrayLens[Y]; if( inArrayLens[X] < iLength ) { iLength = inArrayLens[X]; } for( i=0; i<4; i++ ) { if( outArrayLens[0] != iLength ) { pResult[i] = (double*)realloc( outArrays[i], iLength * sizeof( double ) ); } else { pResult[i] = outArrays[i]; } } if( pResult[0] != NULL && pResult[1] != NULL && pResult[2] != NULL && pResult[3] != NULL ) { for( i=0; i<4; i++ ) { outArrays[i] = pResult[i]; outArrayLens[i] = iLength; } if( !gsl_fit_linear( inArrays[X], 1, inArrays[Y], 1, iLength, &c0, &c1, &cov00, &cov01, &cov11, &dSumSq ) ) { for( i=0; i<iLength; i++ ) { gsl_fit_linear_est( inArrays[X][i], c0, c1, cov00, cov01, cov11, &y, &yErr ); outArrays[0][i] = y; outArrays[1][i] = y - yErr; outArrays[2][i] = y + yErr; outArrays[3][i] = inArrays[Y][i] - y; } outScalars[0] = c0; outScalars[1] = c1; outScalars[2] = cov00; outScalars[3] = cov01; outScalars[4] = cov11; outScalars[5] = dSumSq; iReturn = 0; } } } return iReturn; }