/** * Initializes chopper offsets and time transformer * * In this method, the instrument dependent parameter for the calculation are * setup, so that a PoldiTimeTransformer is available to transfer parameters to * the time domain using correct factors etc. * * @param poldiInstrument :: Valid PoldiInstrumentAdapter */ void PoldiSpectrumDomainFunction::initializeInstrumentParameters( const PoldiInstrumentAdapter_sptr &poldiInstrument) { m_timeTransformer = boost::make_shared<PoldiTimeTransformer>(poldiInstrument); m_chopperSlitOffsets = getChopperSlitOffsets(poldiInstrument->chopper()); if (!poldiInstrument) { throw std::runtime_error("No valid POLDI instrument."); } m_2dHelpers.clear(); PoldiAbstractDetector_sptr detector = poldiInstrument->detector(); PoldiAbstractChopper_sptr chopper = poldiInstrument->chopper(); std::pair<double, double> qLimits = detector->qLimits(1.1, 5.0); double dMin = Conversions::qToD(qLimits.second); double dMax = Conversions::dToQ(qLimits.first); for (int i = 0; i < static_cast<int>(detector->elementCount()); ++i) { double sinTheta = sin(detector->twoTheta(i) / 2.0); double distance = detector->distanceFromSample(i) + chopper->distanceFromSample(); double deltaD = Conversions::TOFtoD(m_deltaT, distance, sinTheta); Poldi2DHelper_sptr curr = boost::make_shared<Poldi2DHelper>(); curr->setChopperSlitOffsets(distance, sinTheta, deltaD, m_chopperSlitOffsets); curr->setDomain(dMin, dMax, deltaD); curr->deltaD = deltaD; curr->minTOFN = static_cast<int>( Conversions::dtoTOF(dMin, distance, sinTheta) / m_deltaT); curr->setFactors(m_timeTransformer, static_cast<size_t>(i)); m_2dHelpers.push_back(curr); } }
void PoldiAnalyseResiduals::exec() { DataObjects::Workspace2D_sptr measured = getProperty("MeasuredCountData"); DataObjects::Workspace2D_sptr calculated = getProperty("FittedCountData"); PoldiInstrumentAdapter_sptr poldiInstrument = boost::make_shared<PoldiInstrumentAdapter>(measured); // Dead wires need to be taken into account PoldiAbstractDetector_sptr deadWireDetector = boost::make_shared<PoldiDeadWireDecorator>(measured->getInstrument(), poldiInstrument->detector()); // Since the valid workspace indices are required for some calculations, we // extract and keep them const std::vector<int> &validWorkspaceIndices = deadWireDetector->availableElements(); // Subtract calculated from measured to get residuals DataObjects::Workspace2D_sptr residuals = calculateResidualWorkspace(measured, calculated); // Normalize residuals so that they are 0. normalizeResiduals(residuals, validWorkspaceIndices); // Residual correlation core which will be used iteratively. PoldiResidualCorrelationCore core(g_log, 0.1); core.setInstrument(deadWireDetector, poldiInstrument->chopper()); double lambdaMin = getProperty("LambdaMin"); double lambdaMax = getProperty("LambdaMax"); core.setWavelengthRange(lambdaMin, lambdaMax); // One iteration is always necessary DataObjects::Workspace2D_sptr sum = core.calculate(residuals, calculated); // For keeping track of the relative changes the sum of measured counts is // required double sumOfMeasuredCounts = sumCounts(measured, validWorkspaceIndices); double relativeChange = relativeCountChange(sum, sumOfMeasuredCounts); int iteration = 1; logIteration(iteration, relativeChange); // Iterate until conditions are met, accumulate correlation spectra in sum. while (nextIterationAllowed(iteration, relativeChange)) { ++iteration; DataObjects::Workspace2D_sptr corr = core.calculate(residuals, calculated); relativeChange = relativeCountChange(corr, sumOfMeasuredCounts); sum = addWorkspaces(sum, corr); logIteration(iteration, relativeChange); } g_log.notice() << "Finished after " << iteration << " iterations, final change=" << relativeChange << std::endl; // Return final correlation spectrum. setProperty("OutputWorkspace", boost::dynamic_pointer_cast<Workspace>(sum)); }