/** * 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, 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; }
void SphericalAbsorption::exec() { // Retrieve the input workspace m_inputWS = getProperty("InputWorkspace"); // Get the input parameters retrieveBaseProperties(); // Create the output workspace MatrixWorkspace_sptr correctionFactors = WorkspaceFactory::Instance().create(m_inputWS); correctionFactors->isDistribution(true); // The output of this is a distribution correctionFactors->setYUnit(""); // Need to explicitly set YUnit to nothing correctionFactors->setYUnitLabel("Attenuation factor"); double m_sphRadius = getProperty("SphericalSampleRadius"); // in cm IAlgorithm_sptr anvred = createSubAlgorithm("AnvredCorrection"); anvred->setProperty<MatrixWorkspace_sptr>("InputWorkspace", m_inputWS); anvred->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", correctionFactors); anvred->setProperty("PreserveEvents", true); anvred->setProperty("ReturnTransmissionOnly", true); anvred->setProperty("LinearScatteringCoef", m_refAtten); anvred->setProperty("LinearAbsorptionCoef", m_scattering); anvred->setProperty("Radius", m_sphRadius); anvred->executeAsSubAlg(); // Get back the result correctionFactors = anvred->getProperty("OutputWorkspace"); setProperty("OutputWorkspace", correctionFactors); }
/** 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; }
MatrixWorkspace_sptr MonteCarloAbsorption::createOutputWorkspace( const MatrixWorkspace &inputWS) const { MatrixWorkspace_sptr outputWS = inputWS.clone(); // The algorithm computes the signal values at bin centres so they should // be treated as a distribution outputWS->setDistribution(true); outputWS->setYUnit(""); outputWS->setYUnitLabel("Attenuation factor"); return outputWS; }
MatrixWorkspace_sptr CalculateCarpenterSampleCorrection::createOutputWorkspace( const MatrixWorkspace_sptr &inputWksp, const std::string ylabel) const { MatrixWorkspace_sptr outputWS = create<HistoWorkspace>(*inputWksp); // The algorithm computes the signal values at bin centres so they should // be treated as a distribution outputWS->setDistribution(true); outputWS->setYUnit(""); outputWS->setYUnitLabel(ylabel); return outputWS; }
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); }
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); }
/** Execute the algorithm. */ void ResampleX::exec() { // generically having access to the input workspace is a good idea MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); bool inPlace = (inputWS == outputWS); // Rebinning in-place m_isDistribution = inputWS->isDistribution(); m_isHistogram = inputWS->isHistogramData(); const int numSpectra = static_cast<int>(inputWS->getNumberHistograms()); // the easy parameters m_useLogBinning = getProperty("LogBinning"); m_numBins = getProperty("NumberBins"); m_preserveEvents = getProperty("PreserveEvents"); // determine the xmin/xmax for the workspace vector<double> xmins = getProperty("XMin"); vector<double> xmaxs = getProperty("XMax"); string error = determineXMinMax(inputWS, xmins, xmaxs); if (!error.empty()) throw std::runtime_error(error); bool common_limits = true; { double xmin_common = xmins[0]; double xmax_common = xmaxs[0]; for (size_t i = 1; i < xmins.size(); ++i) { if (xmins[i] != xmin_common) { common_limits = false; break; } if (xmaxs[i] != xmax_common) { common_limits = false; break; } } } if (common_limits) { g_log.debug() << "Common limits between all spectra\n"; } else { g_log.debug() << "Does not have common limits between all spectra\n"; } // start doing actual work EventWorkspace_const_sptr inputEventWS = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS); if (inputEventWS != nullptr) { if (m_preserveEvents) { if (inPlace) { g_log.debug() << "Rebinning event workspace in place\n"; } else { g_log.debug() << "Rebinning event workspace out of place\n"; outputWS = inputWS->clone(); } auto outputEventWS = boost::dynamic_pointer_cast<EventWorkspace>(outputWS); if (common_limits) { // get the delta from the first since they are all the same BinEdges xValues(0); const double delta = this->determineBinning(xValues.mutableRawData(), xmins[0], xmaxs[0]); g_log.debug() << "delta = " << delta << "\n"; outputEventWS->setAllX(xValues); } else { // initialize progress reporting. Progress prog(this, 0.0, 1.0, numSpectra); // do the rebinning PARALLEL_FOR_IF(Kernel::threadSafe(*inputEventWS, *outputWS)) for (int wkspIndex = 0; wkspIndex < numSpectra; ++wkspIndex) { PARALLEL_START_INTERUPT_REGION BinEdges xValues(0); const double delta = this->determineBinning( xValues.mutableRawData(), xmins[wkspIndex], xmaxs[wkspIndex]); g_log.debug() << "delta[wkspindex=" << wkspIndex << "] = " << delta << " xmin=" << xmins[wkspIndex] << " xmax=" << xmaxs[wkspIndex] << "\n"; outputEventWS->setHistogram(wkspIndex, xValues); prog.report(name()); // Report progress PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION } } // end if (m_preserveEvents) else // event workspace -> matrix workspace { //--------- Different output, OR you're inplace but not preserving Events g_log.information() << "Creating a Workspace2D from the EventWorkspace " << inputEventWS->getName() << ".\n"; outputWS = create<DataObjects::Workspace2D>( *inputWS, numSpectra, HistogramData::BinEdges(m_numBins + 1)); // Initialize progress reporting. Progress prog(this, 0.0, 1.0, numSpectra); // Go through all the histograms and set the data PARALLEL_FOR_IF(Kernel::threadSafe(*inputEventWS, *outputWS)) for (int wkspIndex = 0; wkspIndex < numSpectra; ++wkspIndex) { PARALLEL_START_INTERUPT_REGION // Set the X axis for each output histogram MantidVec xValues; const double delta = this->determineBinning(xValues, xmins[wkspIndex], xmaxs[wkspIndex]); g_log.debug() << "delta[wkspindex=" << wkspIndex << "] = " << delta << "\n"; outputWS->setBinEdges(wkspIndex, xValues); // Get a const event list reference. inputEventWS->dataY() doesn't work. const EventList &el = inputEventWS->getSpectrum(wkspIndex); MantidVec y_data, e_data; // The EventList takes care of histogramming. el.generateHistogram(xValues, y_data, e_data); // Copy the data over. outputWS->mutableY(wkspIndex) = std::move(y_data); outputWS->mutableE(wkspIndex) = std::move(e_data); // Report progress prog.report(name()); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION // Copy all the axes for (int i = 1; i < inputWS->axes(); i++) { outputWS->replaceAxis(i, inputWS->getAxis(i)->clone(outputWS.get())); outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit(); } // Copy the units over too. for (int i = 0; i < outputWS->axes(); ++i) { outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit(); } outputWS->setYUnit(inputEventWS->YUnit()); outputWS->setYUnitLabel(inputEventWS->YUnitLabel()); } // Assign it to the output workspace property setProperty("OutputWorkspace", outputWS); return; } else // (inputeventWS != NULL)
/** 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); }
void SANSSolidAngleCorrection::exec() { // Reduction property manager const std::string reductionManagerName = getProperty("ReductionProperties"); boost::shared_ptr<PropertyManager> reductionManager; if (PropertyManagerDataService::Instance().doesExist(reductionManagerName)) { reductionManager = PropertyManagerDataService::Instance().retrieve(reductionManagerName); } else { reductionManager = boost::make_shared<PropertyManager>(); PropertyManagerDataService::Instance().addOrReplace(reductionManagerName, reductionManager); } // If the solid angle algorithm isn't in the reduction properties, add it if (!reductionManager->existsProperty("SolidAngleAlgorithm")) { AlgorithmProperty *algProp = new AlgorithmProperty("SolidAngleAlgorithm"); algProp->setValue(toString()); reductionManager->declareProperty(algProp); } MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace"); DataObjects::EventWorkspace_const_sptr inputEventWS = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS); if (inputEventWS) return execEvent(); // Now create the output workspace MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); if (outputWS != inputWS) { outputWS = WorkspaceFactory::Instance().create(inputWS); outputWS->isDistribution(true); outputWS->setYUnit(""); outputWS->setYUnitLabel("Steradian"); setProperty("OutputWorkspace", outputWS); } const int numHists = static_cast<int>(inputWS->getNumberHistograms()); Progress progress(this, 0.0, 1.0, numHists); // Number of X bins const int xLength = static_cast<int>(inputWS->readY(0).size()); PARALLEL_FOR2(outputWS, inputWS) for (int i = 0; i < numHists; ++i) { PARALLEL_START_INTERUPT_REGION outputWS->dataX(i) = inputWS->readX(i); IDetector_const_sptr det; try { det = inputWS->getDetector(i); } catch (Exception::NotFoundError &) { g_log.warning() << "Spectrum index " << i << " has no detector assigned to it - discarding" << std::endl; // Catch if no detector. Next line tests whether this happened - test // placed // outside here because Mac Intel compiler doesn't like 'continue' in a // catch // in an openmp block. } // If no detector found, skip onto the next spectrum if (!det) continue; // Skip if we have a monitor or if the detector is masked. if (det->isMonitor() || det->isMasked()) continue; const MantidVec &YIn = inputWS->readY(i); const MantidVec &EIn = inputWS->readE(i); MantidVec &YOut = outputWS->dataY(i); MantidVec &EOut = outputWS->dataE(i); // Compute solid angle correction factor const bool is_tube = getProperty("DetectorTubes"); const double tanTheta = tan(inputWS->detectorTwoTheta(det)); const double theta_term = sqrt(tanTheta * tanTheta + 1.0); double corr; if (is_tube) { const double tanAlpha = tan(getYTubeAngle(det, inputWS)); const double alpha_term = sqrt(tanAlpha * tanAlpha + 1.0); corr = alpha_term * theta_term * theta_term; } else { corr = theta_term * theta_term * theta_term; } // Correct data for all X bins for (int j = 0; j < xLength; j++) { YOut[j] = YIn[j] * corr; EOut[j] = fabs(EIn[j] * corr); } progress.report("Solid Angle Correction"); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION setProperty("OutputMessage", "Solid angle correction applied"); }
/** Executes the algorithm. Reading in the file and creating and populating * the output workspace * * @throw Exception::FileError If the Nexus file cannot be found/opened * @throw std::invalid_argument If the optional properties are set to invalid *values */ void LoadTOFRawNexus::exec() { // The input properties std::string filename = getPropertyValue("Filename"); m_signalNo = getProperty("Signal"); m_spec_min = getProperty("SpectrumMin"); m_spec_max = getProperty("SpectrumMax"); // Find the entry name we want. std::string entry_name = LoadTOFRawNexus::getEntryName(filename); // Count pixels and other setup auto prog = new Progress(this, 0.0, 1.0, 10); prog->doReport("Counting pixels"); std::vector<std::string> bankNames; countPixels(filename, entry_name, bankNames); g_log.debug() << "Workspace found to have " << m_numPixels << " pixels and " << m_numBins << " bins" << std::endl; prog->setNumSteps(bankNames.size() + 5); prog->doReport("Creating workspace"); // Start with a dummy WS just to hold the logs and load the instrument MatrixWorkspace_sptr WS = WorkspaceFactory::Instance().create( "Workspace2D", m_numPixels, m_numBins + 1, m_numBins); // Load the logs prog->doReport("Loading DAS logs"); g_log.debug() << "Loading DAS logs" << std::endl; int nPeriods = 1; // Unused std::unique_ptr<const TimeSeriesProperty<int>> periodLog( new const TimeSeriesProperty<int>("period_log")); // Unused LoadEventNexus::runLoadNexusLogs<MatrixWorkspace_sptr>( filename, WS, *this, false, nPeriods, periodLog); // Load the instrument prog->report("Loading instrument"); g_log.debug() << "Loading instrument" << std::endl; LoadEventNexus::runLoadInstrument<MatrixWorkspace_sptr>(filename, WS, entry_name, this); // Load the meta data, but don't stop on errors prog->report("Loading metadata"); g_log.debug() << "Loading metadata" << std::endl; try { LoadEventNexus::loadEntryMetadata(filename, WS, entry_name); } catch (std::exception &e) { g_log.warning() << "Error while loading meta data: " << e.what() << std::endl; } // Set the spectrum number/detector ID at each spectrum. This is consistent // with LoadEventNexus for non-ISIS files. prog->report("Building Spectra Mapping"); g_log.debug() << "Building Spectra Mapping" << std::endl; WS->rebuildSpectraMapping(false); // And map ID to WI g_log.debug() << "Mapping ID to WI" << std::endl; const auto id_to_wi = WS->getDetectorIDToWorkspaceIndexMap(); // Load each bank sequentially // PARALLEL_FOR1(WS) for (auto bankName : bankNames) { // PARALLEL_START_INTERUPT_REGION prog->report("Loading bank " + bankName); g_log.debug() << "Loading bank " << bankName << std::endl; loadBank(filename, entry_name, bankName, WS, id_to_wi); // PARALLEL_END_INTERUPT_REGION } // PARALLEL_CHECK_INTERUPT_REGION // Set some units if (m_xUnits == "Ang") WS->getAxis(0)->setUnit("dSpacing"); else if (m_xUnits == "invAng") WS->getAxis(0)->setUnit("MomentumTransfer"); else // Default to TOF for any other string WS->getAxis(0)->setUnit("TOF"); WS->setYUnit("Counts"); // Set to the output setProperty("OutputWorkspace", WS); delete prog; }
/** Executes the rebin algorithm * * @throw runtime_error Thrown if the bin range does not intersect the range of *the input workspace */ void Rebin::exec() { // Get the input workspace MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); // Are we preserving event workspace-iness? bool PreserveEvents = getProperty("PreserveEvents"); // Rebinning in-place bool inPlace = (inputWS == outputWS); std::vector<double> rbParams = rebinParamsFromInput(getProperty("Params"), *inputWS, g_log); const bool dist = inputWS->isDistribution(); const bool isHist = inputWS->isHistogramData(); // workspace independent determination of length const int histnumber = static_cast<int>(inputWS->getNumberHistograms()); //------------------------------------------------------- bool fullBinsOnly = getProperty("FullBinsOnly"); MantidVecPtr XValues_new; // create new output X axis const int ntcnew = VectorHelper::createAxisFromRebinParams( rbParams, XValues_new.access(), true, fullBinsOnly); //--------------------------------------------------------------------------------- // Now, determine if the input workspace is actually an EventWorkspace EventWorkspace_const_sptr eventInputWS = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS); if (eventInputWS != NULL) { //------- EventWorkspace as input ------------------------------------- EventWorkspace_sptr eventOutputWS = boost::dynamic_pointer_cast<EventWorkspace>(outputWS); if (inPlace && PreserveEvents) { // -------------Rebin in-place, preserving events // ---------------------------------------------- // This only sets the X axis. Actual rebinning will be done upon data // access. eventOutputWS->setAllX(XValues_new); this->setProperty( "OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(eventOutputWS)); } else if (!inPlace && PreserveEvents) { // -------- NOT in-place, but you want to keep events for some reason. // ---------------------- // Must copy the event workspace to a new EventWorkspace (and bin that). // Make a brand new EventWorkspace eventOutputWS = boost::dynamic_pointer_cast<EventWorkspace>( API::WorkspaceFactory::Instance().create( "EventWorkspace", inputWS->getNumberHistograms(), 2, 1)); // Copy geometry over. API::WorkspaceFactory::Instance().initializeFromParent( inputWS, eventOutputWS, false); // You need to copy over the data as well. eventOutputWS->copyDataFrom((*eventInputWS)); // This only sets the X axis. Actual rebinning will be done upon data // access. eventOutputWS->setAllX(XValues_new); // Cast to the matrixOutputWS and save it this->setProperty( "OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(eventOutputWS)); } else { //--------- Different output, OR you're inplace but not preserving Events //--- create a Workspace2D ------- g_log.information() << "Creating a Workspace2D from the EventWorkspace " << eventInputWS->getName() << ".\n"; // Create a Workspace2D // This creates a new Workspace2D through a torturous route using the // WorkspaceFactory. // The Workspace2D is created with an EMPTY CONSTRUCTOR outputWS = WorkspaceFactory::Instance().create("Workspace2D", histnumber, ntcnew, ntcnew - 1); WorkspaceFactory::Instance().initializeFromParent(inputWS, outputWS, true); // Initialize progress reporting. Progress prog(this, 0.0, 1.0, histnumber); // Go through all the histograms and set the data PARALLEL_FOR3(inputWS, eventInputWS, outputWS) for (int i = 0; i < histnumber; ++i) { PARALLEL_START_INTERUPT_REGION // Set the X axis for each output histogram outputWS->setX(i, XValues_new); // Get a const event list reference. eventInputWS->dataY() doesn't work. const EventList &el = eventInputWS->getEventList(i); MantidVec y_data, e_data; // The EventList takes care of histogramming. el.generateHistogram(*XValues_new, y_data, e_data); // Copy the data over. outputWS->dataY(i).assign(y_data.begin(), y_data.end()); outputWS->dataE(i).assign(e_data.begin(), e_data.end()); // Report progress prog.report(name()); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION // Copy all the axes for (int i = 1; i < inputWS->axes(); i++) { outputWS->replaceAxis(i, inputWS->getAxis(i)->clone(outputWS.get())); outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit(); } // Copy the units over too. for (int i = 0; i < outputWS->axes(); ++i) outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit(); outputWS->setYUnit(eventInputWS->YUnit()); outputWS->setYUnitLabel(eventInputWS->YUnitLabel()); // Assign it to the output workspace property setProperty("OutputWorkspace", outputWS); } } // END ---- EventWorkspace
/** * Execute the algorithm. */ void RebinByTimeBase::exec() { using Mantid::DataObjects::EventWorkspace; IEventWorkspace_sptr inWS = getProperty("InputWorkspace"); if (!boost::dynamic_pointer_cast<EventWorkspace>(inWS)) { const std::string algName = this->name(); throw std::invalid_argument( algName + " Algorithm requires an EventWorkspace as an input."); } MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); // retrieve the properties const std::vector<double> inParams = getProperty("Params"); std::vector<double> rebinningParams; // workspace independent determination of length const int histnumber = static_cast<int>(inWS->getNumberHistograms()); const uint64_t nanoSecondsInASecond = static_cast<uint64_t>(1e9); const DateAndTime runStartTime = inWS->run().startTime(); // The validator only passes parameters with size 1, or 3xn. double tStep = 0; if (inParams.size() >= 3) { // Use the start of the run to offset the times provided by the user. pulse // time of the events are absolute. const DateAndTime startTime = runStartTime + inParams[0]; const DateAndTime endTime = runStartTime + inParams[2]; // Rebinning params in nanoseconds. rebinningParams.push_back( static_cast<double>(startTime.totalNanoseconds())); tStep = inParams[1] * nanoSecondsInASecond; rebinningParams.push_back(tStep); rebinningParams.push_back(static_cast<double>(endTime.totalNanoseconds())); } else if (inParams.size() == 1) { const uint64_t xmin = getMinX(inWS); const uint64_t xmax = getMaxX(inWS); rebinningParams.push_back(static_cast<double>(xmin)); tStep = inParams[0] * nanoSecondsInASecond; rebinningParams.push_back(tStep); rebinningParams.push_back(static_cast<double>(xmax)); } // Validate the timestep. if (tStep <= 0) { throw std::invalid_argument( "Cannot have a timestep less than or equal to zero."); } // Initialize progress reporting. Progress prog(this, 0.0, 1.0, histnumber); MantidVecPtr XValues_new; // create new X axis, with absolute times in seconds. const int ntcnew = VectorHelper::createAxisFromRebinParams( rebinningParams, XValues_new.access()); ConvertToRelativeTime transformToRelativeT(runStartTime); // Transform the output into relative times in seconds. MantidVec OutXValues_scaled(XValues_new->size()); std::transform(XValues_new->begin(), XValues_new->end(), OutXValues_scaled.begin(), transformToRelativeT); outputWS = WorkspaceFactory::Instance().create("Workspace2D", histnumber, ntcnew, ntcnew - 1); WorkspaceFactory::Instance().initializeFromParent(inWS, outputWS, true); // Copy all the axes for (int i = 1; i < inWS->axes(); i++) { outputWS->replaceAxis(i, inWS->getAxis(i)->clone(outputWS.get())); outputWS->getAxis(i)->unit() = inWS->getAxis(i)->unit(); } // X-unit is relative time since the start of the run. outputWS->getAxis(0)->unit() = boost::make_shared<Units::Time>(); // Copy the units over too. for (int i = 1; i < outputWS->axes(); ++i) { outputWS->getAxis(i)->unit() = inWS->getAxis(i)->unit(); } outputWS->setYUnit(inWS->YUnit()); outputWS->setYUnitLabel(inWS->YUnitLabel()); // Assign it to the output workspace property setProperty("OutputWorkspace", outputWS); // Go through all the histograms and set the data doHistogramming(inWS, outputWS, XValues_new, OutXValues_scaled, prog); }
/** Load an individual "<SASentry>" element into a new workspace. It extends the *LoadCanSAS1D * in the direction of loading the SAStransmission_spectrum as well. (which was *introduced in version 1.1) * * @param[in] workspaceData points to a "<SASentry>" element * @param[out] runName the name this workspace should take * @return dataWS this workspace will be filled with data * @throw NotFoundError if any expected elements couldn't be read * @throw NotImplementedError if the entry doesn't contain exactly one run */ MatrixWorkspace_sptr LoadCanSAS1D2::loadEntry(Poco::XML::Node *const workspaceData, std::string &runName) { MatrixWorkspace_sptr main_out = LoadCanSAS1D::loadEntry(workspaceData, runName); bool loadTrans = getProperty("LoadTransmission"); if (!loadTrans) return main_out; // all done. It is not to load the transmission, nor check // if it exists. Element *workspaceElem = dynamic_cast<Element *>(workspaceData); // check(workspaceElem, "<SASentry>"); // already done at // LoadCanSAS1D::loadEntry Poco::AutoPtr<NodeList> sasTransList = workspaceElem->getElementsByTagName("SAStransmission_spectrum"); if (!sasTransList->length()) { g_log.warning() << "There is no transmission data for this file " << getPropertyValue("Filename") << std::endl; return main_out; } for (unsigned short trans_index = 0; trans_index < sasTransList->length(); trans_index++) { // foreach SAStransmission_spectrum Node *idataElem = sasTransList->item(trans_index); Element *sasTrasElem = dynamic_cast<Element *>(idataElem); if (!sasTrasElem) continue; std::vector<API::MatrixWorkspace_sptr> &group = (sasTrasElem->getAttribute("name") == "sample") ? trans_gp : trans_can_gp; // getting number of Tdata elements in the xml file Poco::AutoPtr<NodeList> tdataElemList = sasTrasElem->getElementsByTagName("Tdata"); size_t nBins = tdataElemList->length(); MatrixWorkspace_sptr dataWS = WorkspaceFactory::Instance().create("Workspace2D", 1, nBins, nBins); createLogs(workspaceElem, dataWS); std::string title = main_out->getTitle(); title += ":trans"; title += sasTrasElem->getAttribute("name"); dataWS->setTitle(title); dataWS->isDistribution(true); dataWS->setYUnit(""); // load workspace data MantidVec &X = dataWS->dataX(0); MantidVec &Y = dataWS->dataY(0); MantidVec &E = dataWS->dataE(0); int vecindex = 0; // iterate through each Tdata element and get the values of "Lambda", //"T" and "Tdev" text nodes and fill X,Y,E vectors for (unsigned long index = 0; index < nBins; ++index) { Node *idataElem = tdataElemList->item(index); Element *elem = dynamic_cast<Element *>(idataElem); if (elem) { // setting X vector std::string nodeVal; Element *qElem = elem->getChildElement("Lambda"); check(qElem, "Lambda"); nodeVal = qElem->innerText(); std::stringstream x(nodeVal); double d; x >> d; X[vecindex] = d; // setting Y vector Element *iElem = elem->getChildElement("T"); check(qElem, "T"); nodeVal = iElem->innerText(); std::stringstream y(nodeVal); y >> d; Y[vecindex] = d; // setting the error vector Element *idevElem = elem->getChildElement("Tdev"); check(qElem, "Tdev"); nodeVal = idevElem->innerText(); std::stringstream e(nodeVal); e >> d; E[vecindex] = d; ++vecindex; } } runLoadInstrument(main_out->getInstrument()->getName(), dataWS); dataWS->getAxis(0)->setUnit("Wavelength"); // add to group group.push_back(dataWS); } return main_out; }
/** Execute the algorithm. */ void ResampleX::exec() { // generically having access to the input workspace is a good idea MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); bool inPlace = (inputWS == outputWS); // Rebinning in-place m_isDistribution = inputWS->isDistribution(); m_isHistogram = inputWS->isHistogramData(); int numSpectra = static_cast<int>(inputWS->getNumberHistograms()); // the easy parameters m_useLogBinning = getProperty("LogBinning"); m_numBins = getProperty("NumberBins"); m_preserveEvents = getProperty("PreserveEvents"); // determine the xmin/xmax for the workspace vector<double> xmins = getProperty("XMin"); vector<double> xmaxs = getProperty("XMax"); string error = determineXMinMax(inputWS, xmins, xmaxs); if (!error.empty()) throw std::runtime_error(error); bool common_limits = true; { double xmin_common = xmins[0]; double xmax_common = xmaxs[0]; for (size_t i = 1; i < xmins.size(); ++i) { if (xmins[i] != xmin_common) { common_limits = false; break; } if (xmaxs[i] != xmax_common) { common_limits = false; break; } } } if (common_limits) { g_log.debug() << "Common limits between all spectra\n"; } else { g_log.debug() << "Does not have common limits between all spectra\n"; } // start doing actual work EventWorkspace_const_sptr inputEventWS = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS); if (inputEventWS != NULL) { if (m_preserveEvents) { EventWorkspace_sptr outputEventWS = boost::dynamic_pointer_cast<EventWorkspace>(outputWS); if (inPlace) { g_log.debug() << "Rebinning event workspace in place\n"; } else { g_log.debug() << "Rebinning event workspace out of place\n"; // copy the event workspace to a new EventWorkspace outputEventWS = boost::dynamic_pointer_cast<EventWorkspace>( API::WorkspaceFactory::Instance().create( "EventWorkspace", inputWS->getNumberHistograms(), 2, 1)); // copy geometry over. API::WorkspaceFactory::Instance().initializeFromParent( inputEventWS, outputEventWS, false); // copy over the data as well. outputEventWS->copyDataFrom((*inputEventWS)); } if (common_limits) { // get the delta from the first since they are all the same MantidVecPtr xValues; double delta = this->determineBinning(xValues.access(), xmins[0], xmaxs[0]); g_log.debug() << "delta = " << delta << "\n"; outputEventWS->setAllX(xValues); } else { // initialize progress reporting. Progress prog(this, 0.0, 1.0, numSpectra); // do the rebinning PARALLEL_FOR2(inputEventWS, outputWS) for (int wkspIndex = 0; wkspIndex < numSpectra; ++wkspIndex) { PARALLEL_START_INTERUPT_REGION MantidVec xValues; double delta = this->determineBinning(xValues, xmins[wkspIndex], xmaxs[wkspIndex]); g_log.debug() << "delta[wkspindex=" << wkspIndex << "] = " << delta << " xmin=" << xmins[wkspIndex] << " xmax=" << xmaxs[wkspIndex] << "\n"; outputEventWS->getSpectrum(wkspIndex)->setX(xValues); prog.report(name()); // Report progress PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION } this->setProperty( "OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(outputEventWS)); } // end if (m_preserveEvents) else // event workspace -> matrix workspace { //--------- Different output, OR you're inplace but not preserving Events //--- create a Workspace2D ------- g_log.information() << "Creating a Workspace2D from the EventWorkspace " << inputEventWS->getName() << ".\n"; // Create a Workspace2D // This creates a new Workspace2D through a torturous route using the // WorkspaceFactory. // The Workspace2D is created with an EMPTY CONSTRUCTOR outputWS = WorkspaceFactory::Instance().create("Workspace2D", numSpectra, m_numBins, m_numBins - 1); WorkspaceFactory::Instance().initializeFromParent(inputWS, outputWS, true); // Initialize progress reporting. Progress prog(this, 0.0, 1.0, numSpectra); // Go through all the histograms and set the data PARALLEL_FOR2(inputEventWS, outputWS) for (int wkspIndex = 0; wkspIndex < numSpectra; ++wkspIndex) { PARALLEL_START_INTERUPT_REGION // Set the X axis for each output histogram MantidVec xValues; double delta = this->determineBinning(xValues, xmins[wkspIndex], xmaxs[wkspIndex]); g_log.debug() << "delta[wkspindex=" << wkspIndex << "] = " << delta << "\n"; outputWS->setX(wkspIndex, xValues); // Get a const event list reference. inputEventWS->dataY() doesn't work. const EventList &el = inputEventWS->getEventList(wkspIndex); MantidVec y_data, e_data; // The EventList takes care of histogramming. el.generateHistogram(xValues, y_data, e_data); // Copy the data over. outputWS->dataY(wkspIndex).assign(y_data.begin(), y_data.end()); outputWS->dataE(wkspIndex).assign(e_data.begin(), e_data.end()); // Report progress prog.report(name()); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION // Copy all the axes for (int i = 1; i < inputWS->axes(); i++) { outputWS->replaceAxis(i, inputWS->getAxis(i)->clone(outputWS.get())); outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit(); } // Copy the units over too. for (int i = 0; i < outputWS->axes(); ++i) outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit(); outputWS->setYUnit(inputEventWS->YUnit()); outputWS->setYUnitLabel(inputEventWS->YUnitLabel()); // Assign it to the output workspace property setProperty("OutputWorkspace", outputWS); } return; } else // (inputeventWS != NULL)
/** * Read histogram data * @param histogramEntries map of the file entries that have histogram * @param outputGroup pointer to the workspace group * @param nxFile Reads data from inside first first top entry */ void LoadMcStas::readHistogramData( const std::map<std::string, std::string> &histogramEntries, WorkspaceGroup_sptr &outputGroup, ::NeXus::File &nxFile) { std::string nameAttrValueYLABEL; for (const auto &histogramEntry : histogramEntries) { const std::string &dataName = histogramEntry.first; const std::string &dataType = histogramEntry.second; // open second level entry nxFile.openGroup(dataName, dataType); // grap title to use to e.g. create workspace name std::string nameAttrValueTITLE; nxFile.getAttr("filename", nameAttrValueTITLE); if (nxFile.hasAttr("ylabel")) { nxFile.getAttr("ylabel", nameAttrValueYLABEL); } // Find the axis names auto nxdataEntries = nxFile.getEntries(); std::string axis1Name, axis2Name; for (auto &nxdataEntry : nxdataEntries) { if (nxdataEntry.second == "NXparameters") continue; if (nxdataEntry.first == "ncount") continue; nxFile.openData(nxdataEntry.first); if (nxFile.hasAttr("axis")) { int axisNo(0); nxFile.getAttr("axis", axisNo); if (axisNo == 1) axis1Name = nxdataEntry.first; else if (axisNo == 2) axis2Name = nxdataEntry.first; else throw std::invalid_argument("Unknown axis number"); } nxFile.closeData(); } std::vector<double> axis1Values, axis2Values; nxFile.readData<double>(axis1Name, axis1Values); if (axis2Name.length() == 0) { axis2Name = nameAttrValueYLABEL; axis2Values.push_back(0.0); } else { nxFile.readData<double>(axis2Name, axis2Values); } const size_t axis1Length = axis1Values.size(); const size_t axis2Length = axis2Values.size(); g_log.debug() << "Axis lengths=" << axis1Length << " " << axis2Length << '\n'; // Require "data" field std::vector<double> data; nxFile.readData<double>("data", data); // Optional errors field std::vector<double> errors; try { nxFile.readData<double>("errors", errors); } catch (::NeXus::Exception &) { g_log.information() << "Field " << dataName << " contains no error information.\n"; } // close second level entry nxFile.closeGroup(); MatrixWorkspace_sptr ws = WorkspaceFactory::Instance().create( "Workspace2D", axis2Length, axis1Length, axis1Length); Axis *axis1 = ws->getAxis(0); axis1->title() = axis1Name; // Set caption auto lblUnit = boost::make_shared<Units::Label>(); lblUnit->setLabel(axis1Name, ""); axis1->unit() = lblUnit; Axis *axis2 = new NumericAxis(axis2Length); axis2->title() = axis2Name; // Set caption lblUnit = boost::make_shared<Units::Label>(); lblUnit->setLabel(axis2Name, ""); axis2->unit() = lblUnit; ws->setYUnit(axis2Name); ws->replaceAxis(1, axis2); for (size_t wsIndex = 0; wsIndex < axis2Length; ++wsIndex) { auto &dataY = ws->dataY(wsIndex); auto &dataE = ws->dataE(wsIndex); auto &dataX = ws->dataX(wsIndex); for (size_t j = 0; j < axis1Length; ++j) { // Data is stored in column-major order so we are translating to // row major for Mantid const size_t fileDataIndex = j * axis2Length + wsIndex; dataY[j] = data[fileDataIndex]; dataX[j] = axis1Values[j]; if (!errors.empty()) dataE[j] = errors[fileDataIndex]; } axis2->setValue(wsIndex, axis2Values[wsIndex]); } // set the workspace title ws->setTitle(nameAttrValueTITLE); // use the workspace title to create the workspace name std::replace(nameAttrValueTITLE.begin(), nameAttrValueTITLE.end(), ' ', '_'); // ensure that specified name is given to workspace (eventWS) when added to // outputGroup std::string nameOfGroupWS = getProperty("OutputWorkspace"); std::string nameUserSee = nameAttrValueTITLE + "_" + nameOfGroupWS; std::string extraProperty = "Outputworkspace_dummy_" + std::to_string(m_countNumWorkspaceAdded); declareProperty(Kernel::make_unique<WorkspaceProperty<Workspace>>( extraProperty, nameUserSee, Direction::Output)); setProperty(extraProperty, boost::static_pointer_cast<Workspace>(ws)); m_countNumWorkspaceAdded++; // need to increment to ensure extraProperty are // unique // Make Mantid store the workspace in the group outputGroup->addWorkspace(ws); } nxFile.closeGroup(); } // finish