std::map<std::string, std::string> CopyDetectorMapping::validateInputs() { std::map<std::string, std::string> issues; MatrixWorkspace_sptr wsToMatch = getProperty("WorkspaceToMatch"); MatrixWorkspace_sptr wsToRemap = getProperty("WorkspaceToRemap"); // Check that the workspaces actually are MatrixWorkspaces bool validWorkspaces = true; if (wsToMatch == NULL) { issues["WorkspaceToMatch"] = "Must be a MatrixWorkspace"; validWorkspaces = false; } if (wsToRemap == NULL) { issues["WorkspaceToRemap"] = "Must be a MatrixWorkspace"; validWorkspaces = false; } // Check histohram counts match (assuming both are MatrixWorkspaces) if (validWorkspaces && wsToMatch->getNumberHistograms() != wsToRemap->getNumberHistograms()) issues["WorkspaceToRemap"] = "Number of histograms must match WorkspaceToMatch"; return issues; }
/** Compares the properties of the input workspace with the reference * @param ws : the testee workspace * @param checkNumberHistograms : whether to check also the number of histograms * @return : empty if compatible, error message otherwises */ std::string RunCombinationHelper::checkCompatibility(MatrixWorkspace_sptr ws, bool checkNumberHistograms) { std::string errors; if (ws->getNumberHistograms() != m_numberSpectra && checkNumberHistograms) errors += "different number of histograms; "; if (ws->getAxis(0)->unit()->unitID() != m_xUnit) errors += "different X units; "; if (ws->getAxis(1)->unit()->unitID() != m_spectrumAxisUnit) errors += "different spectrum axis units; "; if (ws->YUnit() != m_yUnit) errors += "different Y units; "; if (ws->isHistogramData() != m_isHistogramData) errors += "different distribution or histogram type; "; if (ws->detectorInfo().isScanning() != m_isScanning) errors += "a mix of workspaces with and without detector scans; "; if (m_isScanning && ws->detectorInfo().size() != m_numberDetectors) errors += "workspaces with detectors scans have different number of " "detectors; "; if (ws->getInstrument()->getName() != m_instrumentName) errors += "different instrument names; "; if (ws->getNumberHistograms() == m_numberSpectra) { if (!m_hasDx.empty()) { for (unsigned int i = 0; i < m_numberSpectra; ++i) { if (m_hasDx[i] != ws->hasDx(i)) { errors += "spectra must have either Dx values or not; "; break; } } } } return errors; }
/** * Validates the user input in the UI * @return if the input was valid */ bool ContainerSubtraction::validate() { UserInputValidator uiv; // Check valid inputs const bool samValid = uiv.checkDataSelectorIsValid("Sample", m_uiForm.dsSample); const bool canValid = uiv.checkDataSelectorIsValid("Container", m_uiForm.dsContainer); if (samValid && canValid) { // Get Workspaces MatrixWorkspace_sptr sampleWs = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( m_uiForm.dsSample->getCurrentDataName().toStdString()); MatrixWorkspace_sptr containerWs = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( m_uiForm.dsContainer->getCurrentDataName().toStdString()); // Check Sample is of same type as container QString sample = m_uiForm.dsSample->getCurrentDataName(); QString sampleType = sample.right(sample.length() - sample.lastIndexOf("_")); QString container = m_uiForm.dsContainer->getCurrentDataName(); QString containerType = container.right(sample.length() - container.lastIndexOf("_")); g_log.debug() << "Sample type is: " << sampleType.toStdString() << std::endl; g_log.debug() << "Container type is: " << containerType.toStdString() << std::endl; if (containerType != sampleType) uiv.addErrorMessage( "Sample and can workspaces must contain the same type of data."); // Check sample has the same number of Histograms as the contianer const size_t sampleHist = sampleWs->getNumberHistograms(); const size_t containerHist = containerWs->getNumberHistograms(); if (sampleHist != containerHist) { uiv.addErrorMessage( " Sample and Container do not have a matching number of Histograms."); } } // Show errors if there are any if (!uiv.isAllInputValid()) emit showMessageBox(uiv.generateErrorMessage()); return uiv.isAllInputValid(); }
/** Rebins the distributions and sets error values. */ MatrixWorkspace_sptr VesuvioL1ThetaResolution::processDistribution(MatrixWorkspace_sptr ws, const double binWidth) { const size_t numHist = ws->getNumberHistograms(); double xMin(DBL_MAX); double xMax(DBL_MIN); for (size_t i = 0; i < numHist; i++) { auto &x = ws->x(i); xMin = std::min(xMin, x.front()); xMax = std::max(xMax, x.back()); } std::stringstream binParams; binParams << xMin << "," << binWidth << "," << xMax; IAlgorithm_sptr rebin = AlgorithmManager::Instance().create("Rebin"); rebin->initialize(); rebin->setChild(true); rebin->setLogging(false); rebin->setProperty("InputWorkspace", ws); rebin->setProperty("OutputWorkspace", "__rebin"); rebin->setProperty("Params", binParams.str()); rebin->execute(); ws = rebin->getProperty("OutputWorkspace"); for (size_t i = 0; i < numHist; i++) { auto &y = ws->y(i); auto &e = ws->mutableE(i); std::transform(y.begin(), y.end(), e.begin(), [](double x) { return sqrt(x); }); } return ws; }
/** Checks and retrieves the monitor spectrum out of the input workspace * @param inputWorkspace The input workspace. * @param wsID The workspace ID. * @returns A workspace containing the monitor spectrum only * @throw std::runtime_error If the properties are invalid */ API::MatrixWorkspace_sptr NormaliseToMonitor::getMonitorWorkspace(API::MatrixWorkspace_sptr inputWorkspace,int &wsID) { // Get the workspace from the ADS. Will throw if it's not there. MatrixWorkspace_sptr monitorWS = getProperty("MonitorWorkspace"); wsID = getProperty("MonitorWorkspaceIndex"); // Check that it's a single spectrum workspace if ( static_cast<int>(monitorWS->getNumberHistograms()) < wsID ) { throw std::runtime_error("The MonitorWorkspace must contain the MonitorWorkspaceIndex"); } // Check that the two workspace come from the same instrument if ( monitorWS->getInstrument()->getName() != inputWorkspace->getInstrument()->getName() ) { throw std::runtime_error("The Input and Monitor workspaces must come from the same instrument"); } // Check that they're in the same units if ( monitorWS->getAxis(0)->unit()->unitID() != inputWorkspace->getAxis(0)->unit()->unitID() ) { throw std::runtime_error("The Input and Monitor workspaces must have the same unit"); } // In this case we need to test whether the bins in the monitor workspace match m_commonBins = (m_commonBins && API::WorkspaceHelpers::matchingBins(inputWorkspace,monitorWS,true) ); // If the workspace passes all these tests, make a local copy because it will get changed return this->extractMonitorSpectrum(monitorWS,wsID); }
/** * Computes the square root of the errors and if the input was a distribution * this divides by the new bin-width * @param outputWS The workspace containing the output data * @param inputWS The input workspace used for testing distribution state */ void Rebin2D::normaliseOutput(MatrixWorkspace_sptr outputWS, MatrixWorkspace_const_sptr inputWS) { //PARALLEL_FOR1(outputWS) for(int64_t i = 0; i < static_cast<int64_t>(outputWS->getNumberHistograms()); ++i) { PARALLEL_START_INTERUPT_REGION MantidVec & outputY = outputWS->dataY(i); MantidVec & outputE = outputWS->dataE(i); for(size_t j = 0; j < outputWS->blocksize(); ++j) { m_progress->report("Calculating errors"); const double binWidth = (outputWS->readX(i)[j+1] - outputWS->readX(i)[j]); double eValue = std::sqrt(outputE[j]); // Don't do this for a RebinnedOutput workspace. The fractions // take care of such things. if( inputWS->isDistribution() && inputWS->id() != "RebinnedOutput") { outputY[j] /= binWidth; eValue /= binWidth; } outputE[j] = eValue; } PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION outputWS->isDistribution(inputWS->isDistribution()); }
/* * 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); }
/* * 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; const auto &spectrumInfo = rebinnedWS->spectrumInfo(); for (int i = 0; i < numberOfSpectra; i++) { progress(0.2 + 0.2 * i / numberOfSpectra, "Computing sensitivity"); // Skip if we have a monitor or if the detector is masked. if (spectrumInfo.isMonitor(i) || spectrumInfo.isMasked(i)) continue; // Retrieve the spectrum into a vector auto &YValues = rebinnedWS->y(i); auto &YErrors = rebinnedWS->e(i); sum += YValues[0]; error += YErrors[0] * YErrors[0]; nPixels++; } g_log.debug() << "sumUnmaskedDetectors: unmasked pixels = " << nPixels << " from a total of " << numberOfSpectra << "\n"; error = std::sqrt(error); }
/** * Search each spectrum for y-values that are less than zero and reset * them to the supplied value. * * @param minWS A workspace of minimum values for each spectra. * @param value Reset negative values in the spectra to this number. * @param wksp The workspace to modify. * @param prog The progress. */ void ResetNegatives::changeNegatives(MatrixWorkspace_const_sptr minWS, const double value, MatrixWorkspace_sptr wksp, Progress &prog) { int64_t nHist = wksp->getNumberHistograms(); PARALLEL_FOR2(minWS, wksp) for (int64_t i = 0; i < nHist; i++) { PARALLEL_START_INTERUPT_REGION if (minWS->readY(i)[0] <= 0.) // quick check to see if there is a reason to bother { MantidVec & y = wksp->dataY(i); for (MantidVec::iterator it = y.begin(); it != y.end(); ++it) { if (*it < 0.) { *it = value; } else *it = fixZero(*it); } } prog.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION }
/** * Redraws mini plots when user changes previw range or spectrum. * * @param prop QtProperty that was changed * @param value Value it was changed to */ void IndirectSymmetrise::replotNewSpectrum(QtProperty *prop, double value) { // Validate the preview spectra if (prop == m_properties["PreviewSpec"]) { // Get the range of possible spectra numbers QString workspaceName = m_uiForm.dsInput->getCurrentDataName(); MatrixWorkspace_sptr sampleWS = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( workspaceName.toStdString()); int minSpectrumRange = sampleWS->getSpectrum(0).getSpectrumNo(); int maxSpectrumRange = sampleWS->getSpectrum(sampleWS->getNumberHistograms() - 1) .getSpectrumNo(); // If entered value is lower then set spectra number to lowest valid value if (value < minSpectrumRange) { m_dblManager->setValue(m_properties["PreviewSpec"], minSpectrumRange); return; } // If entered value is higer then set spectra number to highest valid value if (value > maxSpectrumRange) { m_dblManager->setValue(m_properties["PreviewSpec"], maxSpectrumRange); return; } } // If we get this far then properties are valid so update mini plots if (prop == m_properties["PreviewSpec"]) updateMiniPlots(); }
/**Convert a binned workspace to point data * * @param workspace :: The input workspace * @return the converted workspace containing point data */ MatrixWorkspace_sptr SplineInterpolation::convertBinnedData(MatrixWorkspace_sptr workspace) const { if (workspace->isHistogramData()) { const size_t histNo = workspace->getNumberHistograms(); const size_t size = workspace->y(0).size(); // make a new workspace for the point data MatrixWorkspace_sptr pointWorkspace = WorkspaceFactory::Instance().create(workspace, histNo, size, size); // loop over each histogram for (size_t i = 0; i < histNo; ++i) { const auto &xValues = workspace->x(i); pointWorkspace->setSharedY(i, workspace->sharedY(i)); auto &newXValues = pointWorkspace->mutableX(i); // set x values to be average of bin bounds for (size_t j = 0; j < size; ++j) { newXValues[j] = (xValues[j] + xValues[j + 1]) / 2; } } return pointWorkspace; } return workspace; }
/** Reads from the third line of the input file to the end assuming it contains * 2D data * @param firstLine :: the second line in the file * @return a workspace containing the loaded data * @throw NotFoundError if there is compulsulary data is missing from the file * @throw invalid_argument if there is an inconsistency in the header * information */ const MatrixWorkspace_sptr LoadRKH::read2D(const std::string &firstLine) { g_log.information() << "file appears to contain 2D information, reading in 2D data mode\n"; MatrixWorkspace_sptr outWrksp; MantidVec axis0Data; Progress prog(read2DHeader(firstLine, outWrksp, axis0Data)); const size_t nAxis1Values = outWrksp->getNumberHistograms(); for (size_t i = 0; i < nAxis1Values; ++i) { // set the X-values to the common bin values we read above MantidVecPtr toPass; toPass.access() = axis0Data; outWrksp->setX(i, toPass); // now read in the Y values MantidVec &YOut = outWrksp->dataY(i); for (double &value : YOut) { m_fileIn >> value; } prog.report("Loading Y data"); } // loop on to the next spectrum // the error values form one big block after the Y-values for (size_t i = 0; i < nAxis1Values; ++i) { MantidVec &EOut = outWrksp->dataE(i); for (double &value : EOut) { m_fileIn >> value; } prog.report("Loading error estimates"); } // loop on to the next spectrum return outWrksp; }
/** * Plots the loaded file to the miniplot and sets the guides * and the range * * @param filename :: The name of the workspace to plot */ void ResNorm::handleVanadiumInputReady(const QString &filename) { // Plot the vanadium m_uiForm.ppPlot->addSpectrum("Vanadium", filename, m_previewSpec); QPair<double, double> res; QPair<double, double> range = m_uiForm.ppPlot->getCurveRange("Vanadium"); MatrixWorkspace_sptr vanWs = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( filename.toStdString()); m_uiForm.spPreviewSpectrum->setMaximum( static_cast<int>(vanWs->getNumberHistograms()) - 1); auto eRangeSelector = m_uiForm.ppPlot->getRangeSelector("ResNormERange"); // Use the values from the instrument parameter file if we can if (getResolutionRangeFromWs(filename, res)) { // ResNorm resolution should be +/- 10 * the IPF resolution res.first = res.first * 10; res.second = res.second * 10; setRangeSelector(eRangeSelector, m_properties["EMin"], m_properties["EMax"], res); } else { setRangeSelector(eRangeSelector, m_properties["EMin"], m_properties["EMax"], range); } setPlotPropertyRange(eRangeSelector, m_properties["EMin"], m_properties["EMax"], range); }
/** * Determine the min and max x-values for each spectrum and error check the pairs. * * @param inputWS The workspace to check the numbers for. * @param xmins The input/output that will hold the x-mins. * @param xmaxs The input/output that will hold the x-maxs. * * @return Any error messages generated during the execution. If empty everything * went according to plan. */ string determineXMinMax(MatrixWorkspace_sptr inputWS, vector<double>& xmins, vector<double>& xmaxs) { bool updateXMins = xmins.empty(); // they weren't set bool updateXMaxs = xmaxs.empty(); // they weren't set stringstream msg; size_t numSpectra = inputWS->getNumberHistograms(); for (size_t i=0; i < numSpectra; ++i) { // determine ranges if necessary if (updateXMins || updateXMaxs) { const MantidVec& xvalues = inputWS->getSpectrum(i)->dataX(); if (updateXMins) xmins.push_back(xvalues.front()); if (updateXMaxs) xmaxs.push_back(xvalues.back()); } // error check the ranges if (xmins[i] >= xmaxs[i]) { if (!msg.str().empty()) msg << ", "; msg << "at wksp_index=" << i << " XMin >= XMax (" << xmins[i] << " >= " << xmaxs[i] << ")"; } } return msg.str(); // empty string means nothing went wrong }
/** * Handles the JumpFit algorithm finishing, used to plot fit in miniplot. * * @param error True if the algorithm failed, false otherwise */ void JumpFit::fitAlgDone(bool error) { // Ignore errors if(error) return; std::string outWsName = fitAlg->getPropertyValue("Output") + "_Workspace"; MatrixWorkspace_sptr outputWorkspace = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(outWsName); TextAxis* axis = dynamic_cast<TextAxis*>(outputWorkspace->getAxis(1)); for(unsigned int histIndex = 0; histIndex < outputWorkspace->getNumberHistograms(); histIndex++) { QString specName = QString::fromStdString(axis->label(histIndex)); if(specName == "Calc") { plotMiniPlot(outputWorkspace, histIndex, "JumpFitPlot", specName); m_curves[specName]->setPen(QColor(Qt::red)); } if(specName == "Diff") { plotMiniPlot(outputWorkspace, histIndex, "JumpFitPlot", specName); m_curves[specName]->setPen(QColor(Qt::green)); } } replot("JumpFitPlot"); }
/** Executes the algorithm * @throw Exception::FileError If the calibration file cannot be opened and * read successfully * @throw Exception::InstrumentDefinitionError If unable to obtain the * source-sample distance */ void AlignDetectors::exec() { // Get the input workspace MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); this->getCalibrationWS(inputWS); // Initialise the progress reporting object m_numberOfSpectra = static_cast<int64_t>(inputWS->getNumberHistograms()); API::MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); // If input and output workspaces are not the same, create a new workspace for // the output if (outputWS != inputWS) { outputWS = inputWS->clone(); setProperty("OutputWorkspace", outputWS); } // Set the final unit that our output workspace will have setXAxisUnits(outputWS); ConversionFactors converter = ConversionFactors(m_calibrationWS); Progress progress(this, 0.0, 1.0, m_numberOfSpectra); auto eventW = boost::dynamic_pointer_cast<EventWorkspace>(outputWS); if (eventW) { align(converter, progress, *eventW); } else { align(converter, progress, *outputWS); } }
/** Initialise a workspace from its parent * This sets values such as title, instrument, units, sample, spectramap. * This does NOT copy any data. * * @param parent :: the parent workspace * @param child :: the child workspace * @param differentSize :: A flag to indicate if the two workspace will be different sizes */ void WorkspaceFactoryImpl::initializeFromParent(const MatrixWorkspace_const_sptr parent, const MatrixWorkspace_sptr child, const bool differentSize) const { child->setTitle(parent->getTitle()); child->setComment(parent->getComment()); child->setInstrument(parent->getInstrument()); // This call also copies the SHARED POINTER to the parameter map // This call will (should) perform a COPY of the parameter map. child->instrumentParameters(); child->m_sample = parent->m_sample; child->m_run = parent->m_run; child->setYUnit(parent->m_YUnit); child->setYUnitLabel(parent->m_YUnitLabel); child->isDistribution(parent->isDistribution()); // Only copy the axes over if new sizes are not given if ( !differentSize ) { // Only copy mask map if same size for now. Later will need to check continued validity. child->m_masks = parent->m_masks; } // Same number of histograms = copy over the spectra data if (parent->getNumberHistograms() == child->getNumberHistograms()) { for (size_t wi=0; wi<parent->getNumberHistograms(); wi++) { ISpectrum * childSpec = child->getSpectrum(wi); const ISpectrum * parentSpec = parent->getSpectrum(wi); // Copy spectrum number and detector IDs childSpec->copyInfoFrom(*parentSpec); } } // deal with axis for (size_t i = 0; i < parent->m_axes.size(); ++i) { const size_t newAxisLength = child->getAxis(i)->length(); const size_t oldAxisLength = parent->getAxis(i)->length(); if ( !differentSize || newAxisLength == oldAxisLength ) { // Need to delete the existing axis created in init above delete child->m_axes[i]; // Now set to a copy of the parent workspace's axis child->m_axes[i] = parent->m_axes[i]->clone(child.get()); } else { if (! parent->getAxis(i)->isSpectra()) // WHY??? { delete child->m_axes[i]; // Call the 'different length' clone variant child->m_axes[i] = parent->m_axes[i]->clone(newAxisLength,child.get()); } } } return; }
/** * Displays the sample data on the plot preview * @param dataName Name of new data source */ void ContainerSubtraction::newData(const QString &dataName) { const MatrixWorkspace_sptr sampleWs = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( dataName.toStdString()); m_uiForm.spPreviewSpec->setMaximum( static_cast<int>(sampleWs->getNumberHistograms()) - 1); // Plot the sample curve m_uiForm.ppPreview->clear(); m_uiForm.ppPreview->addSpectrum("Sample", sampleWs, 0, Qt::black); }
void FindCenterOfMassPosition2::exec() { MatrixWorkspace_sptr inputWSWvl = getProperty("InputWorkspace"); MatrixWorkspace_sptr inputWS; // Option to exclude beam area bool direct_beam = getProperty("DirectBeam"); //TODO: Need an input for the X bin to use, assume 0 for now int specID = 0; // Initial center location double center_x = getProperty("CenterX"); double center_y = getProperty("CenterY"); const double tolerance = getProperty("Tolerance"); // Iteration cutoff int max_iteration = 200; // Radius of the beam area, in pixels double beam_radius = getProperty("BeamRadius"); // Get the number of monitors. We assume that all monitors are stored in the first spectra const int numSpec = static_cast<int>(inputWSWvl->getNumberHistograms()); // Set up the progress reporting object Progress progress(this,0.0,1.0,max_iteration); EventWorkspace_const_sptr inputEventWS = boost::dynamic_pointer_cast<const EventWorkspace>(inputWSWvl); if(inputEventWS) { std::vector<double> y_values(numSpec); std::vector<double> e_values(numSpec); PARALLEL_FOR_NO_WSP_CHECK() for (int i = 0; i < numSpec; i++) { double sum_i(0), err_i(0); progress.report("Integrating events"); const EventList& el = inputEventWS->getEventList(i); el.integrate(0,0,true,sum_i,err_i); y_values[i] = sum_i; e_values[i] = err_i; } IAlgorithm_sptr algo = createChildAlgorithm("CreateWorkspace", 0.7, 1.0); algo->setProperty< std::vector<double> >("DataX", std::vector<double>(2,0.0) ); algo->setProperty< std::vector<double> >("DataY", y_values ); algo->setProperty< std::vector<double> >("DataE", e_values ); algo->setProperty<int>("NSpec", numSpec ); algo->execute(); inputWS = algo->getProperty("OutputWorkspace"); WorkspaceFactory::Instance().initializeFromParent(inputWSWvl, inputWS, false); } else {
/** * This performs a similar operation to divide, but is a separate algorithm so *that the correct spectra are used in the case of detector scans. This *currently does not support event workspaces properly, but should be made to in *the future. * * @param inputWorkspace The workspace with the spectra to divide by the monitor * @param outputWorkspace The resulting workspace */ void NormaliseToMonitor::performHistogramDivision( const MatrixWorkspace_sptr &inputWorkspace, MatrixWorkspace_sptr &outputWorkspace) { if (outputWorkspace != inputWorkspace) outputWorkspace = inputWorkspace->clone(); size_t monitorWorkspaceIndex = 0; Progress prog(this, 0.0, 1.0, m_workspaceIndexes.size()); const auto &specInfo = inputWorkspace->spectrumInfo(); for (const auto workspaceIndex : m_workspaceIndexes) { // Errors propagated according to // http://docs.mantidproject.org/nightly/concepts/ErrorPropagation.html#error-propagation // This is similar to that in MantidAlgorithms::Divide prog.report("Performing normalisation"); size_t timeIndex = 0; if (m_scanInput) timeIndex = specInfo.spectrumDefinition(workspaceIndex)[0].second; const auto newYFactor = 1.0 / m_monitor->histogram(monitorWorkspaceIndex).y()[0]; const auto divisorError = m_monitor->histogram(monitorWorkspaceIndex).e()[0]; const double yErrorFactor = pow(divisorError * newYFactor, 2); monitorWorkspaceIndex++; PARALLEL_FOR_IF(Kernel::threadSafe(*outputWorkspace)) for (int64_t i = 0; i < int64_t(outputWorkspace->getNumberHistograms()); ++i) { PARALLEL_START_INTERUPT_REGION const auto &specDef = specInfo.spectrumDefinition(i); if (!spectrumDefinitionsMatchTimeIndex(specDef, timeIndex)) continue; auto hist = outputWorkspace->histogram(i); auto &yValues = hist.mutableY(); auto &eValues = hist.mutableE(); for (size_t j = 0; j < yValues.size(); ++j) { eValues[j] = newYFactor * sqrt(eValues[j] * eValues[j] + yValues[j] * yValues[j] * yErrorFactor); yValues[j] *= newYFactor; } outputWorkspace->setHistogram(i, hist); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION } }
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->setX(i, base->refX(i)); } auto zeroed = this->multiply(wsTemplate, 0); auto filled = this->add(zeroed, value); return filled; }
/** Convert a workspace to Q * * @param inputWS : The input workspace (in wavelength) to convert to Q * @return : output workspace in Q */ MatrixWorkspace_sptr ReflectometryReductionOne2::convertToQ(MatrixWorkspace_sptr inputWS) { bool const moreThanOneDetector = inputWS->getDetector(0)->nDets() > 1; bool const shouldCorrectAngle = !(*getProperty("ThetaIn")).isDefault() && !summingInQ(); if (shouldCorrectAngle && moreThanOneDetector) { if (inputWS->getNumberHistograms() > 1) { throw std::invalid_argument( "Expected a single group in " "ProcessingInstructions to be able to " "perform angle correction, found " + std::to_string(inputWS->getNumberHistograms())); } MatrixWorkspace_sptr IvsQ = inputWS->clone(); auto &XOut0 = IvsQ->mutableX(0); const auto &XIn0 = inputWS->x(0); double const theta = getProperty("ThetaIn"); double const factor = 4.0 * M_PI * sin(theta * M_PI / 180.0); std::transform(XIn0.rbegin(), XIn0.rend(), XOut0.begin(), [factor](double x) { return factor / x; }); auto &Y0 = IvsQ->mutableY(0); auto &E0 = IvsQ->mutableE(0); std::reverse(Y0.begin(), Y0.end()); std::reverse(E0.begin(), E0.end()); IvsQ->getAxis(0)->unit() = UnitFactory::Instance().create("MomentumTransfer"); return IvsQ; } else { auto convertUnits = this->createChildAlgorithm("ConvertUnits"); convertUnits->initialize(); convertUnits->setProperty("InputWorkspace", inputWS); convertUnits->setProperty("Target", "MomentumTransfer"); convertUnits->setProperty("AlignBins", false); convertUnits->execute(); MatrixWorkspace_sptr IvsQ = convertUnits->getProperty("OutputWorkspace"); return IvsQ; } }
/** Execute the algorithm. */ void WeightedMeanOfWorkspace::exec() { MatrixWorkspace_sptr inputWS = this->getProperty("InputWorkspace"); // Check if it is an event workspace EventWorkspace_const_sptr eventW = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS); if (eventW != NULL) { throw std::runtime_error("WeightedMeanOfWorkspace cannot handle EventWorkspaces!"); } // Create the output workspace MatrixWorkspace_sptr singleValued = WorkspaceFactory::Instance().create("WorkspaceSingleValue", 1, 1, 1); // Calculate weighted mean std::size_t numHists = inputWS->getNumberHistograms(); double averageValue = 0.0; double weightSum = 0.0; for (std::size_t i = 0; i < numHists; ++i) { try { IDetector_const_sptr det = inputWS->getDetector(i); if( det->isMonitor() || det->isMasked() ) { continue; } } catch (...) { // Swallow these if no instrument is found ; } MantidVec y = inputWS->dataY(i); MantidVec e = inputWS->dataE(i); double weight = 0.0; for (std::size_t j = 0; j < y.size(); ++j) { if (!boost::math::isnan(y[j]) && !boost::math::isinf(y[j]) && !boost::math::isnan(e[j]) && !boost::math::isinf(e[j])) { weight = 1.0 / (e[j] * e[j]); averageValue += (y[j] * weight); weightSum += weight; } } } singleValued->dataX(0)[0] = 0.0; singleValued->dataY(0)[0] = averageValue / weightSum; singleValued->dataE(0)[0] = std::sqrt(weightSum); this->setProperty("OutputWorkspace", singleValued); }
/** Validate the input properties. */ std::map<std::string, std::string> MaxEnt::validateInputs() { std::map<std::string, std::string> result; MatrixWorkspace_sptr inWS = getProperty("InputWorkspace"); if (inWS) { // 1. X values in input workspace must be (almost) equally spaced const double warningLevel = 0.01; const double errorLevel = 0.5; bool printWarning = false; // Average spacing const MantidVec &X = inWS->readX(0); const double dx = (X[X.size() - 1] - X[0]) / static_cast<double>(X.size() - 1); for (size_t i = 1; i < X.size() - 1; i++) { // 1% accuracy exceeded, but data still usable if (std::abs(X[i] - X[0] - static_cast<double>(i) * dx) / dx > warningLevel) { printWarning = true; if (std::abs(X[i] - X[0] - static_cast<double>(i) * dx) / dx > errorLevel) { // 50% accuracy exceeded, data not usable printWarning = false; result["InputWorkspace"] = "X axis must be linear (all bins have same width)"; break; } } } if (printWarning) { g_log.warning() << "Bin widths differ by more than " << warningLevel * 100 << "% of average\n"; } // 2. If the input signal is complex, we expect an even number of histograms // in the input workspace size_t nhistograms = inWS->getNumberHistograms(); bool complex = getProperty("ComplexData"); if (complex && (nhistograms % 2)) result["InputWorkspace"] = "The number of histograms in the input " "workspace must be even for complex data"; } return result; }
/** Sets the properties of the reference (usually first) workspace, * to later check the compatibility of the others with the reference * @param ref : the reference workspace */ void RunCombinationHelper::setReferenceProperties(MatrixWorkspace_sptr ref) { m_numberSpectra = ref->getNumberHistograms(); m_numberDetectors = ref->detectorInfo().size(); m_xUnit = ref->getAxis(0)->unit()->unitID(); m_spectrumAxisUnit = ref->getAxis(1)->unit()->unitID(); m_yUnit = ref->YUnit(); m_isHistogramData = ref->isHistogramData(); m_isScanning = ref->detectorInfo().isScanning(); m_instrumentName = ref->getInstrument()->getName(); if (m_numberSpectra) { m_hasDx.reserve(m_numberSpectra); for (unsigned int i = 0; i < m_numberSpectra; ++i) m_hasDx.push_back(ref->hasDx(i)); } }
void IQTransform::exec() { MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); // Print a warning if the input workspace has more than one spectrum if ( inputWS->getNumberHistograms() > 1 ) { g_log.warning("This algorithm is intended for use on single-spectrum workspaces.\n" "Only the first spectrum will be transformed."); } // Do background subtraction from a workspace first because it doesn't like // potential conversion to point data that follows. Requires a temporary workspace. MatrixWorkspace_sptr tmpWS; MatrixWorkspace_sptr backgroundWS = getProperty("BackgroundWorkspace"); if ( backgroundWS ) tmpWS = subtractBackgroundWS(inputWS,backgroundWS); else tmpWS = inputWS; // Create the output workspace const size_t length = tmpWS->blocksize(); MatrixWorkspace_sptr outputWS = WorkspaceFactory::Instance().create(inputWS,1,length,length); m_label->setLabel(""); outputWS->setYUnit(""); // Copy the data over. Assume single spectrum input (output will be). // Take the mid-point of histogram bins if ( tmpWS->isHistogramData() ) { VectorHelper::convertToBinCentre(tmpWS->readX(0),outputWS->dataX(0)); } else { outputWS->setX(0,tmpWS->refX(0)); } MantidVec& Y = outputWS->dataY(0) = tmpWS->dataY(0); outputWS->dataE(0) = tmpWS->dataE(0); // Subtract a constant background if requested const double background = getProperty("BackgroundValue"); if ( background > 0.0 ) subtractBackgroundValue(Y,background); // Select the desired transformation function and call it TransformFunc f = m_transforms.find(getProperty("TransformType"))->second; (this->*f)(outputWS); // Need the generic label unit on this (unless the unit on the X axis hasn't changed) if ( ! m_label->caption().empty() ) outputWS->getAxis(0)->unit() = m_label; setProperty("OutputWorkspace",outputWS); }
void EQSANSSensitivityCorrection::exec() { MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); MatrixWorkspace_sptr effWS = getProperty("EfficiencyWorkspace"); const double factor = getProperty("Factor"); const double error = getProperty("Error"); Progress progress(this,0.0,1.0,5); // Now create a workspace to put in the wavelength-dependence MatrixWorkspace_sptr lambdaWS = WorkspaceFactory::Instance().create(inputWS); // Number of X bins const int xLength = static_cast<int>(inputWS->readY(0).size()); // Number of detector pixels const int numHists = static_cast<int>(inputWS->getNumberHistograms()); const MantidVec& XIn = inputWS->dataX(0); MantidVec& YOut = lambdaWS->dataY(0); MantidVec& EOut = lambdaWS->dataE(0); progress.report("Computing detector efficiency"); for (int i = 0; i < xLength; i++) { double wl = (XIn[i]+XIn[i+1])/2.0; YOut[i] = 1.0-std::exp(-factor*wl); EOut[i] = std::fabs(factor)*std::exp(-factor*wl)*error; } progress.report("Computing detector efficiency"); for (int i = 0; i < numHists; i++) { MantidVec& YOut_i = lambdaWS->dataY(i); MantidVec& EOut_i = lambdaWS->dataE(i); MantidVec& XOut_i = lambdaWS->dataX(i); YOut_i = YOut; EOut_i = EOut; XOut_i = XIn; } lambdaWS = lambdaWS * effWS; MatrixWorkspace_sptr outputWS = inputWS / lambdaWS; setProperty("OutputWorkspace", outputWS); setProperty("OutputEfficiencyWorkspace", lambdaWS); setProperty("OutputMessage", "Applied wavelength-dependent sensitivity correction"); }
/** * Extracts time bin width from workspace parameter * * The method uses the difference between first and second x-value of the * first spectrum as time bin width. If the workspace does not contain proper * data (0 spectra or less than 2 x-values), the method throws an * std::invalid_argument-exception Otherwise it calls setDeltaT. * * @param matrixWorkspace :: MatrixWorkspace with at least one spectrum with *at * least two x-values. */ void PoldiFitPeaks2D::setDeltaTFromWorkspace( const MatrixWorkspace_sptr &matrixWorkspace) { if (matrixWorkspace->getNumberHistograms() < 1) { throw std::invalid_argument("MatrixWorkspace does not contain any data."); } auto &xData = matrixWorkspace->x(0); if (xData.size() < 2) { throw std::invalid_argument( "Cannot process MatrixWorkspace with less than 2 x-values."); } // difference between first and second x-value is assumed to be the bin // width. setDeltaT(matrixWorkspace->x(0)[1] - matrixWorkspace->x(0)[0]); }
MatrixWorkspace_sptr CreateFloodWorkspace::scaleToCentralPixel(MatrixWorkspace_sptr ws) { int const centralSpectrum = getProperty(Prop::CENTRAL_PIXEL); auto const nHisto = static_cast<int>(ws->getNumberHistograms()); if (centralSpectrum >= nHisto) { throw std::invalid_argument( "Spectrum index " + std::to_string(centralSpectrum) + " passed to property " + Prop::CENTRAL_PIXEL + " is outside the range 0-" + std::to_string(nHisto - 1)); } auto const spectraMap = ws->getSpectrumToWorkspaceIndexMap(); auto const centralIndex = spectraMap.at(centralSpectrum); auto const scaleFactor = ws->y(centralIndex).front(); g_log.information() << "Scale to central pixel, factor = " << scaleFactor << '\n'; if (scaleFactor <= 0.0) { throw std::runtime_error("Scale factor muhst be > 0, found " + std::to_string(scaleFactor)); } auto const axis = ws->getAxis(1); auto const sa = dynamic_cast<const SpectraAxis *>(axis); double const startX = isDefault(Prop::START_X) ? sa->getMin() : getProperty(Prop::START_X); double const endX = isDefault(Prop::END_X) ? sa->getMax() : getProperty(Prop::END_X); PARALLEL_FOR_IF(Kernel::threadSafe(*ws)) for (int i = 0; i < nHisto; ++i) { PARALLEL_START_INTERUPT_REGION auto const spec = ws->getSpectrum(i).getSpectrumNo(); if (isExcludedSpectrum(spec)) { ws->mutableY(i)[0] = VERY_BIG_VALUE; ws->mutableE(i)[0] = 0.0; } else if (spec >= startX && spec <= endX) { ws->mutableY(i)[0] /= scaleFactor; ws->mutableE(i)[0] /= scaleFactor; } else { ws->mutableY(i)[0] = 1.0; ws->mutableE(i)[0] = 0.0; } PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION return ws; }
/** * Main work portion of algorithm. Calculates mean of standard deviation, * ignoring * the detectors marked as "bad", then determines if any of the detectors are * "bad". * @param progress :: progress indicator * @param valid :: eventual output workspace, holding 0 for bad and 1 for good * @param values :: stddeviations of each spectra (I think) */ void IdentifyNoisyDetectors::getStdDev(API::Progress &progress, MatrixWorkspace_sptr valid, MatrixWorkspace_sptr values) { const int nhist = static_cast<int>(valid->getNumberHistograms()); int count = 0; double mean = 0.0; double mean2 = 0.0; for (int i = 0; i < nhist; i++) { if (valid->readY(i)[0] > 0) { mean += values->readY(i)[0]; mean2 += std::pow(values->readY(i)[0], 2); count++; } progress.report(); } if (0 == count) { // all values are zero, no need to loop return; } mean = mean / count; double stddev = sqrt((mean2 / count) - std::pow(mean, 2)); double upper = mean + 3 * stddev; double lower = mean - 3 * stddev; double min = mean * 0.0001; for (int i = 0; i < nhist; i++) { double value = values->readY(i)[0]; if (value > upper) { valid->dataY(i)[0] = 0.0; } else if (value < lower) { valid->dataY(i)[0] = 0.0; } else if (value < min) { valid->dataY(i)[0] = 0.0; } progress.report("Calculating StdDev..."); } }