Example #1
0
/**
 * This performs a similar operation to divide, but is a separate algorithm so
 *that the correct spectra are used in the case of detector scans. This
 *currently does not support event workspaces properly, but should be made to in
 *the future.
 *
 * @param inputWorkspace The workspace with the spectra to divide by the monitor
 * @param outputWorkspace The resulting workspace
 */
void NormaliseToMonitor::performHistogramDivision(
    const MatrixWorkspace_sptr &inputWorkspace,
    MatrixWorkspace_sptr &outputWorkspace) {
  if (outputWorkspace != inputWorkspace)
    outputWorkspace = inputWorkspace->clone();

  size_t monitorWorkspaceIndex = 0;

  Progress prog(this, 0.0, 1.0, m_workspaceIndexes.size());
  const auto &specInfo = inputWorkspace->spectrumInfo();
  for (const auto workspaceIndex : m_workspaceIndexes) {
    // Errors propagated according to
    // http://docs.mantidproject.org/nightly/concepts/ErrorPropagation.html#error-propagation
    // This is similar to that in MantidAlgorithms::Divide

    prog.report("Performing normalisation");

    size_t timeIndex = 0;
    if (m_scanInput)
      timeIndex = specInfo.spectrumDefinition(workspaceIndex)[0].second;

    const auto newYFactor =
        1.0 / m_monitor->histogram(monitorWorkspaceIndex).y()[0];
    const auto divisorError =
        m_monitor->histogram(monitorWorkspaceIndex).e()[0];
    const double yErrorFactor = pow(divisorError * newYFactor, 2);
    monitorWorkspaceIndex++;

    PARALLEL_FOR_IF(Kernel::threadSafe(*outputWorkspace))
    for (int64_t i = 0; i < int64_t(outputWorkspace->getNumberHistograms());
         ++i) {
      PARALLEL_START_INTERUPT_REGION
      const auto &specDef = specInfo.spectrumDefinition(i);

      if (!spectrumDefinitionsMatchTimeIndex(specDef, timeIndex))
        continue;

      auto hist = outputWorkspace->histogram(i);
      auto &yValues = hist.mutableY();
      auto &eValues = hist.mutableE();

      for (size_t j = 0; j < yValues.size(); ++j) {
        eValues[j] = newYFactor * sqrt(eValues[j] * eValues[j] +
                                       yValues[j] * yValues[j] * yErrorFactor);
        yValues[j] *= newYFactor;
      }

      outputWorkspace->setHistogram(i, hist);
      PARALLEL_END_INTERUPT_REGION
    }
    PARALLEL_CHECK_INTERUPT_REGION
  }
}
/**
* Uses linear algorithm to do the fitting.
* @param histogram the histogram to fit
* @param background an output variable for the calculated background
* @param variance an output variable for background's variance, currently always
* zero.
* @param startX an X value in the first bin to be included in the fit
* @param endX an X value in the last bin to be included in the fit
*/
void CalculateFlatBackground::LinearFit(
    const HistogramData::Histogram &histogram, double &background,
    double &variance, const double startX, const double endX) {
  MatrixWorkspace_sptr WS = WorkspaceFactory::Instance().create(
      "Workspace2D", 1, histogram.x().size(), histogram.y().size());
  WS->setHistogram(0, histogram);
  IAlgorithm_sptr childAlg = createChildAlgorithm("Fit");

  IFunction_sptr func =
      API::FunctionFactory::Instance().createFunction("LinearBackground");
  childAlg->setProperty<IFunction_sptr>("Function", func);

  childAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", WS);
  childAlg->setProperty<bool>("CreateOutput", true);
  childAlg->setProperty<int>("WorkspaceIndex", 0);
  childAlg->setProperty<double>("StartX", startX);
  childAlg->setProperty<double>("EndX", endX);
  // Default minimizer doesn't work properly even on the easiest cases,
  // so Levenberg-MarquardtMD is used instead
  childAlg->setProperty<std::string>("Minimizer", "Levenberg-MarquardtMD");

  childAlg->executeAsChildAlg();

  std::string outputStatus = childAlg->getProperty("OutputStatus");
  if (outputStatus != "success") {
    g_log.warning("Unable to successfully fit the data: " + outputStatus);
    background = -1;
    return;
  }

  Mantid::API::ITableWorkspace_sptr output =
      childAlg->getProperty("OutputParameters");

  // Find rows with parameters we are after
  size_t rowA0, rowA1;
  output->find(static_cast<std::string>("A0"), rowA0, 0);
  output->find(static_cast<std::string>("A1"), rowA1, 0);

  // Linear function is defined as A0 + A1*x
  const double intercept = output->cell<double>(rowA0, 1);
  const double slope = output->cell<double>(rowA1, 1);

  const double centre = (startX + endX) / 2.0;

  // Calculate the value of the flat background by taking the value at the
  // centre point of the fit
  background = slope * centre + intercept;
  // ATM we don't calculate the error here.
  variance = 0;
}
/// Create the efficiency workspace by combining single spectra workspaces into
/// one.
/// @param labels :: Axis labels for each workspace.
/// @param workspaces :: Workspaces to put together.
MatrixWorkspace_sptr JoinISISPolarizationEfficiencies::createEfficiencies(
    std::vector<std::string> const &labels,
    std::vector<MatrixWorkspace_sptr> const &workspaces) {
  auto interpolatedWorkspaces = interpolateWorkspaces(workspaces);

  auto const &inWS = interpolatedWorkspaces.front();
  MatrixWorkspace_sptr outWS = DataObjects::create<Workspace2D>(
      *inWS, labels.size(), inWS->histogram(0));
  auto axis1 = new TextAxis(labels.size());
  outWS->replaceAxis(1, axis1);
  outWS->getAxis(0)->setUnit("Wavelength");

  for (size_t i = 0; i < interpolatedWorkspaces.size(); ++i) {
    auto &ws = interpolatedWorkspaces[i];
    outWS->setHistogram(i, ws->histogram(0));
    axis1->setLabel(i, labels[i]);
  }

  return outWS;
}
Example #4
0
/** Create the final output workspace after converting the X axis
* @returns the final output workspace
*
* @param progress :: Progress indicator
* @param targetUnit :: Target conversion unit
* @param inputWS :: Input workspace
* @param nHist :: Stores the number of histograms
*/
MatrixWorkspace_sptr ConvertSpectrumAxis2::createOutputWorkspace(
    API::Progress &progress, const std::string &targetUnit,
    API::MatrixWorkspace_sptr &inputWS, size_t nHist) {
  // Create the output workspace. Can not re-use the input one because the
  // spectra are re-ordered.
  MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create(
      inputWS, m_indexMap.size(), inputWS->x(0).size(), inputWS->y(0).size());

  // Now set up a new numeric axis holding the theta values corresponding to
  // each spectrum.
  auto const newAxis = new NumericAxis(m_indexMap.size());
  outputWorkspace->replaceAxis(1, newAxis);

  progress.setNumSteps(nHist + m_indexMap.size());

  // Set the units of the axis.
  if (targetUnit == "theta" || targetUnit == "Theta" ||
      targetUnit == "signed_theta" || targetUnit == "SignedTheta") {
    newAxis->unit() = boost::make_shared<Units::Degrees>();
  } else if (targetUnit == "ElasticQ") {
    newAxis->unit() = UnitFactory::Instance().create("MomentumTransfer");
  } else if (targetUnit == "ElasticQSquared") {
    newAxis->unit() = UnitFactory::Instance().create("QSquared");
  }

  std::multimap<double, size_t>::const_iterator it;
  size_t currentIndex = 0;
  for (it = m_indexMap.begin(); it != m_indexMap.end(); ++it) {
    // Set the axis value.
    newAxis->setValue(currentIndex, it->first);
    // Copy over the data.
    outputWorkspace->setHistogram(currentIndex, inputWS->histogram(it->second));
    // We can keep the spectrum numbers etc.
    outputWorkspace->getSpectrum(currentIndex)
        .copyInfoFrom(inputWS->getSpectrum(it->second));
    ++currentIndex;

    progress.report("Creating output workspace...");
  }
  return outputWorkspace;
}