/**Convert a binned workspace to point data * * @param workspace :: The input workspace * @return the converted workspace containing point data */ MatrixWorkspace_sptr SplineInterpolation::convertBinnedData(MatrixWorkspace_sptr workspace) const { if (workspace->isHistogramData()) { const size_t histNo = workspace->getNumberHistograms(); const size_t size = workspace->y(0).size(); // make a new workspace for the point data MatrixWorkspace_sptr pointWorkspace = WorkspaceFactory::Instance().create(workspace, histNo, size, size); // loop over each histogram for (size_t i = 0; i < histNo; ++i) { const auto &xValues = workspace->x(i); pointWorkspace->setSharedY(i, workspace->sharedY(i)); auto &newXValues = pointWorkspace->mutableX(i); // set x values to be average of bin bounds for (size_t j = 0; j < size; ++j) { newXValues[j] = (xValues[j] + xValues[j + 1]) / 2; } } return pointWorkspace; } return workspace; }
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); }
/** 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; } }
/** * Read histogram data * @param histogramEntries map of the file entries that have histogram * @param nxFile Reads data from inside first first top entry * @return Names of workspaces to include in output group */ std::vector<std::string> LoadMcStas::readHistogramData( const std::map<std::string, std::string> &histogramEntries, ::NeXus::File &nxFile) { std::string nameAttrValueYLABEL; std::vector<std::string> histoWSNames; 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; std::vector<double> 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 &dataX = ws->mutableX(wsIndex); auto &dataY = ws->mutableY(wsIndex); auto &dataE = ws->mutableE(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; dataX[j] = axis1Values[j]; dataY[j] = data[fileDataIndex]; 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 const std::string outputWS = getProperty("OutputWorkspace"); const std::string nameUserSee = nameAttrValueTITLE + "_" + outputWS; AnalysisDataService::Instance().addOrReplace(nameUserSee, ws); histoWSNames.emplace_back(ws->getName()); } nxFile.closeGroup(); return histoWSNames; } // finish
/** Convert the workspace units using TOF as an intermediate step in the * conversion * @param fromUnit :: The unit of the input workspace * @param inputWS :: The input workspace * @returns A shared pointer to the output workspace */ MatrixWorkspace_sptr ConvertUnitsUsingDetectorTable::convertViaTOF( Kernel::Unit_const_sptr fromUnit, API::MatrixWorkspace_const_sptr inputWS) { using namespace Geometry; // Let's see if we are using a TableWorkspace to override parameters TableWorkspace_sptr paramWS = getProperty("DetectorParameters"); // See if we have supplied a DetectorParameters Workspace // TODO: Check if paramWS is NULL and if so throw an exception // const std::string l1ColumnLabel("l1"); // Let's check all the columns exist and are readable try { auto spectraColumnTmp = paramWS->getColumn("spectra"); auto l1ColumnTmp = paramWS->getColumn("l1"); auto l2ColumnTmp = paramWS->getColumn("l2"); auto twoThetaColumnTmp = paramWS->getColumn("twotheta"); auto efixedColumnTmp = paramWS->getColumn("efixed"); auto emodeColumnTmp = paramWS->getColumn("emode"); } catch (...) { throw Exception::InstrumentDefinitionError( "DetectorParameter TableWorkspace is not defined correctly."); } // Now let's take a reference to the vectors. const auto &l1Column = paramWS->getColVector<double>("l1"); const auto &l2Column = paramWS->getColVector<double>("l2"); const auto &twoThetaColumn = paramWS->getColVector<double>("twotheta"); const auto &efixedColumn = paramWS->getColVector<double>("efixed"); const auto &emodeColumn = paramWS->getColVector<int>("emode"); const auto &spectraColumn = paramWS->getColVector<int>("spectra"); Progress prog(this, 0.2, 1.0, m_numberOfSpectra); int64_t numberOfSpectra_i = static_cast<int64_t>(m_numberOfSpectra); // cast to make openmp happy // Get the unit object for each workspace Kernel::Unit_const_sptr outputUnit = m_outputUnit; std::vector<double> emptyVec; int failedDetectorCount = 0; // Perform Sanity Validation before creating workspace size_t checkIndex = 0; int checkSpecNo = inputWS->getDetector(checkIndex)->getID(); auto checkSpecIter = std::find(spectraColumn.begin(), spectraColumn.end(), checkSpecNo); if (checkSpecIter != spectraColumn.end()) { size_t detectorRow = std::distance(spectraColumn.begin(), checkSpecIter); // copy the X values for the check auto checkXValues = inputWS->readX(checkIndex); // Convert the input unit to time-of-flight auto checkFromUnit = std::unique_ptr<Unit>(fromUnit->clone()); auto checkOutputUnit = std::unique_ptr<Unit>(outputUnit->clone()); double checkdelta = 0; checkFromUnit->toTOF(checkXValues, emptyVec, l1Column[detectorRow], l2Column[detectorRow], twoThetaColumn[detectorRow], emodeColumn[detectorRow], efixedColumn[detectorRow], checkdelta); // Convert from time-of-flight to the desired unit checkOutputUnit->fromTOF(checkXValues, emptyVec, l1Column[detectorRow], l2Column[detectorRow], twoThetaColumn[detectorRow], emodeColumn[detectorRow], efixedColumn[detectorRow], checkdelta); } // create the output workspace MatrixWorkspace_sptr outputWS = this->setupOutputWorkspace(inputWS); EventWorkspace_sptr eventWS = boost::dynamic_pointer_cast<EventWorkspace>(outputWS); assert(static_cast<bool>(eventWS) == m_inputEvents); // Sanity check // TODO: Check why this parallel stuff breaks // Loop over the histograms (detector spectra) // PARALLEL_FOR_IF(Kernel::threadSafe(*outputWS)) for (int64_t i = 0; i < numberOfSpectra_i; ++i) { // Lets find what row this spectrum Number appears in our detector table. // PARALLEL_START_INTERUPT_REGION std::size_t wsid = i; try { double deg2rad = M_PI / 180.; auto det = outputWS->getDetector(i); int specNo = det->getID(); // int spectraNumber = static_cast<int>(spectraColumn->toDouble(i)); // wsid = outputWS->getIndexFromSpectrumNumber(spectraNumber); g_log.debug() << "###### Spectra #" << specNo << " ==> Workspace ID:" << wsid << '\n'; // Now we need to find the row that contains this spectrum std::vector<int>::const_iterator specIter; specIter = std::find(spectraColumn.begin(), spectraColumn.end(), specNo); if (specIter != spectraColumn.end()) { const size_t detectorRow = std::distance(spectraColumn.begin(), specIter); const double l1 = l1Column[detectorRow]; const double l2 = l2Column[detectorRow]; const double twoTheta = twoThetaColumn[detectorRow] * deg2rad; const double efixed = efixedColumn[detectorRow]; const int emode = emodeColumn[detectorRow]; if (g_log.is(Logger::Priority::PRIO_DEBUG)) { g_log.debug() << "specNo from detector table = " << spectraColumn[detectorRow] << '\n'; g_log.debug() << "###### Spectra #" << specNo << " ==> Det Table Row:" << detectorRow << '\n'; g_log.debug() << "\tL1=" << l1 << ",L2=" << l2 << ",TT=" << twoTheta << ",EF=" << efixed << ",EM=" << emode << '\n'; } // Make local copies of the units. This allows running the loop in // parallel auto localFromUnit = std::unique_ptr<Unit>(fromUnit->clone()); auto localOutputUnit = std::unique_ptr<Unit>(outputUnit->clone()); /// @todo Don't yet consider hold-off (delta) const double delta = 0.0; std::vector<double> values(outputWS->x(wsid).begin(), outputWS->x(wsid).end()); // Convert the input unit to time-of-flight localFromUnit->toTOF(values, emptyVec, l1, l2, twoTheta, emode, efixed, delta); // Convert from time-of-flight to the desired unit localOutputUnit->fromTOF(values, emptyVec, l1, l2, twoTheta, emode, efixed, delta); outputWS->mutableX(wsid) = std::move(values); // EventWorkspace part, modifying the EventLists. if (m_inputEvents) { eventWS->getSpectrum(wsid) .convertUnitsViaTof(localFromUnit.get(), localOutputUnit.get()); } } else { // Not found failedDetectorCount++; outputWS->maskWorkspaceIndex(wsid); } } catch (Exception::NotFoundError &) { // Get to here if exception thrown when calculating distance to detector failedDetectorCount++; // Since you usually (always?) get to here when there's no attached // detectors, this call is // the same as just zeroing out the data (calling clearData on the // spectrum) outputWS->maskWorkspaceIndex(i); } prog.report("Convert to " + m_outputUnit->unitID()); // PARALLEL_END_INTERUPT_REGION } // loop over spectra // PARALLEL_CHECK_INTERUPT_REGION if (failedDetectorCount != 0) { g_log.information() << "Something went wrong for " << failedDetectorCount << " spectra. Masking spectrum.\n"; } if (m_inputEvents) eventWS->clearMRU(); return outputWS; }