/** Construct output
   */
  Workspace2D_sptr RefinePowderInstrumentParameters2::genOutputWorkspace(FunctionDomain1DVector domain,
                                                               FunctionValues rawvalues)
  {
    // 1. Create and set up output workspace
    size_t lenx = m_dataWS->readX(m_wsIndex).size();
    size_t leny = m_dataWS->readY(m_wsIndex).size();

    Workspace2D_sptr outws = boost::dynamic_pointer_cast<Workspace2D>
        (WorkspaceFactory::Instance().create("Workspace2D", 6, lenx, leny));

    outws->getAxis(0)->setUnit("dSpacing");

    TextAxis* taxis = new TextAxis(outws->getNumberHistograms());
    taxis->setLabel(0, "Data");
    taxis->setLabel(1, "Model");
    taxis->setLabel(2, "DiffDM");
    taxis->setLabel(3, "Start");
    taxis->setLabel(4, "DiffDS");
    taxis->setLabel(5, "Zdiff");
    outws->replaceAxis(1, taxis);

    // 3. Re-calculate values
    FunctionValues funcvalues(domain);
    m_positionFunc->function(domain, funcvalues);

    // 4. Add values
    // a) X axis
    for (size_t iws = 0; iws < outws->getNumberHistograms(); ++iws)
    {
      MantidVec& vecX = outws->dataX(iws);
      for (size_t n = 0; n < lenx; ++n)
        vecX[n] = domain[n];
    }

    // b) Y axis
    const MantidVec& dataY = m_dataWS->readY(m_wsIndex);

    for (size_t i = 0; i < domain.size(); ++i)
    {
      outws->dataY(0)[i] = dataY[i];
      outws->dataY(1)[i] = funcvalues[i];
      outws->dataY(2)[i] = dataY[i] - funcvalues[i];
      outws->dataY(3)[i] = rawvalues[i];
      outws->dataY(4)[i] = dataY[i] - rawvalues[i];
    }

    // 5. Zscore
    vector<double> zscore = Kernel::getZscore(outws->readY(2));
    for (size_t i = 0; i < domain.size(); ++i)
      outws->dataY(5)[i] = zscore[i];

    return outws;
  }
  /** Fit function
    * Minimizer: "Levenberg-MarquardtMD"/"Simplex"
   */
  bool RefinePowderInstrumentParameters2::doFitFunction(IFunction_sptr function, Workspace2D_sptr dataws, int wsindex,
                                                        string minimizer, int numiters, double& chi2, string& fitstatus)
  {
    // 0. Debug output
    stringstream outss;
    outss << "Fit function: " << m_positionFunc->asString() << endl << "Data To Fit: \n";
    for (size_t i = 0; i < dataws->readX(0).size(); ++i)
      outss << dataws->readX(wsindex)[i] << "\t\t" << dataws->readY(wsindex)[i] << "\t\t"
            << dataws->readE(wsindex)[i] << "\n";
    g_log.information() << outss.str();

    // 1. Create and setup fit algorithm
    API::IAlgorithm_sptr fitalg = createChildAlgorithm("Fit", 0.0, 0.2, true);
    fitalg->initialize();

    fitalg->setProperty("Function", function);
    fitalg->setProperty("InputWorkspace", dataws);
    fitalg->setProperty("WorkspaceIndex", wsindex);
    fitalg->setProperty("Minimizer", minimizer);
    fitalg->setProperty("CostFunction", "Least squares");
    fitalg->setProperty("MaxIterations", numiters);
    fitalg->setProperty("CalcErrors", true);

    // 2. Fit
    bool successfulfit = fitalg->execute();
    if (!fitalg->isExecuted() || ! successfulfit)
    {
      // Early return due to bad fit
      g_log.warning("Fitting to instrument geometry function failed. ");
      chi2 = DBL_MAX;
      fitstatus = "Minimizer throws exception.";
      return false;
    }

    // 3. Understand solution
    chi2 = fitalg->getProperty("OutputChi2overDoF");
    string tempfitstatus = fitalg->getProperty("OutputStatus");
    fitstatus = tempfitstatus;

    bool goodfit = fitstatus.compare("success") == 0;

    stringstream dbss;
    dbss << "Fit Result (GSL):  Chi^2 = " << chi2
         << "; Fit Status = " << fitstatus << ", Return Bool = " << goodfit << std::endl;
    vector<string> funcparnames = function->getParameterNames();
    for (size_t i = 0; i < funcparnames.size(); ++i)
      dbss << funcparnames[i] << " = " << setw(20) << function->getParameter(funcparnames[i])
           << " +/- " << function->getError(i) << "\n";
    g_log.debug() << dbss.str();

    return goodfit;
  }
Beispiel #3
0
void PoldiPeakSearch::exec() {
  g_log.information() << "PoldiPeakSearch:" << std::endl;

  Workspace2D_sptr correlationWorkspace = getProperty("InputWorkspace");
  MantidVec correlationQValues = correlationWorkspace->readX(0);
  MantidVec correlatedCounts = correlationWorkspace->readY(0);
  g_log.information() << "   Auto-correlation data read." << std::endl;

  Unit_sptr xUnit = correlationWorkspace->getAxis(0)->unit();

  if (xUnit->caption() == "") {
    g_log.information()
        << "   Workspace does not have unit, defaulting to MomentumTransfer."
        << std::endl;

    xUnit = UnitFactory::Instance().create("MomentumTransfer");
  } else {
    g_log.information() << "   Unit of workspace is " << xUnit->caption() << "."
                        << std::endl;
  }

  setMinimumDistance(getProperty("MinimumPeakSeparation"));
  setMinimumPeakHeight(getProperty("MinimumPeakHeight"));
  setMaximumPeakNumber(getProperty("MaximumPeakNumber"));

  if (m_doubleMinimumDistance > static_cast<int>(correlatedCounts.size())) {
    throw(std::runtime_error("MinimumPeakSeparation is smaller than number of "
                             "spectrum points - no peaks possible."));
  }

  g_log.information() << "   Parameters set." << std::endl;

  MantidVec summedNeighborCounts = getNeighborSums(correlatedCounts);
  g_log.information() << "   Neighboring counts summed, contains "
                      << summedNeighborCounts.size() << " data points."
                      << std::endl;

  std::list<MantidVec::const_iterator> peakPositionsSummed =
      findPeaks(summedNeighborCounts.begin(), summedNeighborCounts.end());
  g_log.information() << "   Peaks detected in summed spectrum: "
                      << peakPositionsSummed.size() << std::endl;

  /* This step is required because peaks are actually searched in the
   * "sum-of-neighbors"-spectrum.
   * The mapping removes the offset from the peak position which results from
   * different beginning
   * of this vector compared to the original correlation counts.
   */
  std::list<MantidVec::const_iterator> peakPositionsCorrelation =
      mapPeakPositionsToCorrelationData(peakPositionsSummed,
                                        summedNeighborCounts.begin(),
                                        correlatedCounts.begin());
  g_log.information() << "   Peak positions transformed to original spectrum."
                      << std::endl;

  /* Since intensities are required for filtering, they are extracted from the
   * original count data,
   * along with the Q-values.
   */
  std::vector<PoldiPeak_sptr> peakCoordinates =
      getPeaks(correlatedCounts.begin(), correlatedCounts.end(),
               peakPositionsCorrelation, correlationQValues, xUnit);
  g_log.information()
      << "   Extracted peak positions in Q and intensity guesses." << std::endl;

  UncertainValue backgroundWithSigma =
      getBackgroundWithSigma(peakPositionsCorrelation, correlatedCounts);
  g_log.information() << "   Calculated average background and deviation: "
                      << UncertainValueIO::toString(backgroundWithSigma)
                      << std::endl;

  if ((*getProperty("MinimumPeakHeight")).isDefault()) {
    setMinimumPeakHeight(minimumPeakHeightFromBackground(backgroundWithSigma));
  }

  std::vector<PoldiPeak_sptr> intensityFilteredPeaks(peakCoordinates.size());
  auto newEnd = std::remove_copy_if(
      peakCoordinates.begin(), peakCoordinates.end(),
      intensityFilteredPeaks.begin(),
      boost::bind(&PoldiPeakSearch::isLessThanMinimum, this, _1));
  intensityFilteredPeaks.resize(
      std::distance(intensityFilteredPeaks.begin(), newEnd));

  g_log.information() << "   Peaks above minimum intensity ("
                      << m_minimumPeakHeight
                      << "): " << intensityFilteredPeaks.size() << std::endl;

  std::sort(intensityFilteredPeaks.begin(), intensityFilteredPeaks.end(),
            boost::bind<bool>(&PoldiPeak::greaterThan, _1, _2,
                              &PoldiPeak::intensity));

  for (std::vector<PoldiPeak_sptr>::const_iterator peak =
           intensityFilteredPeaks.begin();
       peak != intensityFilteredPeaks.end(); ++peak) {
    m_peaks->addPeak(*peak);
  }

  /* The derived background error is set as error in the workspace containing
   * correlation data, so it may be used as weights for peak fitting later on.
   */
  setErrorsOnWorkspace(correlationWorkspace, backgroundWithSigma.error());

  setProperty("OutputWorkspace", m_peaks->asTableWorkspace());
}