/** Calculate the derivatives of the newly smoothed data using the spline * Wraps CubicSpline derivative1D * * @param inputWorkspace :: The input workspace * @param outputWorkspace :: The output workspace * @param order :: The order of derivatives to calculate * @param row :: The row of spectra to use */ void SplineSmoothing::calculateDerivatives( const MatrixWorkspace &inputWorkspace, API::MatrixWorkspace &outputWorkspace, const int order, const size_t row) const { const auto &xIn = inputWorkspace.x(row); const double *xValues = &(xIn[0]); double *yValues = &(outputWorkspace.mutableY(order - 1)[0]); const size_t nData = xIn.size(); m_cspline->derivative1D(yValues, xValues, nData, order); }
/** Calculate smoothing of the data using the spline * Wraps CubicSpline function1D * * @param inputWorkspace :: The input workspace * @param outputWorkspace :: The output workspace * @param row :: The row of spectra to use */ void SplineSmoothing::calculateSmoothing(const MatrixWorkspace &inputWorkspace, MatrixWorkspace &outputWorkspace, size_t row) const { // define the spline's parameters const auto &xIn = inputWorkspace.x(row); const size_t nData = xIn.size(); const double *xValues = &(xIn[0]); double *yValues = &(outputWorkspace.mutableY(row)[0]); // calculate the smoothing m_cspline->function1D(yValues, xValues, nData); }
/** Defines the points used to make the spline by iteratively creating more *smoothing points * until all smoothing points fall within a certain error tolerance * * @param inputWorkspace :: The input workspace containing noisy data * @param row :: The row of spectra to use */ void SplineSmoothing::selectSmoothingPoints( const MatrixWorkspace &inputWorkspace, const size_t row) { std::set<int> smoothPts; const auto &xs = inputWorkspace.x(row); const auto &ys = inputWorkspace.y(row); // retrieving number of breaks int maxBreaks = static_cast<int>(getProperty("MaxNumberOfBreaks")); int xSize = static_cast<int>(xs.size()); // evenly space initial points over data set int delta; // if retrieved value is default zero/default bool incBreaks = false; if (maxBreaks != 0) { // number of points to start with int numSmoothPts(maxBreaks); delta = xSize / numSmoothPts; // include maxBreaks when != 0 incBreaks = true; } else { int numSmoothPts(M_START_SMOOTH_POINTS); delta = xSize / numSmoothPts; } for (int i = 0; i < xSize; i += delta) { smoothPts.insert(i); } smoothPts.insert(xSize - 1); bool resmooth(true); while (resmooth) { if (incBreaks) { if (smoothPts.size() > static_cast<unsigned>(maxBreaks + 2)) { break; } } else if (!incBreaks) { if (smoothPts.size() >= xs.size() - 1) { break; } } addSmoothingPoints(smoothPts, &xs[0], &ys[0]); resmooth = false; // calculate the spline and retrieve smoothed points boost::shared_array<double> ysmooth(new double[xSize]); m_cspline->function1D(ysmooth.get(), &xs[0], xSize); // iterate over smoothing points auto iter = smoothPts.cbegin(); int start = *iter; for (++iter; iter != smoothPts.cend(); ++iter) { int end = *iter; // check each point falls within our range of error. bool accurate = checkSmoothingAccuracy(start, end, &ys[0], ysmooth.get()); // if not, flag for resmoothing and add another point between these two // data points if (!accurate) { resmooth = true; smoothPts.insert((start + end) / 2); } start = end; } } }