/* * Sum up all the unmasked detector pixels. * * @param rebinnedWS: workspace where all the wavelength bins have been grouped together * @param sum: sum of all the unmasked detector pixels (counts) * @param error: error on sum (counts) * @param nPixels: number of unmasked detector pixels that contributed to sum */ void CalculateEfficiency::sumUnmaskedDetectors(MatrixWorkspace_sptr rebinnedWS, double& sum, double& error, int& nPixels) { // Number of spectra const int numberOfSpectra = static_cast<int>(rebinnedWS->getNumberHistograms()); sum = 0.0; error = 0.0; nPixels = 0; for (int i = 0; i < numberOfSpectra; i++) { progress(0.2+0.2*i/numberOfSpectra, "Computing sensitivity"); // Get the detector object for this spectrum IDetector_const_sptr det = rebinnedWS->getDetector(i); // If this detector is masked, skip to the next one if ( det->isMasked() ) continue; // If this detector is a monitor, skip to the next one if ( det->isMonitor() ) continue; // Retrieve the spectrum into a vector const MantidVec& YValues = rebinnedWS->readY(i); const MantidVec& YErrors = rebinnedWS->readE(i); sum += YValues[0]; error += YErrors[0]*YErrors[0]; nPixels++; } error = std::sqrt(error); }
/** Calculate the integral asymmetry for a pair of workspaces (red & green). * @param ws_red :: The red workspace * @param ws_green :: The green workspace * @param Y :: Reference to a variable receiving the value of asymmetry * @param E :: Reference to a variable receiving the value of the error */ void PlotAsymmetryByLogValue::calcIntAsymmetry(MatrixWorkspace_sptr ws_red, MatrixWorkspace_sptr ws_green, double &Y, double &E) { if (!m_int) { // "Differential asymmetry" MatrixWorkspace_sptr tmpWS = WorkspaceFactory::Instance().create( ws_red, 1, ws_red->readX(0).size(), ws_red->readY(0).size()); for (size_t i = 0; i < tmpWS->dataY(0).size(); i++) { double FNORM = ws_green->readY(0)[i] + ws_red->readY(0)[i]; FNORM = FNORM != 0.0 ? 1.0 / FNORM : 1.0; double BNORM = ws_green->readY(1)[i] + ws_red->readY(1)[i]; BNORM = BNORM != 0.0 ? 1.0 / BNORM : 1.0; double ZF = (ws_green->readY(0)[i] - ws_red->readY(0)[i]) * FNORM; double ZB = (ws_green->readY(1)[i] - ws_red->readY(1)[i]) * BNORM; tmpWS->dataY(0)[i] = ZB - ZF; tmpWS->dataE(0)[i] = (1.0 + ZF * ZF) * FNORM + (1.0 + ZB * ZB) * BNORM; } IAlgorithm_sptr integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace", tmpWS); integr->setProperty("RangeLower", m_minTime); integr->setProperty("RangeUpper", m_maxTime); integr->execute(); MatrixWorkspace_sptr out = integr->getProperty("OutputWorkspace"); Y = out->readY(0)[0] / static_cast<double>(tmpWS->dataY(0).size()); E = out->readE(0)[0] / static_cast<double>(tmpWS->dataY(0).size()); } else { // "Integral asymmetry" IAlgorithm_sptr integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace", ws_red); integr->setProperty("RangeLower", m_minTime); integr->setProperty("RangeUpper", m_maxTime); integr->execute(); MatrixWorkspace_sptr intWS_red = integr->getProperty("OutputWorkspace"); integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace", ws_green); integr->setProperty("RangeLower", m_minTime); integr->setProperty("RangeUpper", m_maxTime); integr->execute(); MatrixWorkspace_sptr intWS_green = integr->getProperty("OutputWorkspace"); double YIF = (intWS_green->readY(0)[0] - intWS_red->readY(0)[0]) / (intWS_green->readY(0)[0] + intWS_red->readY(0)[0]); double YIB = (intWS_green->readY(1)[0] - intWS_red->readY(1)[0]) / (intWS_green->readY(1)[0] + intWS_red->readY(1)[0]); Y = YIB - YIF; double VARIF = (1.0 + YIF * YIF) / (intWS_green->readY(0)[0] + intWS_red->readY(0)[0]); double VARIB = (1.0 + YIB * YIB) / (intWS_green->readY(1)[0] + intWS_red->readY(1)[0]); E = sqrt(VARIF + VARIB); } }
/** Calculate the integral asymmetry for a workspace. * The calculation is done by AsymmetryCalc and Integration algorithms. * @param ws :: The workspace * @param Y :: Reference to a variable receiving the value of asymmetry * @param E :: Reference to a variable receiving the value of the error */ void PlotAsymmetryByLogValue::calcIntAsymmetry(MatrixWorkspace_sptr ws, double &Y, double &E) { if (!m_int) { // "Differential asymmetry" IAlgorithm_sptr asym = createChildAlgorithm("AsymmetryCalc"); asym->setLogging(false); asym->setProperty("InputWorkspace", ws); asym->execute(); MatrixWorkspace_sptr asymWS = asym->getProperty("OutputWorkspace"); IAlgorithm_sptr integr = createChildAlgorithm("Integration"); integr->setLogging(false); integr->setProperty("InputWorkspace", asymWS); integr->setProperty("RangeLower", m_minTime); integr->setProperty("RangeUpper", m_maxTime); integr->execute(); MatrixWorkspace_sptr out = integr->getProperty("OutputWorkspace"); Y = out->readY(0)[0]; E = out->readE(0)[0]; } else { // "Integral asymmetry" IAlgorithm_sptr integr = createChildAlgorithm("Integration"); integr->setLogging(false); integr->setProperty("InputWorkspace", ws); integr->setProperty("RangeLower", m_minTime); integr->setProperty("RangeUpper", m_maxTime); integr->execute(); MatrixWorkspace_sptr intWS = integr->getProperty("OutputWorkspace"); IAlgorithm_sptr asym = createChildAlgorithm("AsymmetryCalc"); asym->setLogging(false); asym->setProperty("InputWorkspace", intWS); asym->execute(); MatrixWorkspace_sptr out = asym->getProperty("OutputWorkspace"); Y = out->readY(0)[0]; E = out->readE(0)[0]; } }
/** * Groups the workspace according to grouping provided. * * @param ws :: Workspace to group * @param g :: The grouping information * @return Sptr to created grouped workspace */ MatrixWorkspace_sptr groupWorkspace(MatrixWorkspace_const_sptr ws, const Grouping& g) { // As I couldn't specify multiple groups for GroupDetectors, I am going down quite a complicated // route - for every group distinct grouped workspace is created using GroupDetectors. These // workspaces are then merged into the output workspace. // Create output workspace MatrixWorkspace_sptr outWs = WorkspaceFactory::Instance().create(ws, g.groups.size(), ws->readX(0).size(), ws->blocksize()); for(size_t gi = 0; gi < g.groups.size(); gi++) { Mantid::API::IAlgorithm_sptr alg = AlgorithmManager::Instance().create("GroupDetectors"); alg->setChild(true); // So Output workspace is not added to the ADS alg->initialize(); alg->setProperty("InputWorkspace", boost::const_pointer_cast<MatrixWorkspace>(ws)); alg->setPropertyValue("SpectraList", g.groups[gi]); alg->setPropertyValue("OutputWorkspace", "grouped"); // Is not actually used, just to make validators happy alg->execute(); MatrixWorkspace_sptr grouped = alg->getProperty("OutputWorkspace"); // Copy the spectrum *(outWs->getSpectrum(gi)) = *(grouped->getSpectrum(0)); // Update spectrum number outWs->getSpectrum(gi)->setSpectrumNo(static_cast<specid_t>(gi)); // Copy to the output workspace outWs->dataY(gi) = grouped->readY(0); outWs->dataX(gi) = grouped->readX(0); outWs->dataE(gi) = grouped->readE(0); } return outWs; }
/** Checks input properties and compares them to previous values * @param is :: [output] Number of the first run * @param ie :: [output] Number of the last run */ void PlotAsymmetryByLogValue::checkProperties(size_t &is, size_t &ie) { // Log Value m_logName = getPropertyValue("LogValue"); // Get function to apply to logValue m_logFunc = getPropertyValue("Function"); // Get type of computation m_int = (getPropertyValue("Type") == "Integral"); // Get grouping properties m_forward_list = getProperty("ForwardSpectra"); m_backward_list = getProperty("BackwardSpectra"); // Get green and red periods m_red = getProperty("Red"); m_green = getProperty("Green"); // Get time min and time max m_minTime = getProperty("TimeMin"); m_maxTime = getProperty("TimeMax"); // Get type of dead-time corrections m_dtcType = getPropertyValue("DeadTimeCorrType"); m_dtcFile = getPropertyValue("DeadTimeCorrFile"); // Get runs std::string firstFN = getProperty("FirstRun"); std::string lastFN = getProperty("LastRun"); // Parse run names and get the number of runs parseRunNames(firstFN, lastFN, m_filenameBase, m_filenameExt, m_filenameZeros); is = atoi(firstFN.c_str()); // starting run number ie = atoi(lastFN.c_str()); // last run number if (ie < is) { throw std::runtime_error( "First run number is greater than last run number"); } // Create a string holding all the properties std::ostringstream ss; ss << m_filenameBase << "," << m_filenameExt << "," << m_filenameZeros << ","; ss << m_dtcType << "," << m_dtcFile << ","; ss << getPropertyValue("ForwardSpectra") << "," << getPropertyValue("BackwardSpectra") << ","; ss << m_int << "," << m_minTime << "," << m_maxTime << ","; ss << m_red << "," << m_green << ","; ss << m_logName << ", " << m_logFunc; m_allProperties = ss.str(); // Check if we can re-use results from previous run // We can reuse results if: // 1. There is a ws in the ADS with name m_currResName // 2. It is a MatrixWorkspace // 3. It has a title equatl to m_allProperties // This ws stores previous results as described below if (AnalysisDataService::Instance().doesExist(m_currResName)) { MatrixWorkspace_sptr prevResults = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( m_currResName); if (prevResults) { if (m_allProperties == prevResults->getTitle()) { // We can re-use results size_t nPoints = prevResults->blocksize(); size_t nHisto = prevResults->getNumberHistograms(); if (nHisto == 2) { // Only 'red' data for (size_t i = 0; i < nPoints; i++) { // The first spectrum contains: X -> run number, Y -> log value // The second spectrum contains: Y -> redY, E -> redE size_t run = static_cast<size_t>(prevResults->readX(0)[i]); if ((run >= is) && (run <= ie)) { m_logValue[run] = prevResults->readY(0)[i]; m_redY[run] = prevResults->readY(1)[i]; m_redE[run] = prevResults->readE(1)[i]; } } } else { // 'Red' and 'Green' data for (size_t i = 0; i < nPoints; i++) { // The first spectrum contains: X -> run number, Y -> log value // The second spectrum contains: Y -> diffY, E -> diffE // The third spectrum contains: Y -> redY, E -> redE // The fourth spectrum contains: Y -> greenY, E -> greeE // The fifth spectrum contains: Y -> sumY, E -> sumE size_t run = static_cast<size_t>(prevResults->readX(0)[i]); if ((run >= is) && (run <= ie)) { m_logValue[run] = prevResults->readY(0)[i]; m_diffY[run] = prevResults->readY(1)[i]; m_diffE[run] = prevResults->readE(1)[i]; m_redY[run] = prevResults->readY(2)[i]; m_redE[run] = prevResults->readE(2)[i]; m_greenY[run] = prevResults->readY(3)[i]; m_greenE[run] = prevResults->readE(3)[i]; m_sumY[run] = prevResults->readY(4)[i]; m_sumE[run] = prevResults->readE(4)[i]; } } } } } } }
/** * Set errors in Diff spectrum after a fit * @param data :: [input/output] Workspace containing spectrum to set errors to */ void ALCBaselineModellingModel::setErrorsAfterFit (MatrixWorkspace_sptr data) { data->dataE(2)=data->readE(0); }
/** * This function handles the logic for summing RebinnedOutput workspaces. * @param outputWorkspace the workspace to hold the summed input * @param progress the progress indicator * @param numSpectra * @param numMasked * @param numZeros */ void SumSpectra::doRebinnedOutput(MatrixWorkspace_sptr outputWorkspace, Progress &progress, size_t &numSpectra, size_t &numMasked, size_t &numZeros) { // Get a copy of the input workspace MatrixWorkspace_sptr temp = getProperty("InputWorkspace"); // First, we need to clean the input workspace for nan's and inf's in order // to treat the data correctly later. This will create a new private // workspace that will be retrieved as mutable. IAlgorithm_sptr alg = this->createChildAlgorithm("ReplaceSpecialValues"); alg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", temp); std::string outName = "_" + temp->getName() + "_clean"; alg->setProperty("OutputWorkspace", outName); alg->setProperty("NaNValue", 0.0); alg->setProperty("NaNError", 0.0); alg->setProperty("InfinityValue", 0.0); alg->setProperty("InfinityError", 0.0); alg->executeAsChildAlg(); MatrixWorkspace_sptr localworkspace = alg->getProperty("OutputWorkspace"); // Transform to real workspace types RebinnedOutput_sptr inWS = boost::dynamic_pointer_cast<RebinnedOutput>(localworkspace); RebinnedOutput_sptr outWS = boost::dynamic_pointer_cast<RebinnedOutput>(outputWorkspace); // Get references to the output workspaces's data vectors ISpectrum *outSpec = outputWorkspace->getSpectrum(0); MantidVec &YSum = outSpec->dataY(); MantidVec &YError = outSpec->dataE(); MantidVec &FracSum = outWS->dataF(0); MantidVec Weight; std::vector<size_t> nZeros; if (m_calculateWeightedSum) { Weight.assign(YSum.size(), 0); nZeros.assign(YSum.size(), 0); } numSpectra = 0; numMasked = 0; numZeros = 0; // Loop over spectra std::set<int>::iterator it; // for (int i = m_minSpec; i <= m_maxSpec; ++i) for (it = m_indices.begin(); it != m_indices.end(); ++it) { int i = *it; // Don't go outside the range. if ((i >= m_numberOfSpectra) || (i < 0)) { g_log.error() << "Invalid index " << i << " was specified. Sum was aborted.\n"; break; } try { // Get the detector object for this spectrum Geometry::IDetector_const_sptr det = localworkspace->getDetector(i); // Skip monitors, if the property is set to do so if (!m_keepMonitors && det->isMonitor()) continue; // Skip masked detectors if (det->isMasked()) { numMasked++; continue; } } catch (...) { // if the detector not found just carry on } numSpectra++; // Retrieve the spectrum into a vector const MantidVec &YValues = localworkspace->readY(i); const MantidVec &YErrors = localworkspace->readE(i); const MantidVec &FracArea = inWS->readF(i); if (m_calculateWeightedSum) { for (int k = 0; k < this->m_yLength; ++k) { if (YErrors[k] != 0) { double errsq = YErrors[k] * YErrors[k] * FracArea[k] * FracArea[k]; YError[k] += errsq; Weight[k] += 1. / errsq; YSum[k] += YValues[k] * FracArea[k] / errsq; FracSum[k] += FracArea[k]; } else { nZeros[k]++; FracSum[k] += FracArea[k]; } } } else { for (int k = 0; k < this->m_yLength; ++k) { YSum[k] += YValues[k] * FracArea[k]; YError[k] += YErrors[k] * YErrors[k] * FracArea[k] * FracArea[k]; FracSum[k] += FracArea[k]; } } // Map all the detectors onto the spectrum of the output outSpec->addDetectorIDs(localworkspace->getSpectrum(i)->getDetectorIDs()); progress.report(); } if (m_calculateWeightedSum) { numZeros = 0; for (size_t i = 0; i < Weight.size(); i++) { if (nZeros[i] == 0) YSum[i] *= double(numSpectra) / Weight[i]; else numZeros += nZeros[i]; } } // Create the correct representation outWS->finalize(); }
void CalculateEfficiency::normalizeDetectors(MatrixWorkspace_sptr rebinnedWS, MatrixWorkspace_sptr outputWS, double sum, double error, int nPixels, double min_eff, double max_eff) { // Number of spectra const size_t numberOfSpectra = rebinnedWS->getNumberHistograms(); // Empty vector to store the pixels that outside the acceptable efficiency range std::vector<size_t> dets_to_mask; for (size_t i = 0; i < numberOfSpectra; i++) { const double currProgress = 0.4+0.2*((double)i/(double)numberOfSpectra); progress(currProgress, "Computing sensitivity"); // Get the detector object for this spectrum IDetector_const_sptr det = rebinnedWS->getDetector(i); // If this detector is masked, skip to the next one if ( det->isMasked() ) continue; // Retrieve the spectrum into a vector const MantidVec& YIn = rebinnedWS->readY(i); const MantidVec& EIn = rebinnedWS->readE(i); MantidVec& YOut = outputWS->dataY(i); MantidVec& EOut = outputWS->dataE(i); // If this detector is a monitor, skip to the next one if ( det->isMonitor() ) { YOut[0] = 1.0; EOut[0] = 0.0; continue; } // Normalize counts to get relative efficiency YOut[0] = nPixels/sum * YIn[0]; const double err_sum = YIn[0]/sum*error; EOut[0] = nPixels/std::abs(sum) * std::sqrt(EIn[0]*EIn[0] + err_sum*err_sum); // Mask this detector if the signal is outside the acceptable band if ( !isEmpty(min_eff) && YOut[0] < min_eff ) dets_to_mask.push_back(i); if ( !isEmpty(max_eff) && YOut[0] > max_eff ) dets_to_mask.push_back(i); } // If we identified pixels to be masked, mask them now if ( !dets_to_mask.empty() ) { // Mask detectors that were found to be outside the acceptable efficiency band try { IAlgorithm_sptr mask = createChildAlgorithm("MaskDetectors", 0.8, 0.9); // First we mask detectors in the output workspace mask->setProperty<MatrixWorkspace_sptr>("Workspace", outputWS); mask->setProperty< std::vector<size_t> >("WorkspaceIndexList", dets_to_mask); mask->execute(); mask = createChildAlgorithm("MaskDetectors", 0.9, 1.0); // Then we mask the same detectors in the input workspace mask->setProperty<MatrixWorkspace_sptr>("Workspace", rebinnedWS); mask->setProperty< std::vector<size_t> >("WorkspaceIndexList", dets_to_mask); mask->execute(); } catch (std::invalid_argument& err) { std::stringstream e; e << "Invalid argument to MaskDetectors Child Algorithm: " << err.what(); g_log.error(e.str()); } catch (std::runtime_error& err) { std::stringstream e; e << "Unable to successfully run MaskDetectors Child Algorithm: " << err.what(); g_log.error(e.str()); } } }
/** Execute the algorithm. */ void MaxEnt::exec() { // MaxEnt parameters // Complex data? bool complex = getProperty("ComplexData"); // Image must be positive? bool positiveImage = getProperty("PositiveImage"); // Autoshift bool autoShift = getProperty("AutoShift"); // Increase the number of points in the image by this factor size_t densityFactor = getProperty("DensityFactor"); // Background (default level, sky background, etc) double background = getProperty("A"); // Chi target double chiTarget = getProperty("ChiTarget"); // Required precision for Chi arget double chiEps = getProperty("ChiEps"); // Maximum degree of non-parallelism between S and C double angle = getProperty("MaxAngle"); // Distance penalty for current image double distEps = getProperty("DistancePenalty"); // Maximum number of iterations size_t niter = getProperty("MaxIterations"); // Maximum number of iterations in alpha chop size_t alphaIter = getProperty("AlphaChopIterations"); // Number of spectra and datapoints // Read input workspace MatrixWorkspace_sptr inWS = getProperty("InputWorkspace"); // Number of spectra size_t nspec = inWS->getNumberHistograms(); // Number of data points size_t npoints = inWS->blocksize() * densityFactor; // Number of X bins size_t npointsX = inWS->isHistogramData() ? npoints + 1 : npoints; // The type of entropy we are going to use (depends on the type of image, // positive only, or positive and/or negative) MaxentData_sptr maxentData; if (positiveImage) { maxentData = boost::make_shared<MaxentData>( boost::make_shared<MaxentEntropyPositiveValues>()); } else { maxentData = boost::make_shared<MaxentData>( boost::make_shared<MaxentEntropyNegativeValues>()); } // Output workspaces MatrixWorkspace_sptr outImageWS; MatrixWorkspace_sptr outDataWS; MatrixWorkspace_sptr outEvolChi; MatrixWorkspace_sptr outEvolTest; nspec = complex ? nspec / 2 : nspec; outImageWS = WorkspaceFactory::Instance().create(inWS, 2 * nspec, npointsX, npoints); outDataWS = WorkspaceFactory::Instance().create(inWS, 2 * nspec, npointsX, npoints); outEvolChi = WorkspaceFactory::Instance().create(inWS, nspec, niter, niter); outEvolTest = WorkspaceFactory::Instance().create(inWS, nspec, niter, niter); npoints *= 2; for (size_t s = 0; s < nspec; s++) { // Start distribution (flat background) std::vector<double> image(npoints, background); if (complex) { auto dataRe = inWS->readY(s); auto dataIm = inWS->readY(s + nspec); auto errorsRe = inWS->readE(s); auto errorsIm = inWS->readE(s + nspec); maxentData->loadComplex(dataRe, dataIm, errorsRe, errorsIm, image, background); } else { auto data = inWS->readY(s); auto error = inWS->readE(s); maxentData->loadReal(data, error, image, background); } // To record the algorithm's progress std::vector<double> evolChi(niter, 0.); std::vector<double> evolTest(niter, 0.); // Progress Progress progress(this, 0, 1, niter); // Run maxent algorithm for (size_t it = 0; it < niter; it++) { // Calculate quadratic model coefficients // (SB eq. 21 and 24) maxentData->calculateQuadraticCoefficients(); double currAngle = maxentData->getAngle(); double currChisq = maxentData->getChisq(); auto coeffs = maxentData->getQuadraticCoefficients(); // Calculate delta to construct new image (SB eq. 25) auto delta = move(coeffs, chiTarget / currChisq, chiEps, alphaIter); // Apply distance penalty (SB eq. 33) image = maxentData->getImage(); delta = applyDistancePenalty(delta, coeffs, image, background, distEps); // Update image according to 'delta' and calculate the new Chi-square maxentData->updateImage(delta); currChisq = maxentData->getChisq(); // Record the evolution of Chi-square and angle(S,C) evolChi[it] = currChisq; evolTest[it] = currAngle; // Stop condition, solution found if ((std::abs(currChisq / chiTarget - 1.) < chiEps) && (currAngle < angle)) { break; } // Check for canceling the algorithm if (!(it % 1000)) { interruption_point(); } progress.report(); } // iterations // Get calculated data auto solData = maxentData->getReconstructedData(); auto solImage = maxentData->getImage(); // Populate the output workspaces populateDataWS(inWS, s, nspec, solData, outDataWS); populateImageWS(inWS, s, nspec, solImage, outImageWS, autoShift); // Populate workspaces recording the evolution of Chi and Test // X values for (size_t it = 0; it < niter; it++) { outEvolChi->dataX(s)[it] = static_cast<double>(it); outEvolTest->dataX(s)[it] = static_cast<double>(it); } // Y values outEvolChi->dataY(s).assign(evolChi.begin(), evolChi.end()); outEvolTest->dataY(s).assign(evolTest.begin(), evolTest.end()); // No errors } // Next spectrum setProperty("EvolChi", outEvolChi); setProperty("EvolAngle", outEvolTest); setProperty("ReconstructedImage", outImageWS); setProperty("ReconstructedData", outDataWS); }
/** Calculate the integral asymmetry for a workspace (red & green). * The calculation is done by MuonAsymmetryCalc and SimpleIntegration algorithms. * @param ws_red :: The red workspace * @param ws_green :: The green workspace * @param Y :: Reference to a variable receiving the value of asymmetry * @param E :: Reference to a variable receiving the value of the error */ void PlotAsymmetryByLogValue::calcIntAsymmetry(API::MatrixWorkspace_sptr ws_red, API::MatrixWorkspace_sptr ws_green,double& Y, double& E) { if ( !m_autogroup ) { groupDetectors(ws_red,m_backward_list); groupDetectors(ws_red,m_forward_list); groupDetectors(ws_green,m_backward_list); groupDetectors(ws_green,m_forward_list); } Property* startXprop = getProperty("TimeMin"); Property* endXprop = getProperty("TimeMax"); bool setX = !startXprop->isDefault() && !endXprop->isDefault(); double startX(0.0),endX(0.0); if (setX) { startX = getProperty("TimeMin"); endX = getProperty("TimeMax"); } if (!m_int) { // "Differential asymmetry" API::MatrixWorkspace_sptr tmpWS = API::WorkspaceFactory::Instance().create( ws_red,1,ws_red->readX(0).size(),ws_red->readY(0).size()); for(size_t i=0; i<tmpWS->dataY(0).size(); i++) { double FNORM = ws_green->readY(0)[i] + ws_red->readY(0)[i]; FNORM = FNORM != 0.0 ? 1.0 / FNORM : 1.0; double BNORM = ws_green->readY(1)[i] + ws_red->readY(1)[i]; BNORM = BNORM != 0.0 ? 1.0 / BNORM : 1.0; double ZF = ( ws_green->readY(0)[i] - ws_red->readY(0)[i] ) * FNORM; double ZB = ( ws_green->readY(1)[i] - ws_red->readY(1)[i] ) * BNORM; tmpWS->dataY(0)[i] = ZB - ZF; tmpWS->dataE(0)[i] = (1.0+ZF*ZF)*FNORM+(1.0+ZB*ZB)*BNORM; } IAlgorithm_sptr integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace",tmpWS); integr->setPropertyValue("OutputWorkspace","tmp"); if (setX) { integr->setProperty("RangeLower",startX); integr->setProperty("RangeUpper",endX); } integr->execute(); MatrixWorkspace_sptr out = integr->getProperty("OutputWorkspace"); Y = out->readY(0)[0] / static_cast<double>(tmpWS->dataY(0).size()); E = out->readE(0)[0] / static_cast<double>(tmpWS->dataY(0).size()); } else { // "Integral asymmetry" IAlgorithm_sptr integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace", ws_red); integr->setPropertyValue("OutputWorkspace","tmp"); if (setX) { integr->setProperty("RangeLower",startX); integr->setProperty("RangeUpper",endX); } integr->execute(); API::MatrixWorkspace_sptr intWS_red = integr->getProperty("OutputWorkspace"); integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace", ws_green); integr->setPropertyValue("OutputWorkspace","tmp"); if (setX) { integr->setProperty("RangeLower",startX); integr->setProperty("RangeUpper",endX); } integr->execute(); API::MatrixWorkspace_sptr intWS_green = integr->getProperty("OutputWorkspace"); double YIF = ( intWS_green->readY(0)[0] - intWS_red->readY(0)[0] ) / ( intWS_green->readY(0)[0] + intWS_red->readY(0)[0] ); double YIB = ( intWS_green->readY(1)[0] - intWS_red->readY(1)[0] ) / ( intWS_green->readY(1)[0] + intWS_red->readY(1)[0] ); Y = YIB - YIF; double VARIF = (1.0 + YIF*YIF) / ( intWS_green->readY(0)[0] + intWS_red->readY(0)[0] ); double VARIB = (1.0 + YIB*YIB) / ( intWS_green->readY(1)[0] + intWS_red->readY(1)[0] ); E = sqrt( VARIF + VARIB ); } }
/** Calculate the integral asymmetry for a workspace. * The calculation is done by MuonAsymmetryCalc and SimpleIntegration algorithms. * @param ws :: The workspace * @param Y :: Reference to a variable receiving the value of asymmetry * @param E :: Reference to a variable receiving the value of the error */ void PlotAsymmetryByLogValue::calcIntAsymmetry(API::MatrixWorkspace_sptr ws, double& Y, double& E) { Property* startXprop = getProperty("TimeMin"); Property* endXprop = getProperty("TimeMax"); bool setX = !startXprop->isDefault() && !endXprop->isDefault(); double startX(0.0),endX(0.0); if (setX) { startX = getProperty("TimeMin"); endX = getProperty("TimeMax"); } if (!m_int) { // "Differential asymmetry" IAlgorithm_sptr asym = createChildAlgorithm("AsymmetryCalc"); asym->initialize(); asym->setProperty("InputWorkspace",ws); asym->setPropertyValue("OutputWorkspace","tmp"); if ( !m_autogroup ) { asym->setProperty("ForwardSpectra",m_forward_list); asym->setProperty("BackwardSpectra",m_backward_list); } asym->execute(); MatrixWorkspace_sptr asymWS = asym->getProperty("OutputWorkspace"); IAlgorithm_sptr integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace",asymWS); integr->setPropertyValue("OutputWorkspace","tmp"); if (setX) { integr->setProperty("RangeLower",startX); integr->setProperty("RangeUpper",endX); } integr->execute(); API::MatrixWorkspace_sptr out = integr->getProperty("OutputWorkspace"); Y = out->readY(0)[0]; E = out->readE(0)[0]; } else { // "Integral asymmetry" IAlgorithm_sptr integr = createChildAlgorithm("Integration"); integr->setProperty("InputWorkspace", ws); integr->setPropertyValue("OutputWorkspace","tmp"); if (setX) { integr->setProperty("RangeLower",startX); integr->setProperty("RangeUpper",endX); } integr->execute(); API::MatrixWorkspace_sptr intWS = integr->getProperty("OutputWorkspace"); IAlgorithm_sptr asym = createChildAlgorithm("AsymmetryCalc"); asym->initialize(); asym->setProperty("InputWorkspace",intWS); asym->setPropertyValue("OutputWorkspace","tmp"); if ( !m_autogroup ) { asym->setProperty("ForwardSpectra",m_forward_list); asym->setProperty("BackwardSpectra",m_backward_list); } asym->execute(); MatrixWorkspace_sptr out = asym->getProperty("OutputWorkspace"); Y = out->readY(0)[0]; E = out->readE(0)[0]; } }
void SofQWCentre::exec() { using namespace Geometry; MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace"); // Do the full check for common binning if (!WorkspaceHelpers::commonBoundaries(inputWorkspace)) { g_log.error( "The input workspace must have common binning across all spectra"); throw std::invalid_argument( "The input workspace must have common binning across all spectra"); } std::vector<double> verticalAxis; MatrixWorkspace_sptr outputWorkspace = setUpOutputWorkspace( inputWorkspace, getProperty("QAxisBinning"), verticalAxis); setProperty("OutputWorkspace", outputWorkspace); // Holds the spectrum-detector mapping std::vector<specnum_t> specNumberMapping; std::vector<detid_t> detIDMapping; m_EmodeProperties.initCachedValues(*inputWorkspace, this); int emode = m_EmodeProperties.m_emode; // Get a pointer to the instrument contained in the workspace Instrument_const_sptr instrument = inputWorkspace->getInstrument(); // Get the distance between the source and the sample (assume in metres) IComponent_const_sptr source = instrument->getSource(); IComponent_const_sptr sample = instrument->getSample(); V3D beamDir = sample->getPos() - source->getPos(); beamDir.normalize(); try { double l1 = source->getDistance(*sample); g_log.debug() << "Source-sample distance: " << l1 << '\n'; } catch (Exception::NotFoundError &) { g_log.error("Unable to calculate source-sample distance"); throw Exception::InstrumentDefinitionError( "Unable to calculate source-sample distance", inputWorkspace->getTitle()); } // Conversion constant for E->k. k(A^-1) = sqrt(energyToK*E(meV)) const double energyToK = 8.0 * M_PI * M_PI * PhysicalConstants::NeutronMass * PhysicalConstants::meV * 1e-20 / (PhysicalConstants::h * PhysicalConstants::h); // Loop over input workspace bins, reassigning data to correct bin in output // qw workspace const size_t numHists = inputWorkspace->getNumberHistograms(); const size_t numBins = inputWorkspace->blocksize(); Progress prog(this, 0.0, 1.0, numHists); for (int64_t i = 0; i < int64_t(numHists); ++i) { try { // Now get the detector object for this histogram IDetector_const_sptr spectrumDet = inputWorkspace->getDetector(i); if (spectrumDet->isMonitor()) continue; const double efixed = m_EmodeProperties.getEFixed(*spectrumDet); // For inelastic scattering the simple relationship q=4*pi*sinTheta/lambda // does not hold. In order to // be completely general we must calculate the momentum transfer by // calculating the incident and final // wave vectors and then use |q| = sqrt[(ki - kf)*(ki - kf)] DetectorGroup_const_sptr detGroup = boost::dynamic_pointer_cast<const DetectorGroup>(spectrumDet); std::vector<IDetector_const_sptr> detectors; if (detGroup) { detectors = detGroup->getDetectors(); } else { detectors.push_back(spectrumDet); } const size_t numDets = detectors.size(); const double numDets_d = static_cast<double>( numDets); // cache to reduce number of static casts const MantidVec &Y = inputWorkspace->readY(i); const MantidVec &E = inputWorkspace->readE(i); const MantidVec &X = inputWorkspace->readX(i); // Loop over the detectors and for each bin calculate Q for (size_t idet = 0; idet < numDets; ++idet) { IDetector_const_sptr det = detectors[idet]; // Calculate kf vector direction and then Q for each energy bin V3D scatterDir = (det->getPos() - sample->getPos()); scatterDir.normalize(); for (size_t j = 0; j < numBins; ++j) { const double deltaE = 0.5 * (X[j] + X[j + 1]); // Compute ki and kf wave vectors and therefore q = ki - kf double ei(0.0), ef(0.0); if (emode == 1) { ei = efixed; ef = efixed - deltaE; if (ef < 0) { std::string mess = "Energy transfer requested in Direct mode exceeds incident " "energy.\n Found for det ID: " + std::to_string(idet) + " bin No " + std::to_string(j) + " with Ei=" + boost::lexical_cast<std::string>(efixed) + " and energy transfer: " + boost::lexical_cast<std::string>(deltaE); throw std::runtime_error(mess); } } else { ei = efixed + deltaE; ef = efixed; if (ef < 0) { std::string mess = "Incident energy of a neutron is negative. Are you trying to " "process Direct data in Indirect mode?\n Found for det ID: " + std::to_string(idet) + " bin No " + std::to_string(j) + " with efied=" + boost::lexical_cast<std::string>(efixed) + " and energy transfer: " + boost::lexical_cast<std::string>(deltaE); throw std::runtime_error(mess); } } if (ei < 0) throw std::runtime_error( "Negative incident energy. Check binning."); const V3D ki = beamDir * sqrt(energyToK * ei); const V3D kf = scatterDir * (sqrt(energyToK * (ef))); const double q = (ki - kf).norm(); // Test whether it's in range of the Q axis if (q < verticalAxis.front() || q > verticalAxis.back()) continue; // Find which q bin this point lies in const MantidVec::difference_type qIndex = std::upper_bound(verticalAxis.begin(), verticalAxis.end(), q) - verticalAxis.begin() - 1; // Add this spectra-detector pair to the mapping specNumberMapping.push_back( outputWorkspace->getSpectrum(qIndex).getSpectrumNo()); detIDMapping.push_back(det->getID()); // And add the data and it's error to that bin, taking into account // the number of detectors contributing to this bin outputWorkspace->dataY(qIndex)[j] += Y[j] / numDets_d; // Standard error on the average outputWorkspace->dataE(qIndex)[j] = sqrt((pow(outputWorkspace->readE(qIndex)[j], 2) + pow(E[j], 2)) / numDets_d); } } } catch (Exception::NotFoundError &) { // Get to here if exception thrown when calculating distance to detector // Presumably, if we get to here the spectrum will be all zeroes anyway // (from conversion to E) continue; } prog.report(); } // If the input workspace was a distribution, need to divide by q bin width if (inputWorkspace->isDistribution()) this->makeDistribution(outputWorkspace, verticalAxis); // Set the output spectrum-detector mapping SpectrumDetectorMapping outputDetectorMap(specNumberMapping, detIDMapping); outputWorkspace->updateSpectraUsing(outputDetectorMap); }
/** Convert a SPICE 2D Det MatrixWorkspace to MDEvents and append to an * MDEventWorkspace * It is optional to use a virtual instrument or copy from input data workspace * @brief ConvertCWSDExpToMomentum::convertSpiceMatrixToMomentumMDEvents * @param dataws :: data matrix workspace * @param usevirtual :: boolean flag to use virtual instrument * @param startdetid :: starting detid for detectors from this workspace mapping * to virtual instrument in MDEventWorkspace * @param runnumber :: run number for all MDEvents created from this matrix * workspace */ void ConvertCWSDExpToMomentum::convertSpiceMatrixToMomentumMDEvents( MatrixWorkspace_sptr dataws, bool usevirtual, const detid_t &startdetid, const int runnumber) { // Create transformation matrix from which the transformation is Kernel::DblMatrix rotationMatrix; setupTransferMatrix(dataws, rotationMatrix); g_log.information() << "Before insert new event, output workspace has " << m_outputWS->getNEvents() << "Events.\n"; // Creates a new instance of the MDEventInserte to output workspace MDEventWorkspace<MDEvent<3>, 3>::sptr mdws_mdevt_3 = boost::dynamic_pointer_cast<MDEventWorkspace<MDEvent<3>, 3>>(m_outputWS); MDEventInserter<MDEventWorkspace<MDEvent<3>, 3>::sptr> inserter(mdws_mdevt_3); // Calcualte k_i: it is assumed that all k_i are same for one Pt. // number, i.e., one 2D XML file Kernel::V3D sourcePos = dataws->getInstrument()->getSource()->getPos(); Kernel::V3D samplePos = dataws->getInstrument()->getSample()->getPos(); if (dataws->readX(0).size() != 2) throw std::runtime_error( "Input matrix workspace has wrong dimension in X-axis."); double momentum = 0.5 * (dataws->readX(0)[0] + dataws->readX(0)[1]); Kernel::V3D ki = (samplePos - sourcePos) * (momentum / sourcePos.norm()); g_log.debug() << "Source at " << sourcePos.toString() << ", Norm = " << sourcePos.norm() << ", momentum = " << momentum << "\n" << "k_i = " << ki.toString() << "\n"; // Go though each spectrum to conver to MDEvent size_t numspec = dataws->getNumberHistograms(); double maxsignal = 0; size_t nummdevents = 0; for (size_t iws = 0; iws < numspec; ++iws) { // Get detector positions and signal double signal = dataws->readY(iws)[0]; // Skip event with 0 signal if (signal < 0.001) continue; double error = dataws->readE(iws)[0]; Kernel::V3D detpos = dataws->getDetector(iws)->getPos(); std::vector<Mantid::coord_t> q_sample(3); // Calculate Q-sample and new detector ID in virtual instrument. Kernel::V3D qlab = convertToQSample(samplePos, ki, detpos, momentum, q_sample, rotationMatrix); detid_t native_detid = dataws->getDetector(iws)->getID(); detid_t detid = native_detid + startdetid; // Insert inserter.insertMDEvent( static_cast<float>(signal), static_cast<float>(error * error), static_cast<uint16_t>(runnumber), detid, q_sample.data()); updateQRange(q_sample); g_log.debug() << "Q-lab = " << qlab.toString() << "\n"; g_log.debug() << "Insert DetID " << detid << ", signal = " << signal << ", with q_sample = " << q_sample[0] << ", " << q_sample[1] << ", " << q_sample[2] << "\n"; // Update some statistical inforamtion if (signal > maxsignal) maxsignal = signal; ++nummdevents; } g_log.information() << "Imported Matrixworkspace: Max. Signal = " << maxsignal << ", Add " << nummdevents << " MDEvents " << "\n"; // Add experiment info including instrument, goniometer and run number ExperimentInfo_sptr expinfo = boost::make_shared<ExperimentInfo>(); if (usevirtual) expinfo->setInstrument(m_virtualInstrument); else { Geometry::Instrument_const_sptr tmp_inst = dataws->getInstrument(); expinfo->setInstrument(tmp_inst); } expinfo->mutableRun().setGoniometer(dataws->run().getGoniometer(), false); expinfo->mutableRun().addProperty("run_number", runnumber); // Add all the other propertys from original data workspace const std::vector<Kernel::Property *> vec_property = dataws->run().getProperties(); for (auto property : vec_property) { expinfo->mutableRun().addProperty(property->clone()); } m_outputWS->addExperimentInfo(expinfo); return; }
//---------------------------------------------------------------------------------------------- /// @copydoc Mantid::API::Algorithm::exec() void ResetNegatives::exec() { MatrixWorkspace_sptr inputWS = this->getProperty("InputWorkspace"); MatrixWorkspace_sptr outputWS = this->getProperty("OutputWorkspace"); // get the minimum for each spectrum IAlgorithm_sptr alg = this->createChildAlgorithm("Min", 0., .1); alg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", inputWS); alg->executeAsChildAlg(); MatrixWorkspace_const_sptr minWS = alg->getProperty("OutputWorkspace"); // determine if there is anything to do int64_t nHist = static_cast<int64_t>(minWS->getNumberHistograms()); bool hasNegative = false; for (int64_t i = 0; i < nHist; i++) { if (minWS->readY(i)[0] < 0) { hasNegative = true; } break; } // get out early if there is nothing to do if (!hasNegative) { g_log.information() << "No values are negative. Copying InputWorkspace to OutputWorkspace\n"; if (inputWS != outputWS) { IAlgorithm_sptr alg = this->createChildAlgorithm("CloneWorkspace", .1, 1.); alg->setProperty<Workspace_sptr>("InputWorkspace", inputWS); alg->executeAsChildAlg(); Workspace_sptr temp = alg->getProperty("OutputWorkspace"); setProperty("OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(temp)); } return; } // sort the event list to make it fast and thread safe DataObjects::EventWorkspace_const_sptr eventWS = boost::dynamic_pointer_cast<const DataObjects::EventWorkspace>( inputWS ); if (eventWS) eventWS->sortAll(DataObjects::TOF_SORT, NULL); Progress prog(this, .1, 1., 2*nHist); // generate output workspace - copy X and dY outputWS = API::WorkspaceFactory::Instance().create(inputWS); PARALLEL_FOR2(inputWS,outputWS) for (int64_t i = 0; i < nHist; i++) { PARALLEL_START_INTERUPT_REGION outputWS->dataY(i) = inputWS->readY(i); outputWS->dataE(i) = inputWS->readE(i); outputWS->setX(i, inputWS->refX(i)); // share the pointer more prog.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION // do the actual work if (this->getProperty("AddMinimum")) { this->pushMinimum(minWS, outputWS, prog); } else { this->changeNegatives(minWS, this->getProperty("ResetValue"), outputWS, prog); } setProperty("OutputWorkspace",outputWS); }