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