/** 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; }
/** Creates the output workspace, setting the X vector to the bins boundaries in * Qx. * @return A pointer to the newly-created workspace */ API::MatrixWorkspace_sptr Qxy::setUpOutputWorkspace(API::MatrixWorkspace_const_sptr inputWorkspace) { const double max = getProperty("MaxQxy"); const double delta = getProperty("DeltaQ"); int bins = static_cast<int>(max / delta); if (bins * delta != max) ++bins; // Stop at first boundary past MaxQxy if max is not a multiple of // delta const double startVal = -1.0 * delta * bins; bins *= 2; // go from -max to +max bins += 1; // Add 1 - this is a histogram // Create an output workspace with the same meta-data as the input MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create( inputWorkspace, bins - 1, bins, bins - 1); // ... but clear the masking from the parameter map as we don't want to carry // that over since this is essentially // a 2D rebin ParameterMap &pmap = outputWorkspace->instrumentParameters(); pmap.clearParametersByName("masked"); // Create a numeric axis to replace the vertical one Axis *verticalAxis = new BinEdgeAxis(bins); outputWorkspace->replaceAxis(1, verticalAxis); // Build up the X values Kernel::cow_ptr<MantidVec> axis; MantidVec &horizontalAxisRef = axis.access(); horizontalAxisRef.resize(bins); for (int i = 0; i < bins; ++i) { const double currentVal = startVal + i * delta; // Set the X value horizontalAxisRef[i] = currentVal; // Set the Y value on the axis verticalAxis->setValue(i, currentVal); } // Fill the X vectors in the output workspace for (int i = 0; i < bins - 1; ++i) { outputWorkspace->setX(i, axis); for (int j = 0; j < bins - j; ++j) { outputWorkspace->dataY(i)[j] = std::numeric_limits<double>::quiet_NaN(); outputWorkspace->dataE(i)[j] = std::numeric_limits<double>::quiet_NaN(); } } // Set the axis units outputWorkspace->getAxis(1)->unit() = outputWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create("MomentumTransfer"); // Set the 'Y' unit (gets confusing here...this is probably a Z axis in this // case) outputWorkspace->setYUnitLabel("Cross Section (1/cm)"); setProperty("OutputWorkspace", outputWorkspace); return outputWorkspace; }
/** 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)); } }
/** Checks that the units of the workspace data are declared match any * required units * * @param value :: The workspace to test * @return A user level description of the error or "" for no error */ std::string WorkspaceUnitValidator::checkValidity(const MatrixWorkspace_sptr &value) const { // This effectively checks for single-valued workspaces if (value->axes() == 0) return "A single valued workspace has no unit, which is required for " "this algorithm"; Kernel::Unit_const_sptr unit = value->getAxis(0)->unit(); // If m_unitID is empty it means that the workspace must have units, which // can be anything if (m_unitID.empty()) { return ( unit && (!boost::dynamic_pointer_cast<const Kernel::Units::Empty>(unit)) ? "" : "The workspace must have units"); } // now check if the units of the workspace is correct else { if ((!unit) || (unit->unitID().compare(m_unitID))) { return "The workspace must have units of " + m_unitID; //+ "; its unit is: " + unit->caption(); } else return ""; } }
/** 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); }
/** * 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"); }
/** Create an output workspace of the appropriate (histogram or event) type and * copy over the data * @param inputWS The input workspace */ API::MatrixWorkspace_sptr ConvertUnitsUsingDetectorTable::setupOutputWorkspace( const API::MatrixWorkspace_const_sptr inputWS) { MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); // If input and output workspaces are NOT the same, create a new workspace for // the output if (outputWS != inputWS) { if (m_inputEvents) { // Need to create by name as WorkspaceFactory otherwise spits out // Workspace2D when EventWS passed in outputWS = WorkspaceFactory::Instance().create( "EventWorkspace", inputWS->getNumberHistograms(), 2, 1); // Copy geometry etc. over WorkspaceFactory::Instance().initializeFromParent(inputWS, outputWS, false); // Need to copy over the data as well EventWorkspace_const_sptr inputEventWS = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS); boost::dynamic_pointer_cast<EventWorkspace>(outputWS) ->copyDataFrom(*inputEventWS); } else { // Create the output workspace outputWS = WorkspaceFactory::Instance().create(inputWS); // Copy the data over this->fillOutputHist(inputWS, outputWS); } } // Set the final unit that our output workspace will have outputWS->getAxis(0)->unit() = m_outputUnit; return outputWS; }
/** * Creates the output workspace for this algorithm * @param inputWorkspace A parent workspace to initialize from. * @return A pointer to the output workspace. */ API::MatrixWorkspace_sptr Transpose::createOutputWorkspace( API::MatrixWorkspace_const_sptr inputWorkspace) { Mantid::API::Axis *yAxis = getVerticalAxis(inputWorkspace); const size_t oldNhist = inputWorkspace->getNumberHistograms(); const auto &inX = inputWorkspace->x(0); const size_t oldYlength = inputWorkspace->blocksize(); const size_t oldVerticalAxislength = yAxis->length(); // The input Y axis may be binned so the new X data should be too size_t newNhist(oldYlength), newXsize(oldVerticalAxislength), newYsize(oldNhist); MatrixWorkspace_sptr outputWorkspace = inputWorkspace->cloneEmpty(); outputWorkspace->initialize(newNhist, newXsize, newYsize); outputWorkspace->setTitle(inputWorkspace->getTitle()); outputWorkspace->setComment(inputWorkspace->getComment()); outputWorkspace->copyExperimentInfoFrom(inputWorkspace.get()); outputWorkspace->setYUnit(inputWorkspace->YUnit()); outputWorkspace->setYUnitLabel(inputWorkspace->YUnitLabel()); outputWorkspace->setDistribution(inputWorkspace->isDistribution()); // Create a new numeric axis for Y the same length as the old X array // Values come from input X API::NumericAxis *newYAxis(nullptr); if (inputWorkspace->isHistogramData()) { newYAxis = new API::BinEdgeAxis(inX.rawData()); } else { newYAxis = new API::NumericAxis(inX.rawData()); } newYAxis->unit() = inputWorkspace->getAxis(0)->unit(); outputWorkspace->getAxis(0)->unit() = inputWorkspace->getAxis(1)->unit(); outputWorkspace->replaceAxis(1, newYAxis); setProperty("OutputWorkspace", outputWorkspace); return outputWorkspace; }
/** * Creates the output workspace for this algorithm * @param inputWorkspace A parent workspace to initialize from. * @return A pointer to the output workspace. */ API::MatrixWorkspace_sptr Transpose::createOutputWorkspace( API::MatrixWorkspace_const_sptr inputWorkspace) { Mantid::API::Axis *yAxis = getVerticalAxis(inputWorkspace); const size_t oldNhist = inputWorkspace->getNumberHistograms(); const MantidVec &inX = inputWorkspace->readX(0); const size_t oldYlength = inputWorkspace->blocksize(); const size_t oldVerticalAxislength = yAxis->length(); // The input Y axis may be binned so the new X data should be too size_t newNhist(oldYlength), newXsize(oldVerticalAxislength), newYsize(oldNhist); MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create( inputWorkspace, newNhist, newXsize, newYsize); // Create a new numeric axis for Y the same length as the old X array // Values come from input X API::NumericAxis *newYAxis(nullptr); if (inputWorkspace->isHistogramData()) { newYAxis = new API::BinEdgeAxis(inX); } else { newYAxis = new API::NumericAxis(inX); } newYAxis->unit() = inputWorkspace->getAxis(0)->unit(); outputWorkspace->getAxis(0)->unit() = inputWorkspace->getAxis(1)->unit(); outputWorkspace->replaceAxis(1, newYAxis); setProperty("OutputWorkspace", outputWorkspace); return outputWorkspace; }
/** Creates the output workspace, setting the axes according to the input * binning parameters * @param[in] inputWorkspace The input workspace * @param[in] binParams The bin parameters from the user * @param[out] newAxis The 'vertical' axis defined by the given * parameters * @return A pointer to the newly-created workspace */ API::MatrixWorkspace_sptr SofQWCentre::setUpOutputWorkspace( API::MatrixWorkspace_const_sptr inputWorkspace, const std::vector<double> &binParams, std::vector<double> &newAxis) { // Create vector to hold the new X axis values HistogramData::BinEdges xAxis(inputWorkspace->sharedX(0)); const int xLength = static_cast<int>(xAxis.size()); // Create a vector to temporarily hold the vertical ('y') axis and populate // that const int yLength = static_cast<int>( VectorHelper::createAxisFromRebinParams(binParams, newAxis)); // Create the output workspace MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create( inputWorkspace, yLength - 1, xLength, xLength - 1); // Create a numeric axis to replace the default vertical one Axis *const verticalAxis = new BinEdgeAxis(newAxis); outputWorkspace->replaceAxis(1, verticalAxis); // Now set the axis values for (int i = 0; i < yLength - 1; ++i) { outputWorkspace->setBinEdges(i, xAxis); } // Set the axis units verticalAxis->unit() = UnitFactory::Instance().create("MomentumTransfer"); verticalAxis->title() = "|Q|"; // Set the X axis title (for conversion to MD) outputWorkspace->getAxis(0)->title() = "Energy transfer"; outputWorkspace->setYUnit(""); outputWorkspace->setYUnitLabel("Intensity"); return outputWorkspace; }
/** 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; }
/** Checks that the axis stated * @param value :: The workspace to test * @return A message for users with negative results, otherwise "" */ std::string SpectraAxisValidator::checkValidity(const MatrixWorkspace_sptr &value) const { Mantid::API::Axis *axis = value->getAxis(m_axisNumber); if (axis->isSpectra()) return ""; else return "A workspace with axis being Spectra Number is required here."; }
void SumRowColumn::exec() { // First task is to integrate the input workspace MatrixWorkspace_const_sptr integratedWS = integrateWorkspace(); const size_t numSpec = integratedWS->getNumberHistograms(); // Check number of spectra is 128*128 or 192*192. Print warning if not. if (numSpec != 16384 && numSpec != 36864) { g_log.warning() << "The input workspace has " << numSpec << " spectra." << "This is not 128*128 or 192*192 - did you make a mistake?\n"; } // This is the dimension if all rows/columns are included const int dim = static_cast<int>( std::sqrt(static_cast<double>(numSpec)) ); // Check the column range properties int start = getProperty("HOverVMin"); int end = getProperty("HOverVMax"); if ( isEmpty(start) ) start = 0; if ( isEmpty(end) || end > dim-1 ) end = dim-1; if ( start > end ) { g_log.error("H/V_Min must be less than H/V_Max"); throw std::out_of_range("H/V_Min must be less than H/V_Max"); } MatrixWorkspace_sptr outputWS = WorkspaceFactory::Instance().create(integratedWS,1,dim,dim); // Remove the unit outputWS->getAxis(0)->unit().reset(); // Get references to the vectors for the results MantidVec& X = outputWS->dataX(0); MantidVec& Y = outputWS->dataY(0); // Get the orientation const std::string orientation = getProperty("Orientation"); const bool horizontal = ( orientation=="D_H" ? 1 : 0 ); Progress progress(this,0,1,dim); for (int i = 0; i < dim; ++i) { // Copy X values X[i] = i; // Now loop over calculating Y's for (int j = start; j <= end; ++j) { const int index = ( horizontal ? ( i + j*dim) : ( i*dim + j) ); Y[i] += integratedWS->readY(index)[0]; } } setProperty("OutputWorkspace",outputWS); }
/** * Retrieves the axis labels from the axis with the specified index, in the * specified workspace. * * @param workspace The workspace whose axis labels to retrieve. * @param axisIndex The index of the axis whose labels retrieve. * @return The retrieved axis labels. */ std::vector<std::string> ExtractQENSMembers::getAxisLabels(MatrixWorkspace_sptr workspace, size_t axisIndex) const { auto axis = workspace->getAxis(axisIndex); std::vector<std::string> labels; labels.reserve(axis->length()); for (auto i = 0u; i < axis->length(); ++i) labels.emplace_back(axis->label(i)); return labels; }
/** Checks that the input workspace all exist, that they are the same size, have * the same units * and the same instrument name. Will throw if they don't. * @param inputWorkspaces The names of the input workspaces * @return A list of pointers to the input workspace, ordered by increasing * frame starting point * @throw Exception::NotFoundError If an input workspace doesn't exist * @throw std::invalid_argument If the input workspaces are not compatible */ std::list<API::MatrixWorkspace_sptr> MergeRuns::validateInputs(const std::vector<std::string> &inputWorkspaces) { std::list<MatrixWorkspace_sptr> inWS; std::string xUnitID; std::string YUnit; bool dist(false); // Going to check that name of instrument matches - think that's the best // possible at the moment // because if instrument is created from raw file it'll be a different // object std::string instrument; for (size_t i = 0; i < inputWorkspaces.size(); ++i) { MatrixWorkspace_sptr ws; // Fetch the next input workspace - throw an error if it's not there try { ws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( inputWorkspaces[i]); if (!ws) { g_log.error() << "Input workspace " << inputWorkspaces[i] << " not found.\n"; throw Kernel::Exception::NotFoundError("Data Object", inputWorkspaces[i]); } inWS.push_back(ws); } catch (Exception::NotFoundError &) { g_log.error() << "Input workspace " << inputWorkspaces[i] << " not found.\n"; throw; } // Check that it has common binning if (!WorkspaceHelpers::commonBoundaries(inWS.back())) { g_log.error("Input workspaces must have common binning for all spectra"); throw std::invalid_argument( "Input workspaces must have common binning for all spectra"); } // Check a few things are the same for all input workspaces if (i == 0) { xUnitID = ws->getAxis(0)->unit()->unitID(); YUnit = ws->YUnit(); dist = ws->isDistribution(); instrument = ws->getInstrument()->getName(); } else { testCompatibility(ws, xUnitID, YUnit, dist, instrument); } } // Order the workspaces by ascending frame (X) starting point inWS.sort(compare); return inWS; }
void SumEventsByLogValue::createBinnedOutput( const Kernel::TimeSeriesProperty<T> *log) { // If only the number of bins was given, add the min & max values of the log if (m_binningParams.size() == 1) { m_binningParams.insert(m_binningParams.begin(), log->minValue()); m_binningParams.push_back( log->maxValue() * 1.000001); // Make it a tiny bit larger to cover full range } // XValues will be resized in createAxisFromRebinParams() std::vector<double> XValues; const int XLength = VectorHelper::createAxisFromRebinParams(m_binningParams, XValues); assert((int)XValues.size() == XLength); // Create the output workspace - the factory will give back a Workspace2D MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create( "Workspace2D", 1, XLength, XLength - 1); // Copy the bin boundaries into the output workspace outputWorkspace->mutableX(0) = XValues; outputWorkspace->getAxis(0)->title() = m_logName; outputWorkspace->setYUnit("Counts"); auto &Y = outputWorkspace->mutableY(0); const int numSpec = static_cast<int>(m_inputWorkspace->getNumberHistograms()); Progress prog(this, 0.0, 1.0, numSpec); PARALLEL_FOR_IF(Kernel::threadSafe(*m_inputWorkspace)) for (int spec = 0; spec < numSpec; ++spec) { PARALLEL_START_INTERUPT_REGION const IEventList &eventList = m_inputWorkspace->getSpectrum(spec); const auto pulseTimes = eventList.getPulseTimes(); for (auto pulseTime : pulseTimes) { // Find the value of the log at the time of this event const double logValue = log->getSingleValue(pulseTime); if (logValue >= XValues.front() && logValue < XValues.back()) { PARALLEL_ATOMIC ++Y[VectorHelper::getBinIndex(XValues, logValue)]; } } prog.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION // The errors are the sqrt of the counts so long as we don't deal with // weighted events. std::transform(Y.cbegin(), Y.cend(), outputWorkspace->mutableE(0).begin(), (double (*)(double))std::sqrt); setProperty("OutputWorkspace", outputWorkspace); }
/** * Checks that X axis is in the right direction. * * @param value The workspace to check * @return "" if is valid, otherwise a user level description of a problem */ std::string IncreasingAxisValidator::checkValidity( const MatrixWorkspace_sptr &value) const { // 0 for X axis Axis *xAxis = value->getAxis(0); // Left-most axis value should be less than the right-most, if ws has // more than one X axis value if (xAxis->length() > 1 && xAxis->getValue(0) >= xAxis->getValue(xAxis->length() - 1)) return "X axis of the workspace should be increasing from left to " "right"; else return ""; }
/** Checks that the axis stated * @param value :: The workspace to test * @return A message for users with negative results, otherwise "" */ std::string SpectraAxisValidator::checkValidity(const MatrixWorkspace_sptr &value) const { Mantid::API::Axis *axis; try { axis = value->getAxis(m_axisNumber); } catch (Kernel::Exception::IndexError &) { return "No axis at index " + std::to_string(m_axisNumber) + " available in the workspace"; } if (axis->isSpectra()) return ""; else return "A workspace with axis being Spectra Number is required here."; }
/** Checks and retrieves the requested spectrum out of the input workspace * * @param inputWorkspace The input workspace * @returns The unchanged input workspace (so that signature is the same as *getMonitorWorkspace) * @throw std::runtime_error If the properties are invalid */ MatrixWorkspace_sptr NormaliseToMonitor::getInWSMonitorSpectrum( const MatrixWorkspace_sptr &inputWorkspace) { // this is the index of the spectra within the workspace and we need to // identify it either from DetID or from SpecID // size_t spectra_num(-1); // try monitor spectrum. If it is specified, it overrides everything int monitorSpec = getProperty("MonitorSpectrum"); if (monitorSpec < 0) { // Get hold of the monitor spectrum through detector ID int monitorID = getProperty("MonitorID"); if (monitorID < 0) { throw std::runtime_error( "Both MonitorSpectrum and MonitorID can not be negative"); } // set spectra of detector's ID of one selected monitor ID std::vector<detid_t> detID(1, monitorID); // got the index of correspondent spectra (should be only one). auto indexList = inputWorkspace->getIndicesFromDetectorIDs(detID); if (indexList.empty()) { throw std::runtime_error( "Can not find spectra, corresponding to the requested monitor ID"); } if (indexList.size() > 1 && !m_scanInput) { throw std::runtime_error("More then one spectrum corresponds to the " "requested monitor ID. This is unexpected in a " "non-scanning workspace."); } m_workspaceIndexes = indexList; } else { // monitor spectrum is specified. if (m_scanInput) throw std::runtime_error("For a scanning input workspace the monitor ID " "must be provided. Normalisation can not be " "performed to a spectrum."); const SpectraAxis *axis = dynamic_cast<const SpectraAxis *>(inputWorkspace->getAxis(1)); if (!axis) { throw std::runtime_error("Cannot retrieve monitor spectrum - spectrum " "numbers not attached to workspace"); } auto specs = axis->getSpectraIndexMap(); if (!specs.count(monitorSpec)) { throw std::runtime_error("Input workspace does not contain spectrum " "number given for MonitorSpectrum"); } m_workspaceIndexes = std::vector<size_t>(1, specs[monitorSpec]); } return inputWorkspace; }
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); }
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; }
/** Extract a spectrum from the Efficiencies workspace as a 1D workspace. * @param label :: A label of the spectrum to extract. * @return :: A workspace with a single spectrum. */ boost::shared_ptr<Mantid::API::MatrixWorkspace> PolarizationCorrectionFredrikze::getEfficiencyWorkspace( const std::string &label) { MatrixWorkspace_sptr efficiencies = getProperty(efficienciesLabel); auto const &axis = dynamic_cast<TextAxis &>(*efficiencies->getAxis(1)); size_t index = axis.length(); for (size_t i = 0; i < axis.length(); ++i) { if (axis.label(i) == label) { index = i; break; } } if (index == axis.length()) { // Check if we need to fetch polarization parameters from the instrument's // parameters static std::map<std::string, std::string> loadableProperties{ {crhoLabel, "crho"}, {cppLabel, "cPp"}, {cApLabel, "cAp"}, {cAlphaLabel, "calpha"}}; WorkspaceGroup_sptr inWS = getProperty("InputWorkspace"); Instrument_const_sptr instrument = fetchInstrument(inWS.get()); auto vals = instrument->getStringParameter(loadableProperties[label]); if (vals.empty()) { throw std::invalid_argument("Efficiencey property not found: " + label); } auto extract = createChildAlgorithm("CreatePolarizationEfficiencies"); extract->initialize(); extract->setProperty("InputWorkspace", efficiencies); extract->setProperty(label, vals.front()); extract->execute(); MatrixWorkspace_sptr outWS = extract->getProperty("OutputWorkspace"); return outWS; } else { auto extract = createChildAlgorithm("ExtractSingleSpectrum"); extract->initialize(); extract->setProperty("InputWorkspace", efficiencies); extract->setProperty("WorkspaceIndex", static_cast<int>(index)); extract->execute(); MatrixWorkspace_sptr outWS = extract->getProperty("OutputWorkspace"); return outWS; } }
void ExtractFFTSpectrum::exec() { MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); MatrixWorkspace_sptr inputImagWS = getProperty("InputImagWorkspace"); const int fftPart = getProperty("FFTPart"); const int numHists = static_cast<int>(inputWS->getNumberHistograms()); MatrixWorkspace_sptr outputWS = WorkspaceFactory::Instance().create(inputWS); Progress prog(this, 0.0, 1.0, numHists); PARALLEL_FOR1(outputWS) for ( int i = 0; i < numHists; i++ ) { PARALLEL_START_INTERUPT_REGION IAlgorithm_sptr childFFT = createChildAlgorithm("FFT"); childFFT->setProperty<MatrixWorkspace_sptr>("InputWorkspace", inputWS); childFFT->setProperty<int>("Real", i); if( inputImagWS ) { childFFT->setProperty<MatrixWorkspace_sptr>("InputImagWorkspace", inputImagWS); childFFT->setProperty<int>("Imaginary", i); } childFFT->execute(); MatrixWorkspace_const_sptr fftTemp = childFFT->getProperty("OutputWorkspace"); outputWS->dataE(i) = fftTemp->readE(fftPart); outputWS->dataY(i) = fftTemp->readY(fftPart); outputWS->dataX(i) = fftTemp->readX(fftPart); prog.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION boost::shared_ptr<Kernel::Units::Label> lblUnit = boost::dynamic_pointer_cast<Kernel::Units::Label>(UnitFactory::Instance().create("Label")); lblUnit->setLabel("Time", "ns"); outputWS->getAxis(0)->unit() = lblUnit; setProperty("OutputWorkspace", outputWS); }
/// Create the efficiency workspace by combining single spectra workspaces into /// one. /// @param labels :: Axis labels for each workspace. /// @param workspaces :: Workspaces to put together. MatrixWorkspace_sptr JoinISISPolarizationEfficiencies::createEfficiencies( std::vector<std::string> const &labels, std::vector<MatrixWorkspace_sptr> const &workspaces) { auto interpolatedWorkspaces = interpolateWorkspaces(workspaces); auto const &inWS = interpolatedWorkspaces.front(); MatrixWorkspace_sptr outWS = DataObjects::create<Workspace2D>( *inWS, labels.size(), inWS->histogram(0)); auto axis1 = new TextAxis(labels.size()); outWS->replaceAxis(1, axis1); outWS->getAxis(0)->setUnit("Wavelength"); for (size_t i = 0; i < interpolatedWorkspaces.size(); ++i) { auto &ws = interpolatedWorkspaces[i]; outWS->setHistogram(i, ws->histogram(0)); axis1->setLabel(i, labels[i]); } return outWS; }
void ConvertTableToMatrixWorkspace::exec() { ITableWorkspace_sptr inputWorkspace = getProperty("InputWorkspace"); std::string columnX = getProperty("ColumnX"); std::string columnY = getProperty("ColumnY"); std::string columnE = getProperty("ColumnE"); size_t nrows = inputWorkspace->rowCount(); std::vector<double> X(nrows); std::vector<double> Y(nrows); std::vector<double> E(nrows); inputWorkspace->getColumn(columnX)->numeric_fill(X); inputWorkspace->getColumn(columnY)->numeric_fill(Y); if (!columnE.empty()) { inputWorkspace->getColumn(columnE)->numeric_fill(E); } else { E.assign(X.size(),1.0); } MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create("Workspace2D",1,X.size(),X.size()); outputWorkspace->dataX(0).assign(X.begin(),X.end()); outputWorkspace->dataY(0).assign(Y.begin(),Y.end()); outputWorkspace->dataE(0).assign(E.begin(),E.end()); outputWorkspace->generateSpectraMap(); boost::shared_ptr<Kernel::Units::Label> labelX = boost::dynamic_pointer_cast<Kernel::Units::Label>( Kernel::UnitFactory::Instance().create("Label") ); labelX->setLabel(columnX); outputWorkspace->getAxis(0)->unit() = labelX; outputWorkspace->setYUnitLabel(columnY); setProperty("OutputWorkspace", outputWorkspace); }
/** Create output workspace * @brief GetSpiceDataRawCountsFromMD::createOutputWorkspace * @param vecX * @param vecY * @param xlabel :: only 'Degrees' can be applied to x-axis * @param ylabel * @return */ MatrixWorkspace_sptr GetSpiceDataRawCountsFromMD::createOutputWorkspace( const std::vector<double> &vecX, const std::vector<double> &vecY, const std::string &xlabel, const std::string &ylabel) { // Create MatrixWorkspace size_t sizex = vecX.size(); size_t sizey = vecY.size(); if (sizex != sizey || sizex == 0) throw std::runtime_error("Unable to create output matrix workspace."); MatrixWorkspace_sptr outws = boost::dynamic_pointer_cast<MatrixWorkspace>( WorkspaceFactory::Instance().create("Workspace2D", 1, sizex, sizey)); if (!outws) throw std::runtime_error("Failed to create output matrix workspace."); // Set data MantidVec &dataX = outws->dataX(0); MantidVec &dataY = outws->dataY(0); MantidVec &dataE = outws->dataE(0); for (size_t i = 0; i < sizex; ++i) { dataX[i] = vecX[i]; dataY[i] = vecY[i]; if (dataY[i] > 1.) dataE[i] = sqrt(dataY[i]); else dataE[i] = 1.; } // Set label outws->setYUnitLabel(ylabel); if (xlabel.size() != 0) { try { outws->getAxis(0)->setUnit(xlabel); } catch (...) { g_log.information() << "Label " << xlabel << " for X-axis is not a unit " "registered." << "\n"; } } return outws; }
/** Creates the output workspace, its size, units, etc. * @param binParams the bin boundary specification using the same same syntax as param the Rebin algorithm * @return A pointer to the newly-created workspace */ API::MatrixWorkspace_sptr Q1D2::setUpOutputWorkspace(const std::vector<double> & binParams) const { // Calculate the output binning MantidVecPtr XOut; size_t sizeOut = static_cast<size_t>( VectorHelper::createAxisFromRebinParams(binParams, XOut.access())); // Now create the output workspace MatrixWorkspace_sptr outputWS = WorkspaceFactory::Instance().create(m_dataWS,1,sizeOut,sizeOut-1); outputWS->getAxis(0)->unit() = UnitFactory::Instance().create("MomentumTransfer"); outputWS->setYUnitLabel("1/cm"); // Set the X vector for the output workspace outputWS->setX(0, XOut); outputWS->isDistribution(true); outputWS->getSpectrum(0)->clearDetectorIDs(); outputWS->getSpectrum(0)->setSpectrumNo(1); return outputWS; }
/** Populate output workspace with results * @param outWS :: [input/output] Output workspace to populate * @param nplots :: [input] Number of histograms */ void PlotAsymmetryByLogValue::populateOutputWorkspace( MatrixWorkspace_sptr &outWS, int nplots) { auto tAxis = new TextAxis(nplots); if (nplots == 1) { size_t i = 0; for (auto &value : m_logValue) { outWS->dataX(0)[i] = value.second; outWS->dataY(0)[i] = m_redY[value.first]; outWS->dataE(0)[i] = m_redE[value.first]; i++; } tAxis->setLabel(0, "Asymmetry"); } else { size_t i = 0; for (auto &value : m_logValue) { outWS->dataX(0)[i] = value.second; outWS->dataY(0)[i] = m_diffY[value.first]; outWS->dataE(0)[i] = m_diffE[value.first]; outWS->dataX(1)[i] = value.second; outWS->dataY(1)[i] = m_redY[value.first]; outWS->dataE(1)[i] = m_redE[value.first]; outWS->dataX(2)[i] = value.second; outWS->dataY(2)[i] = m_greenY[value.first]; outWS->dataE(2)[i] = m_greenE[value.first]; outWS->dataX(3)[i] = value.second; outWS->dataY(3)[i] = m_sumY[value.first]; outWS->dataE(3)[i] = m_sumE[value.first]; i++; } tAxis->setLabel(0, "Red-Green"); tAxis->setLabel(1, "Red"); tAxis->setLabel(2, "Green"); tAxis->setLabel(3, "Red+Green"); } outWS->replaceAxis(1, tAxis); outWS->getAxis(0)->title() = m_logName; outWS->setYUnitLabel("Asymmetry"); }
/** 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 LoadNXSPE::exec() { std::string filename = getProperty("Filename"); // quicly check if it's really nxspe try { ::NeXus::File file(filename); std::string mainEntry = (*(file.getEntries().begin())).first; file.openGroup(mainEntry, "NXentry"); file.openData("definition"); if (identiferConfidence(file.getStrData()) < 1) { throw std::invalid_argument("Not NXSPE"); } file.close(); } catch (...) { throw std::invalid_argument("Not NeXus or not NXSPE"); } // Load the data ::NeXus::File file(filename); std::string mainEntry = (*(file.getEntries().begin())).first; file.openGroup(mainEntry, "NXentry"); file.openGroup("NXSPE_info", "NXcollection"); std::map<std::string, std::string> entries = file.getEntries(); std::vector<double> temporary; double fixed_energy, psi = 0.; if (!entries.count("fixed_energy")) { throw std::invalid_argument("fixed_energy field was not found"); } file.openData("fixed_energy"); file.getData(temporary); fixed_energy = temporary.at(0); file.closeData(); if (entries.count("psi")) { file.openData("psi"); file.getData(temporary); psi = temporary.at(0); file.closeData(); } int kikfscaling = 0; if (entries.count("ki_over_kf_scaling")) { file.openData("ki_over_kf_scaling"); std::vector<int> temporaryint; file.getData(temporaryint); kikfscaling = temporaryint.at(0); file.closeData(); } file.closeGroup(); // NXSPE_Info file.openGroup("data", "NXdata"); entries = file.getEntries(); if (!entries.count("data")) { throw std::invalid_argument("data field was not found"); } file.openData("data"); ::NeXus::Info info = file.getInfo(); std::size_t numSpectra = static_cast<std::size_t>(info.dims.at(0)); std::size_t numBins = static_cast<std::size_t>(info.dims.at(1)); std::vector<double> data; file.getData(data); file.closeData(); if (!entries.count("error")) { throw std::invalid_argument("error field was not found"); } file.openData("error"); std::vector<double> error; file.getData(error); file.closeData(); if (!entries.count("energy")) { throw std::invalid_argument("energy field was not found"); } file.openData("energy"); std::vector<double> energies; file.getData(energies); file.closeData(); if (!entries.count("azimuthal")) { throw std::invalid_argument("azimuthal field was not found"); } file.openData("azimuthal"); std::vector<double> azimuthal; file.getData(azimuthal); file.closeData(); if (!entries.count("azimuthal_width")) { throw std::invalid_argument("azimuthal_width field was not found"); } file.openData("azimuthal_width"); std::vector<double> azimuthal_width; file.getData(azimuthal_width); file.closeData(); if (!entries.count("polar")) { throw std::invalid_argument("polar field was not found"); } file.openData("polar"); std::vector<double> polar; file.getData(polar); file.closeData(); if (!entries.count("polar_width")) { throw std::invalid_argument("polar_width field was not found"); } file.openData("polar_width"); std::vector<double> polar_width; file.getData(polar_width); file.closeData(); // distance might not have been saved in all NXSPE files std::vector<double> distance; if (entries.count("distance")) { file.openData("distance"); file.getData(distance); file.closeData(); } file.closeGroup(); // data group file.closeGroup(); // Main entry file.close(); // check if dimensions of the vectors are correct if ((error.size() != data.size()) || (azimuthal.size() != numSpectra) || (azimuthal_width.size() != numSpectra) || (polar.size() != numSpectra) || (polar_width.size() != numSpectra) || ((energies.size() != numBins) && (energies.size() != numBins + 1))) { throw std::invalid_argument( "incompatible sizes of fields in the NXSPE file"); } MatrixWorkspace_sptr outputWS = boost::dynamic_pointer_cast<MatrixWorkspace>( WorkspaceFactory::Instance().create("Workspace2D", numSpectra, energies.size(), numBins)); // Need to get hold of the parameter map outputWS->getAxis(0)->unit() = UnitFactory::Instance().create("DeltaE"); outputWS->setYUnit("SpectraNumber"); // add logs outputWS->mutableRun().addLogData( new PropertyWithValue<double>("Ei", fixed_energy)); outputWS->mutableRun().addLogData(new PropertyWithValue<double>("psi", psi)); outputWS->mutableRun().addLogData(new PropertyWithValue<std::string>( "ki_over_kf_scaling", kikfscaling == 1 ? "true" : "false")); // Set Goniometer Geometry::Goniometer gm; gm.pushAxis("psi", 0, 1, 0, psi); outputWS->mutableRun().setGoniometer(gm, true); // generate instrument Geometry::Instrument_sptr instrument(new Geometry::Instrument("NXSPE")); outputWS->setInstrument(instrument); Geometry::ObjComponent *source = new Geometry::ObjComponent("source"); source->setPos(0.0, 0.0, -10.0); instrument->add(source); instrument->markAsSource(source); Geometry::ObjComponent *sample = new Geometry::ObjComponent("sample"); instrument->add(sample); instrument->markAsSamplePos(sample); Geometry::Object_const_sptr cuboid( createCuboid(0.1, 0.1, 0.1)); // FIXME: memory hog on rendering. Also, // make each detector separate size for (std::size_t i = 0; i < numSpectra; ++i) { double r = 1.0; if (!distance.empty()) { r = distance.at(i); } Kernel::V3D pos; pos.spherical(r, polar.at(i), azimuthal.at(i)); Geometry::Detector *det = new Geometry::Detector("pixel", static_cast<int>(i + 1), sample); det->setPos(pos); det->setShape(cuboid); instrument->add(det); instrument->markAsDetector(det); } Geometry::ParameterMap &pmap = outputWS->instrumentParameters(); std::vector<double>::iterator itdata = data.begin(), iterror = error.begin(), itdataend, iterrorend; API::Progress prog = API::Progress(this, 0.0, 0.9, numSpectra); for (std::size_t i = 0; i < numSpectra; ++i) { itdataend = itdata + numBins; iterrorend = iterror + numBins; outputWS->dataX(i) = energies; if ((!boost::math::isfinite(*itdata)) || (*itdata <= -1e10)) // masked bin { outputWS->dataY(i) = std::vector<double>(numBins, 0); outputWS->dataE(i) = std::vector<double>(numBins, 0); pmap.addBool(outputWS->getDetector(i)->getComponentID(), "masked", true); } else { outputWS->dataY(i) = std::vector<double>(itdata, itdataend); outputWS->dataE(i) = std::vector<double>(iterror, iterrorend); } itdata = (itdataend); iterror = (iterrorend); prog.report(); } setProperty("OutputWorkspace", outputWS); }