Esempio n. 1
0
size_t PawleyFunction::calculateFunctionValues(
    const API::IPeakFunction_sptr &peak, const API::FunctionDomain1D &domain,
    API::FunctionValues &localValues) const {
  size_t domainSize = domain.size();
  const double *domainBegin = domain.getPointerAt(0);
  const double *domainEnd = domain.getPointerAt(domainSize);

  double centre = peak->centre();
  double dx = m_peakRadius * peak->fwhm();

  auto lb = std::lower_bound(domainBegin, domainEnd, centre - dx);
  auto ub = std::upper_bound(lb, domainEnd, centre + dx);

  size_t n = std::distance(lb, ub);

  if (n == 0) {
    throw std::invalid_argument("Null-domain");
  }

  FunctionDomain1DView localDomain(lb, n);
  localValues.reset(localDomain);

  peak->functionLocal(localValues.getPointerToCalculated(0),
                      localDomain.getPointerAt(0), n);

  return std::distance(domainBegin, lb);
}
/// Populates a spectrum with peaks of type given by peakShape argument.
/// @param spectrum :: A composite function that is a collection of peaks.
/// @param peakShape :: A shape of each peak as a name of an IPeakFunction.
/// @param centresAndIntensities :: A FunctionValues object containing centres
///        and intensities for the peaks. First nPeaks calculated values are the
///        centres and the following nPeaks values are the intensities.
/// @param xVec :: x-values of a tabulated width function.
/// @param yVec :: y-values of a tabulated width function.
/// @param fwhmVariation :: A variation in the peak width allowed in a fit.
/// @param defaultFWHM :: A default value for the FWHM to use if xVec and yVec
///        are empty.
/// @param nRequiredPeaks :: A number of peaks required to be created.
/// @param fixAllPeaks :: If true fix all peak parameters
/// @return :: The number of peaks that will be actually fitted.
size_t buildSpectrumFunction(API::CompositeFunction &spectrum,
                             const std::string &peakShape,
                             const API::FunctionValues &centresAndIntensities,
                             const std::vector<double> &xVec,
                             const std::vector<double> &yVec,
                             double fwhmVariation, double defaultFWHM,
                             size_t nRequiredPeaks, bool fixAllPeaks) {
  if (xVec.size() != yVec.size()) {
    throw std::runtime_error("WidthX and WidthY must have the same size.");
  }

  auto nPeaks = calculateNPeaks(centresAndIntensities);
  auto maxNPeaks = calculateMaxNPeaks(nPeaks);
  if (nRequiredPeaks > maxNPeaks) {
    maxNPeaks = nRequiredPeaks;
  }
  for (size_t i = 0; i < maxNPeaks; ++i) {
    const bool isGood = i < nPeaks;
    const auto centre = isGood ? centresAndIntensities.getCalculated(i) : 0.0;
    const auto intensity =
        isGood ? centresAndIntensities.getCalculated(i + nPeaks) : 0.0;
    auto peak = createPeak(peakShape, centre, intensity, xVec, yVec,
                           fwhmVariation, defaultFWHM, isGood, fixAllPeaks);
    spectrum.addFunction(peak);
  }
  return nPeaks;
}
//----------------------------------------------------------------------------------------------
/// Extract values from domain and values objects to vectors.
/// @param domain :: A domain with fitting data arguments.
/// @param values :: A FunctionValues object with the fitting data.
/// @param x :: A vector to store the domain values
/// @param y :: A vector to store the fitting data values.
void extractValues(const API::FunctionDomain1D &domain,
                   const API::FunctionValues &values, std::vector<double> &x,
                   std::vector<double> &y) {

  size_t n = domain.size();
  double start = domain[0];
  double end = domain[n - 1];
  auto dBegin = domain.getPointerAt(0);
  auto startIter = std::lower_bound(dBegin, dBegin + n, start);
  auto istart = static_cast<size_t>(std::distance(dBegin, startIter));
  if (istart == n) {
    x.clear();
    y.clear();
    return;
  }
  auto endIter = std::lower_bound(startIter, dBegin + n, end);
  auto iend = static_cast<size_t>(std::distance(dBegin, endIter));
  if (iend <= istart) {
    x.clear();
    y.clear();
    return;
  }
  n = iend - istart;
  x.resize(n);
  y.resize(n);
  for (size_t i = istart; i < iend; ++i) {
    auto j = i - istart;
    x[j] = domain[i];
    y[j] = values.getFitData(i);
  }
}
/**
 * @param index Index value into functionValues array
 * @param signal Calculated signal value
 * @param functionValues [InOut] Final calculated values
 */
void ResolutionConvolvedCrossSection::storeCalculatedWithMutex(
    const size_t index, const double signal,
    API::FunctionValues &functionValues) const {
    std::lock_guard<std::mutex> lock(m_valuesMutex);
    functionValues.setCalculated(index, signal);
}
/// Calculate the number of visible peaks.
size_t calculateNPeaks(const API::FunctionValues &centresAndIntensities) {
  return centresAndIntensities.size() / 2;
}
Esempio n. 6
0
/**
 * Create an output event workspace filled with data simulated with the fitting
 * function.
 * @param baseName :: The base name for the workspace
 * @param inputWorkspace :: The input workspace.
 * @param values :: The calculated values
 * @param outputWorkspacePropertyName :: The property name
 */
boost::shared_ptr<API::Workspace> FitMD::createEventOutputWorkspace(
    const std::string &baseName, const API::IMDEventWorkspace &inputWorkspace,
    const API::FunctionValues &values,
    const std::string &outputWorkspacePropertyName) {
  auto outputWS =
      MDEventFactory::CreateMDWorkspace(inputWorkspace.getNumDims(), "MDEvent");
  // Add events
  // TODO: Generalize to ND (the current framework is a bit limiting)
  auto mdWS = boost::dynamic_pointer_cast<
      DataObjects::MDEventWorkspace<DataObjects::MDEvent<4>, 4>>(outputWS);
  if (!mdWS) {
    return boost::shared_ptr<API::Workspace>();
  }

  // Bins extents and meta data
  for (size_t i = 0; i < 4; ++i) {
    boost::shared_ptr<const Geometry::IMDDimension> inputDim =
        inputWorkspace.getDimension(i);
    Geometry::MDHistoDimensionBuilder builder;
    builder.setName(inputDim->getName());
    builder.setId(inputDim->getDimensionId());
    builder.setUnits(inputDim->getUnits());
    builder.setNumBins(inputDim->getNBins());
    builder.setMin(inputDim->getMinimum());
    builder.setMax(inputDim->getMaximum());
    builder.setFrameName(inputDim->getMDFrame().name());

    outputWS->addDimension(builder.create());
  }

  // Run information
  outputWS->copyExperimentInfos(inputWorkspace);
  // Coordinates
  outputWS->setCoordinateSystem(inputWorkspace.getSpecialCoordinateSystem());
  // Set sensible defaults for splitting behaviour
  BoxController_sptr bc = outputWS->getBoxController();
  bc->setSplitInto(3);
  bc->setSplitThreshold(3000);
  outputWS->initialize();
  outputWS->splitBox();

  auto inputIter = inputWorkspace.createIterator();
  size_t resultValueIndex(0);
  const float errorSq = 0.0;
  do {
    const size_t numEvents = inputIter->getNumEvents();
    const float signal =
        static_cast<float>(values.getCalculated(resultValueIndex));
    for (size_t i = 0; i < numEvents; ++i) {
      coord_t centers[4] = {
          inputIter->getInnerPosition(i, 0), inputIter->getInnerPosition(i, 1),
          inputIter->getInnerPosition(i, 2), inputIter->getInnerPosition(i, 3)};
      mdWS->addEvent(MDEvent<4>(signal, errorSq, inputIter->getInnerRunIndex(i),
                                inputIter->getInnerDetectorID(i), centers));
    }
    ++resultValueIndex;
  } while (inputIter->next());
  delete inputIter;

  // This splits up all the boxes according to split thresholds and sizes.
  auto threadScheduler = new Kernel::ThreadSchedulerFIFO();
  Kernel::ThreadPool threadPool(threadScheduler);
  outputWS->splitAllIfNeeded(threadScheduler);
  threadPool.joinAll();
  outputWS->refreshCache();

  // Store it
  if (!outputWorkspacePropertyName.empty()) {
    declareProperty(
        new API::WorkspaceProperty<API::IMDEventWorkspace>(
            outputWorkspacePropertyName, "", Direction::Output),
        "Name of the output Workspace holding resulting simulated spectrum");
    m_manager->setPropertyValue(outputWorkspacePropertyName,
                                baseName + "Workspace");
    m_manager->setProperty(outputWorkspacePropertyName, outputWS);
  }

  return outputWS;
}