/** * 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; }
/** 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; }