Example #1
0
/** Executes the algorithm
 */
void MultiplyRange::exec()
{
  // Get the input workspace and other properties
  MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace");
  m_startBin = getProperty("StartBin");
  m_endBin = getProperty("EndBin");
  m_factor = getProperty("Factor");

  // A few checks on the input properties
  const int specSize = static_cast<int>(inputWS->blocksize());
  if ( isEmpty(m_endBin) ) m_endBin = specSize - 1;

  if ( m_endBin >= specSize )
  {
    g_log.error("EndBin out of range!");
    throw std::out_of_range("EndBin out of range!");
  }
  if ( m_endBin < m_startBin )
  {
    g_log.error("StartBin must be less than or equal to EndBin");
    throw std::out_of_range("StartBin must be less than or equal to EndBin");
  }

  // Only create the output workspace if it's different to the input one
  MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
  if ( outputWS != inputWS )
  {
    outputWS = WorkspaceFactory::Instance().create(inputWS);
    setProperty("OutputWorkspace",outputWS);
  }

  // Get the count of histograms in the input workspace
  const int histogramCount = static_cast<int>(inputWS->getNumberHistograms());
  Progress progress(this,0.0,1.0,histogramCount);
  // Loop over spectra
  PARALLEL_FOR2(inputWS,outputWS)
  for (int i = 0; i < histogramCount; ++i)
  {
    PARALLEL_START_INTERUPT_REGION
    // Copy over the bin boundaries
    outputWS->setX(i,inputWS->refX(i));
    // Copy over the data
    outputWS->dataY(i) = inputWS->readY(i);
    outputWS->dataE(i) = inputWS->readE(i);
    MantidVec& newY = outputWS->dataY(i);
    MantidVec& newE = outputWS->dataE(i);

    // Now multiply the requested range
    std::transform(newY.begin()+m_startBin,newY.begin()+m_endBin+1,newY.begin()+m_startBin,
                     std::bind2nd(std::multiplies<double>(),m_factor));
    std::transform(newE.begin()+m_startBin,newE.begin()+m_endBin+1,newE.begin()+m_startBin,
                     std::bind2nd(std::multiplies<double>(),m_factor));

    progress.report();
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION

}
Example #2
0
void SmoothData::exec()
{
  // Get the input properties
  MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace");

  int npts = getProperty("NPoints");
  // Number of smoothing points must always be an odd number, so add 1 if it isn't.
  if (!(npts%2))
  {
    g_log.information("Adding 1 to number of smoothing points, since it must always be odd");
    ++npts;
  }

  // Check that the number of points in the smoothing isn't larger than the spectrum length
  const int vecSize = static_cast<int>(inputWorkspace->blocksize());
  if ( npts >= vecSize )
  {
    g_log.error("The number of averaging points requested is larger than the spectrum length");
    throw std::out_of_range("The number of averaging points requested is larger than the spectrum length");
  }
  const int halfWidth = (npts-1)/2;

  // Create the output workspace
  MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create(inputWorkspace);

  Progress progress(this,0.0,1.0,inputWorkspace->getNumberHistograms());
  PARALLEL_FOR2(inputWorkspace,outputWorkspace)
  // Loop over all the spectra in the workspace
  for (int i = 0; i < static_cast<int>(inputWorkspace->getNumberHistograms()); ++i)
  {
    PARALLEL_START_INTERUPT_REGION
    // Copy the X data over. Preserves data sharing if present in input workspace.
    outputWorkspace->setX(i,inputWorkspace->refX(i));

    // Now get references to the Y & E vectors in the input and output workspaces
    const MantidVec &Y = inputWorkspace->readY(i);
    const MantidVec &E = inputWorkspace->readE(i);
    MantidVec &newY = outputWorkspace->dataY(i);
    MantidVec &newE = outputWorkspace->dataE(i);

    // Use total to help hold our moving average
    double total = 0.0, totalE = 0.0;
    // First push the values ahead of the current point onto total
    for (int i = 0; i < halfWidth; ++i)
    {
      if ( Y[i] == Y[i] ) total += Y[i]; // Exclude if NaN
      totalE += E[i]*E[i];
    }
    // Now calculate the smoothed values for the 'end' points, where the number contributing
    // to the smoothing will be less than NPoints
    for (int j = 0; j <= halfWidth; ++j)
    {
      const int index = j+halfWidth;
      if ( Y[index] == Y[index] ) total += Y[index]; // Exclude if NaN
      newY[j] = total/(index+1);
      totalE += E[index]*E[index];
      newE[j] = sqrt(totalE)/(index+1);
    }
    // This is the main part, where each data point is the average of NPoints points centred on the
    // current point. Note that the statistical error will be reduced by sqrt(npts) because more
    // data is now contributing to each point.
    for (int k = halfWidth+1; k < vecSize-halfWidth; ++k)
    {
      const int kp = k+halfWidth;
      const int km = k-halfWidth-1;
      total += (Y[kp]!=Y[kp] ? 0.0 : Y[kp]) - (Y[km]!=Y[km] ? 0.0 : Y[km]); // Exclude if NaN
      newY[k] = total/npts;
      totalE += E[kp]*E[kp] - E[km]*E[km];
      // Use of a moving average can lead to rounding error where what should be 
      // zero actually comes out as a tiny negative number - bad news for sqrt so protect
      newE[k] = std::sqrt(std::abs(totalE))/npts;
    }
    // This deals with the 'end' at the tail of each spectrum
    for (int l = vecSize-halfWidth; l < vecSize; ++l)
    {
      const int index = l-halfWidth;
      total -= (Y[index-1]!=Y[index-1] ? 0.0 : Y[index-1]); // Exclude if NaN
      newY[l] = total/(vecSize-index);
      totalE -= E[index-1]*E[index-1];
      newE[l] = std::sqrt(std::abs(totalE))/(vecSize-index);
    }
    progress.report();
    PARALLEL_END_INTERUPT_REGION
  } // Loop over spectra
  PARALLEL_CHECK_INTERUPT_REGION

  // Set the output workspace to its property
  setProperty("OutputWorkspace", outputWorkspace);
}