MatrixWorkspace_sptr
PolarizationCorrection::copyShapeAndFill(MatrixWorkspace_sptr &base,
                                         const double &value) {
  MatrixWorkspace_sptr wsTemplate = WorkspaceFactory::Instance().create(base);
  // Copy the x-array across to the new workspace.
  for (size_t i = 0; i < wsTemplate->getNumberHistograms(); ++i) {
    wsTemplate->setSharedX(i, base->sharedX(i));
  }
  auto zeroed = this->multiply(wsTemplate, 0);
  auto filled = this->add(zeroed, value);
  return filled;
}
Example #2
0
/** Carries out the bin-by-bin normalization
 *  @param inputWorkspace The input workspace
 *  @param outputWorkspace The result workspace
 */
void NormaliseToMonitor::normaliseBinByBin(
    const MatrixWorkspace_sptr &inputWorkspace,
    MatrixWorkspace_sptr &outputWorkspace) {
  EventWorkspace_sptr inputEvent =
      boost::dynamic_pointer_cast<EventWorkspace>(inputWorkspace);

  // Only create output workspace if different to input one
  if (outputWorkspace != inputWorkspace) {
    if (inputEvent) {
      outputWorkspace = inputWorkspace->clone();
    } else
      outputWorkspace = create<MatrixWorkspace>(*inputWorkspace);
  }
  auto outputEvent =
      boost::dynamic_pointer_cast<EventWorkspace>(outputWorkspace);

  const auto &inputSpecInfo = inputWorkspace->spectrumInfo();
  const auto &monitorSpecInfo = m_monitor->spectrumInfo();

  const auto specLength = inputWorkspace->blocksize();
  for (auto &workspaceIndex : m_workspaceIndexes) {
    // Get hold of the monitor spectrum
    const auto &monX = m_monitor->binEdges(workspaceIndex);
    auto monY = m_monitor->counts(workspaceIndex);
    auto monE = m_monitor->countStandardDeviations(workspaceIndex);
    size_t timeIndex = 0;
    if (m_scanInput)
      timeIndex = monitorSpecInfo.spectrumDefinition(workspaceIndex)[0].second;
    // Calculate the overall normalization just the once if bins are all
    // matching
    if (m_commonBins)
      this->normalisationFactor(monX, monY, monE);

    const size_t numHists = inputWorkspace->getNumberHistograms();
    // Flag set when a division by 0 is found
    bool hasZeroDivision = false;
    Progress prog(this, 0.0, 1.0, numHists);
    // Loop over spectra
    PARALLEL_FOR_IF(
        Kernel::threadSafe(*inputWorkspace, *outputWorkspace, *m_monitor))
    for (int64_t i = 0; i < int64_t(numHists); ++i) {
      PARALLEL_START_INTERUPT_REGION
      prog.report();

      const auto &specDef = inputSpecInfo.spectrumDefinition(i);
      if (!spectrumDefinitionsMatchTimeIndex(specDef, timeIndex))
        continue;

      const auto &X = inputWorkspace->binEdges(i);
      // If not rebinning, just point to our monitor spectra, otherwise create
      // new vectors

      auto Y = (m_commonBins ? monY : Counts(specLength));
      auto E = (m_commonBins ? monE : CountStandardDeviations(specLength));

      if (!m_commonBins) {
        // ConvertUnits can give X vectors of all zeros - skip these, they
        // cause
        // problems
        if (X.back() == 0.0 && X.front() == 0.0)
          continue;
        // Rebin the monitor spectrum to match the binning of the current data
        // spectrum
        VectorHelper::rebinHistogram(
            monX.rawData(), monY.mutableRawData(), monE.mutableRawData(),
            X.rawData(), Y.mutableRawData(), E.mutableRawData(), false);
        // Recalculate the overall normalization factor
        this->normalisationFactor(X, Y, E);
      }

      if (inputEvent) {
        // --- EventWorkspace ---
        EventList &outEL = outputEvent->getSpectrum(i);
        outEL.divide(X.rawData(), Y.mutableRawData(), E.mutableRawData());
      } else {
        // --- Workspace2D ---
        auto &YOut = outputWorkspace->mutableY(i);
        auto &EOut = outputWorkspace->mutableE(i);
        const auto &inY = inputWorkspace->y(i);
        const auto &inE = inputWorkspace->e(i);
        outputWorkspace->setSharedX(i, inputWorkspace->sharedX(i));

        // The code below comes more or less straight out of Divide.cpp
        for (size_t k = 0; k < specLength; ++k) {
          // Get the input Y's
          const double leftY = inY[k];
          const double rightY = Y[k];

          if (rightY == 0.0) {
            hasZeroDivision = true;
          }

          // Calculate result and store in local variable to avoid overwriting
          // original data if output workspace is same as one of the input
          // ones
          const double newY = leftY / rightY;

          if (fabs(rightY) > 1.0e-12 && fabs(newY) > 1.0e-12) {
            const double lhsFactor = (inE[k] < 1.0e-12 || fabs(leftY) < 1.0e-12)
                                         ? 0.0
                                         : pow((inE[k] / leftY), 2);
            const double rhsFactor =
                E[k] < 1.0e-12 ? 0.0 : pow((E[k] / rightY), 2);
            EOut[k] = std::abs(newY) * sqrt(lhsFactor + rhsFactor);
          }

          // Now store the result
          YOut[k] = newY;
        } // end Workspace2D case
      }   // end loop over current spectrum

      PARALLEL_END_INTERUPT_REGION
    } // end loop over spectra
    PARALLEL_CHECK_INTERUPT_REGION

    if (hasZeroDivision) {
      g_log.warning() << "Division by zero in some of the bins.\n";
    }
    if (inputEvent)
      outputEvent->clearMRU();
  }
}