/** * Return true if the two workspaces are compatible for this operation * Virtual: will be overridden as needed. * @param lhs :: left-hand workspace to check * @param rhs :: right-hand workspace to check * @return flag for the compatibility to the two workspaces */ bool BinaryOperation::checkCompatibility(const API::MatrixWorkspace_const_sptr lhs,const API::MatrixWorkspace_const_sptr rhs) const { Unit_const_sptr lhs_unit; Unit_const_sptr rhs_unit; if ( lhs->axes() && rhs->axes() ) // If one of these is a WorkspaceSingleValue then we don't want to check units match { lhs_unit = lhs->getAxis(0)->unit(); rhs_unit = rhs->getAxis(0)->unit(); } const std::string lhs_unitID = ( lhs_unit ? lhs_unit->unitID() : "" ); const std::string rhs_unitID = ( rhs_unit ? rhs_unit->unitID() : "" ); // Check the workspaces have the same units and distribution flag if ( lhs_unitID != rhs_unitID && lhs->blocksize() > 1 && rhs->blocksize() > 1 ) { g_log.error("The two workspace are not compatible because they have different units on the X axis."); return false; } // Check the size compatibility if (!checkSizeCompatibility(lhs,rhs)) { std::ostringstream ostr; ostr<<"The sizes of the two workspaces " << "(" << lhs->getName() << ": " << lhs->getNumberHistograms() << " spectra, blocksize " << lhs->blocksize() << ")" << " and " << "(" << rhs->getName() << ": " << rhs->getNumberHistograms() << " spectra, blocksize " << rhs->blocksize() << ")" << " are not compatible for algorithm "<<this->name(); g_log.error() << ostr.str() << std::endl; throw std::invalid_argument( ostr.str() ); } return true; }
/** * 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; }
/** * Return true if the two workspaces are compatible for this operation * Virtual: will be overridden as needed. * @param lhs :: left-hand workspace to check * @param rhs :: right-hand workspace to check * @return flag for the compatibility to the two workspaces */ bool BinaryOperation::checkCompatibility( const API::MatrixWorkspace_const_sptr lhs, const API::MatrixWorkspace_const_sptr rhs) const { Unit_const_sptr lhs_unit; Unit_const_sptr rhs_unit; if (lhs->axes() && rhs->axes()) // If one of these is a WorkspaceSingleValue // then we don't want to check units match { lhs_unit = lhs->getAxis(0)->unit(); rhs_unit = rhs->getAxis(0)->unit(); } const std::string lhs_unitID = (lhs_unit ? lhs_unit->unitID() : ""); const std::string rhs_unitID = (rhs_unit ? rhs_unit->unitID() : ""); // Check the workspaces have the same units and distribution flag if (lhs_unitID != rhs_unitID && lhs->blocksize() > 1 && rhs->blocksize() > 1) { g_log.error("The two workspace are not compatible because they have " "different units on the X axis."); return false; } // Check the size compatibility std::string checkSizeCompatibilityResult = checkSizeCompatibility(lhs, rhs); if (!checkSizeCompatibilityResult.empty()) { throw std::invalid_argument(checkSizeCompatibilityResult); } return true; }
/** * 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; }
// internal helper function which extract one or two axis from input matrix // workspace; void MDTransfNoQ::getAxes(API::MatrixWorkspace_const_sptr inWS, API::NumericAxis *&pXAxis, API::NumericAxis *&pYAxis) { // get the X axis of input workspace, it has to be there; if not axis throws // invalid index pXAxis = dynamic_cast<API::NumericAxis *>(inWS->getAxis(0)); if (!pXAxis) { std::string ERR = "Can not retrieve X axis from the source workspace: " + inWS->getName(); throw(std::invalid_argument(ERR)); } // get optional Y axis which can be used in NoQ-kind of algorithms pYAxis = dynamic_cast<API::NumericAxis *>(inWS->getAxis(1)); }
/** Initialization method: @param bkgWS -- shared pointer to the workspace which contains background @param sourceWS -- shared pointer to the workspace to remove background from @param emode -- energy conversion mode used during internal units conversion (0 -- elastic, 1-direct, 2 indirect, as defined in Units conversion @param pLog -- pointer to the logger class which would report errors @param nThreads -- number of threads to be used for background removal @param inPlace -- if the background removal occurs from the existing workspace or target workspace has to be cloned. */ void BackgroundHelper::initialize(const API::MatrixWorkspace_const_sptr &bkgWS, const API::MatrixWorkspace_sptr &sourceWS, int emode, Kernel::Logger *pLog, int nThreads, bool inPlace) { m_bgWs = bkgWS; m_wkWS = sourceWS; m_Emode = emode; m_pgLog = pLog; m_inPlace = inPlace; std::string bgUnits = bkgWS->getAxis(0)->unit()->unitID(); if (bgUnits != "TOF") throw std::invalid_argument(" Background Workspace: " + bkgWS->getName() + " should be in the units of TOF"); if (!(bkgWS->getNumberHistograms() == 1 || sourceWS->getNumberHistograms() == bkgWS->getNumberHistograms())) throw std::invalid_argument(" Background Workspace: " + bkgWS->getName() + " should have the same number of spectra as " "source workspace or be a single histogram " "workspace"); auto WSUnit = sourceWS->getAxis(0)->unit(); if (!WSUnit) throw std::invalid_argument(" Source Workspace: " + sourceWS->getName() + " should have units"); Geometry::IComponent_const_sptr source = sourceWS->getInstrument()->getSource(); m_Sample = sourceWS->getInstrument()->getSample(); if ((!source) || (!m_Sample)) throw std::invalid_argument( "Instrument on Source workspace:" + sourceWS->getName() + "is not sufficiently defined: failed to get source and/or sample"); m_L1 = source->getDistance(*m_Sample); // just in case. this->deleteUnitsConverters(); // allocate the array of units converters to avoid units reallocation within a // loop m_WSUnit.assign(nThreads, NULL); for (int i = 0; i < nThreads; i++) { m_WSUnit[i] = WSUnit->clone(); } m_singleValueBackground = false; if (bkgWS->getNumberHistograms() == 0) m_singleValueBackground = true; const MantidVec &dataX = bkgWS->dataX(0); const MantidVec &dataY = bkgWS->dataY(0); // const MantidVec& dataE = bkgWS->dataE(0); m_NBg = dataY[0]; m_dtBg = dataX[1] - dataX[0]; // m_ErrSq = dataE[0]*dataE[0]; // needs further clarification m_Efix = this->getEi(sourceWS); }
/** Checks that the two input workspace have common binning & size, the same instrument & unit. * Also calls the checkForOverlap method. * @param ws1 :: The first input workspace * @param ws2 :: The second input workspace * @throw std::invalid_argument If the workspaces are not compatible */ void ConjoinWorkspaces::validateInputs(API::MatrixWorkspace_const_sptr ws1, API::MatrixWorkspace_const_sptr ws2) const { // This is the full check for common binning if ( !WorkspaceHelpers::commonBoundaries(ws1) || !WorkspaceHelpers::commonBoundaries(ws2) ) { g_log.error("Both input workspaces must have common binning for all their spectra"); throw std::invalid_argument("Both input workspaces must have common binning for all their spectra"); } if ( ws1->getInstrument()->getName() != ws2->getInstrument()->getName() ) { const std::string message("The input workspaces are not compatible because they come from different instruments"); g_log.error(message); throw std::invalid_argument(message); } Unit_const_sptr ws1_unit = ws1->getAxis(0)->unit(); Unit_const_sptr ws2_unit = ws2->getAxis(0)->unit(); const std::string ws1_unitID = ( ws1_unit ? ws1_unit->unitID() : "" ); const std::string ws2_unitID = ( ws2_unit ? ws2_unit->unitID() : "" ); if ( ws1_unitID != ws2_unitID ) { const std::string message("The input workspaces are not compatible because they have different units on the X axis"); g_log.error(message); throw std::invalid_argument(message); } if ( ws1->isDistribution() != ws2->isDistribution() ) { const std::string message("The input workspaces have inconsistent distribution flags"); g_log.error(message); throw std::invalid_argument(message); } if ( !WorkspaceHelpers::matchingBins(ws1,ws2,true) ) { const std::string message("The input workspaces are not compatible because they have different binning"); g_log.error(message); throw std::invalid_argument(message); } this->checkForOverlap(ws1,ws2, true); }
/** Remove peaks from a input workspace */ Workspace2D_sptr RemovePeaks::removePeaks(API::MatrixWorkspace_const_sptr dataws, int wsindex, double numfwhm) { // Check if (m_vecPeakCentre.empty()) throw runtime_error("RemovePeaks has not been setup yet. "); // Initialize vectors const MantidVec &vecX = dataws->readX(wsindex); const MantidVec &vecY = dataws->readY(wsindex); const MantidVec &vecE = dataws->readE(wsindex); size_t sizex = vecX.size(); vector<bool> vec_useX(sizex, true); // Exclude regions size_t numbkgdpoints = excludePeaks(vecX, vec_useX, m_vecPeakCentre, m_vecPeakFWHM, numfwhm); size_t numbkgdpointsy = numbkgdpoints; size_t sizey = vecY.size(); if (sizex > sizey) --numbkgdpointsy; // Construct output workspace Workspace2D_sptr outws = boost::dynamic_pointer_cast<Workspace2D>( WorkspaceFactory::Instance().create("Workspace2D", 1, numbkgdpoints, numbkgdpointsy)); outws->getAxis(0)->setUnit(dataws->getAxis(0)->unit()->unitID()); MantidVec &outX = outws->dataX(0); MantidVec &outY = outws->dataY(0); MantidVec &outE = outws->dataE(0); size_t index = 0; for (size_t i = 0; i < sizex; ++i) { if (vec_useX[i]) { if (index >= numbkgdpoints) throw runtime_error("Programming logic error (1)"); outX[index] = vecX[i]; ++index; } } index = 0; for (size_t i = 0; i < sizey; ++i) { if (vec_useX[i]) { if (index >= numbkgdpointsy) throw runtime_error("Programming logic error (2)"); outY[index] = vecY[i]; outE[index] = vecE[i]; ++index; } } return outws; }
/** Checks that the axes of the input workspaces match and creates the output * workspace if necessary * @param w1 :: The first input workspace * @param w2 :: The second input workspace * @param out :: Pointer to the output workspace */ void PointByPointVCorrection::check_validity( API::MatrixWorkspace_const_sptr &w1, API::MatrixWorkspace_const_sptr &w2, API::MatrixWorkspace_sptr &out) { // First check that the instrument matches for both input workspaces if (w1->getInstrument()->getName() != w2->getInstrument()->getName()) { g_log.error("The input workspaces have different instrument definitions"); throw std::runtime_error( "The input workspaces have different instrument definitions"); } // Check that the two workspaces are the same size if (w1->size() != w2->size()) { g_log.error("The input workspaces are not the same size"); throw std::runtime_error("The input workspaces are not the same size"); } // Now check that the bins match if (!WorkspaceHelpers::matchingBins(*w1, *w2)) { g_log.error("The input workspaces have different binning"); throw std::runtime_error("The input workspaces have different binning"); } const Mantid::API::Axis *const axis1 = w1->getAxis(1); const Mantid::API::Axis *const axis2 = w2->getAxis(1); if (!((*axis1) == (*axis2))) // Spectra axis are different, so division does // not make any sense { g_log.error( "The two workspaces InputW1 and InputW2 have different spectra list"); throw std::runtime_error( "The two workspaces InputW1 and InputW2 have different spectra list"); } if (out != w1 && out != w2) // Create a new workspace only if it is different // from of the input ones. { out = API::WorkspaceFactory::Instance().create(w1); setProperty("OutputWorkspace", out); } else if (out == w2) { g_log.warning("Any masking in the output workspaces will be taken from the " "vanadium workspace (InputW2)"); } }
/** Initialise the member variables * @param inputWS The input workspace */ void ConvertUnits::setupMemberVariables(const API::MatrixWorkspace_const_sptr inputWS) { m_numberOfSpectra = inputWS->getNumberHistograms(); // In the context of this algorithm, we treat things as a distribution if the flag is set // AND the data are not dimensionless m_distribution = inputWS->isDistribution() && !inputWS->YUnit().empty(); //Check if its an event workspace m_inputEvents = ( boost::dynamic_pointer_cast<const EventWorkspace>(inputWS) != NULL ); m_inputUnit = inputWS->getAxis(0)->unit(); const std::string targetUnit = getPropertyValue("Target"); m_outputUnit = UnitFactory::Instance().create(targetUnit); }
/** returns the units, the input ws is actually in as they coinside with input * units for this class */ const std::string MDTransfNoQ::inputUnitID(Kernel::DeltaEMode::Type mode, API::MatrixWorkspace_const_sptr inWS) const { UNUSED_ARG(mode); API::NumericAxis *pXAxis; // get the X axis of input workspace, it has to be there; if not axis throws // invalid index pXAxis = dynamic_cast<API::NumericAxis *>(inWS->getAxis(0)); if (!pXAxis) { std::string ERR = "Can not retrieve X axis from the source workspace: " + inWS->getName(); throw(std::invalid_argument(ERR)); } return pXAxis->unit()->unitID(); }
/** Checks that the input workspace and table have compatible dimensions * @return a map where: Key = string name of the the property; Value = string * describing the problem with the property. */ std::map<std::string, std::string> PhaseQuadMuon::validateInputs() { std::map<std::string, std::string> result; // Check that input ws and table ws have compatible dimensions API::MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace"); API::ITableWorkspace_const_sptr tabWS = getProperty("PhaseTable"); if (!inputWS) { result["InputWorkspace"] = "InputWorkspace is of Incorrect type. Please " "provide a MatrixWorkspace as the " "InputWorkspace"; return result; } size_t nspec = inputWS->getNumberHistograms(); size_t ndet = tabWS->rowCount(); if (tabWS->columnCount() == 0) { result["PhaseTable"] = "Please provide a non-empty PhaseTable."; } if (nspec != ndet) { result["PhaseTable"] = "PhaseTable must have one row per spectrum"; } // PhaseTable should have three columns: (detector, asymmetry, phase) if (tabWS->columnCount() != 3) { result["PhaseTable"] = "PhaseTable must have three columns"; } // Check units, should be microseconds Unit_const_sptr unit = inputWS->getAxis(0)->unit(); if ((unit->caption() != "Time") || (unit->label().ascii() != "microsecond")) { result["InputWorkspace"] = "InputWorkspace units must be microseconds"; } return result; }
/** Get groupings from XML file * @param fname :: the full path name of the file to open * @param workspace :: a pointer to the input workspace, used to get spectra indexes from numbers * @param unUsedSpec :: the list of spectra indexes that have been included in a group (so far) * @throw FileError if there's any problem with the file or its format */ void GroupDetectors2::processXMLFile(std::string fname, API::MatrixWorkspace_const_sptr workspace, std::vector<int64_t> &unUsedSpec) { // 1. Get maps for spectrum ID and detector ID spec2index_map specs2index; const SpectraAxis* axis = dynamic_cast<const SpectraAxis*>(workspace->getAxis(1)); if (axis) { axis->getSpectraIndexMap(specs2index); } detid2index_map* detIdToWiMap = workspace->getDetectorIDToWorkspaceIndexMap(false); // 2. Load XML file DataHandling::LoadGroupXMLFile loader; loader.setDefaultStartingGroupID(0); loader.loadXMLFile(fname); std::map<int, std::vector<detid_t> > mGroupDetectorsMap = loader.getGroupDetectorsMap(); std::map<int, std::vector<int> > mGroupSpectraMap = loader.getGroupSpectraMap(); // 3. Build m_GroupSpecInds std::map<int, std::vector<detid_t> >::iterator dit; for (dit = mGroupDetectorsMap.begin(); dit != mGroupDetectorsMap.end(); ++ dit) { int groupid = dit->first; std::vector<size_t> tempv; m_GroupSpecInds.insert(std::make_pair(groupid, tempv)); } // 4. Detector IDs for (dit = mGroupDetectorsMap.begin(); dit != mGroupDetectorsMap.end(); ++ dit) { int groupid = dit->first; std::vector<detid_t> detids = dit->second; storage_map::iterator sit; sit = m_GroupSpecInds.find(groupid); if (sit == m_GroupSpecInds.end()) continue; std::vector<size_t>& wsindexes = sit->second; for (size_t i = 0; i < detids.size(); i++) { detid_t detid = detids[i]; detid2index_map::iterator ind =detIdToWiMap->find(detid); if ( ind != detIdToWiMap->end() ) { size_t wsid = ind->second; wsindexes.push_back(wsid); if ( unUsedSpec[wsid] != ( 1000 - INT_MAX ) ) { unUsedSpec[wsid] = ( 1000 - INT_MAX ); } } else { g_log.error() << "Detector with ID " << detid << " is not found in instrument " << std::endl; } } // for index } // for group // 5. Spectrum IDs std::map<int, std::vector<int> >::iterator pit; for (pit = mGroupSpectraMap.begin(); pit != mGroupSpectraMap.end(); ++pit) { int groupid = pit->first; std::vector<int> spectra = pit->second; storage_map::iterator sit; sit = m_GroupSpecInds.find(groupid); if (sit == m_GroupSpecInds.end()) continue; std::vector<size_t>& wsindexes = sit->second; for (size_t i = 0; i < spectra.size(); i++) { int specid = spectra[i]; spec2index_map::iterator ind = specs2index.find(specid); if ( ind != specs2index.end() ) { size_t wsid = ind->second; wsindexes.push_back(wsid); if ( unUsedSpec[wsid] != ( 1000 - INT_MAX ) ) { unUsedSpec[wsid] = ( 1000 - INT_MAX ); } } else { g_log.error() << "Spectrum with ID " << specid<< " is not found in instrument " << std::endl; } } // for index } // for group return; }
/** Read the spectra numbers in from the input file (the file format is in the * source file "GroupDetectors2.h" and make an array of spectra indexes to group * @param fname :: the full path name of the file to open * @param workspace :: a pointer to the input workspace, used to get spectra indexes from numbers * @param unUsedSpec :: the list of spectra indexes that have been included in a group (so far) * @throw FileError if there's any problem with the file or its format */ void GroupDetectors2::processFile(std::string fname, API::MatrixWorkspace_const_sptr workspace, std::vector<int64_t> &unUsedSpec) { // tring to open the file the user told us exists, skip down 20 lines to find out what happens if we can read from it g_log.debug() << "Opening input file ... " << fname; std::ifstream File(fname.c_str(), std::ios::in); std::string firstLine; std::getline( File, firstLine ); // for error reporting keep a count of where we are reading in the file size_t lineNum = 1; if (File.fail()) { g_log.debug() << " file state failbit set after read attempt\n"; throw Exception::FileError("Couldn't read file", fname); } g_log.debug() << " success opening input file " << fname << std::endl; progress(m_FracCompl += OPENINGFILE); // check for a (user) cancel message interruption_point(); // allow spectra number to spectra index look ups spec2index_map specs2index; const SpectraAxis* axis = dynamic_cast<const SpectraAxis*>(workspace->getAxis(1)); if (axis) { axis->getSpectraIndexMap(specs2index); } try { // we don't use the total number of groups report at the top of the file but we'll tell them later if there is a problem with it for their diagnostic purposes int totalNumberOfGroups = readInt(firstLine); // Reading file now ... while ( totalNumberOfGroups == EMPTY_LINE ) { if ( ! File ) throw Exception::FileError("The input file doesn't appear to contain any data", fname); std::getline( File, firstLine ), lineNum ++; totalNumberOfGroups = readInt(firstLine); } readFile(specs2index, File, lineNum, unUsedSpec); if ( m_GroupSpecInds.size() != static_cast<size_t>(totalNumberOfGroups) ) { g_log.warning() << "The input file header states there are " << totalNumberOfGroups << " but the file contains " << m_GroupSpecInds.size() << " groups\n"; } } // add some more info to the error messages, including the line number, to help users correct their files. These problems should cause the algorithm to stop catch (std::invalid_argument &e) { g_log.debug() << "Exception thrown: " << e.what() << std::endl; File.close(); std::string error(e.what() + std::string(" near line number ") + boost::lexical_cast<std::string>(lineNum)); if (File.fail()) { error = "Input output error while reading file "; } throw Exception::FileError(error, fname); } catch (boost::bad_lexical_cast &e) { g_log.debug() << "Exception thrown: " << e.what() << std::endl; File.close(); std::string error(std::string("Problem reading integer value \"") + e.what() + std::string("\" near line number ") + boost::lexical_cast<std::string>(lineNum)); if (File.fail()) { error = "Input output error while reading file "; } throw Exception::FileError(error, fname); } File.close(); g_log.debug() << "Closed file " << fname << " after reading in " << m_GroupSpecInds.size() << " groups\n"; m_FracCompl += fileReadProg( m_GroupSpecInds.size(), specs2index.size() ); return; }
/** Checks that the input workspace and table have compatible dimensions * @return a map where: Key = string name of the the property; Value = string * describing the problem with the property. */ std::map<std::string, std::string> PhaseQuadMuon::validateInputs() { std::map<std::string, std::string> result; // Check that input ws and table ws have compatible dimensions API::MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace"); API::ITableWorkspace_const_sptr tabWS = getProperty("PhaseTable"); if (!inputWS) { result["InputWorkspace"] = "InputWorkspace is of Incorrect type. Please " "provide a MatrixWorkspace as the " "InputWorkspace"; return result; } size_t nspec = inputWS->getNumberHistograms(); size_t ndet = tabWS->rowCount(); if (tabWS->columnCount() == 0) { result["PhaseTable"] = "Please provide a non-empty PhaseTable."; } if (nspec != ndet) { result["PhaseTable"] = "PhaseTable must have one row per spectrum"; } // PhaseTable should have three columns: (detector, asymmetry, phase) if (tabWS->columnCount() != 3) { result["PhaseTable"] = "PhaseTable must have three columns"; } auto names = tabWS->getColumnNames(); for (auto &name : names) { std::transform(name.begin(), name.end(), name.begin(), ::tolower); } int phaseCount = 0; int asymmetryCount = 0; for (const std::string &name : names) { for (const std::string &goodName : phaseNames) { if (name == goodName) { phaseCount += 1; } } for (const std::string &goodName : asymmNames) { if (name == goodName) { asymmetryCount += 1; } } } if (phaseCount == 0) { result["PhaseTable"] = "PhaseTable needs phases column"; } if (asymmetryCount == 0) { result["PhaseTable"] = "PhaseTable needs a asymmetry/asymm/asym column"; } if (phaseCount > 1) { result["PhaseTable"] = "PhaseTable has " + std::to_string(phaseCount) + " phase columns"; } if (asymmetryCount > 1) { result["PhaseTable"] = "PhaseTable has " + std::to_string(asymmetryCount) + " asymmetry/asymm/asym columns"; } // Check units, should be microseconds Unit_const_sptr unit = inputWS->getAxis(0)->unit(); if ((unit->caption() != "Time") || (unit->label().ascii() != "microsecond")) { result["InputWorkspace"] = "InputWorkspace units must be microseconds"; } return result; }
/** Write out a MatrixWorkspace's data as a 2D matrix. * Use writeNexusProcessedDataEvent if writing an EventWorkspace. */ int NexusFileIO::writeNexusProcessedData2D( const API::MatrixWorkspace_const_sptr& localworkspace, const bool& uniformSpectra, const std::vector<int>& spec, const char * group_name, bool write2Ddata) const { NXstatus status; //write data entry status=NXmakegroup(fileID,group_name,"NXdata"); if(status==NX_ERROR) return(2); NXopengroup(fileID,group_name,"NXdata"); // write workspace data const size_t nHist=localworkspace->getNumberHistograms(); if(nHist<1) return(2); const size_t nSpectBins=localworkspace->readY(0).size(); const size_t nSpect=spec.size(); int dims_array[2] = { static_cast<int>(nSpect),static_cast<int>(nSpectBins) }; // Set the axis labels and values Mantid::API::Axis *xAxis=localworkspace->getAxis(0); Mantid::API::Axis *sAxis=localworkspace->getAxis(1); std::string xLabel,sLabel; if ( xAxis->isSpectra() ) xLabel = "spectraNumber"; else { if ( xAxis->unit() ) xLabel = xAxis->unit()->unitID(); else xLabel = "unknown"; } if ( sAxis->isSpectra() ) sLabel = "spectraNumber"; else { if ( sAxis->unit() ) sLabel = sAxis->unit()->unitID(); else sLabel = "unknown"; } // Get the values on the vertical axis std::vector<double> axis2; if (nSpect < nHist) for (size_t i=0;i<nSpect;i++) axis2.push_back((*sAxis)(spec[i])); else for (size_t i=0;i<sAxis->length();i++) axis2.push_back((*sAxis)(i)); int start[2]={0,0}; int asize[2]={1,dims_array[1]}; // -------------- Actually write the 2D data ---------------------------- if (write2Ddata) { std::string name="values"; NXcompmakedata(fileID, name.c_str(), NX_FLOAT64, 2, dims_array,m_nexuscompression,asize); NXopendata(fileID, name.c_str()); for(size_t i=0;i<nSpect;i++) { int s = spec[i]; NXputslab(fileID, reinterpret_cast<void*>(const_cast<double*>(&(localworkspace->readY(s)[0]))),start,asize); start[0]++; } if(m_progress != 0) m_progress->reportIncrement(1, "Writing data"); int signal=1; NXputattr (fileID, "signal", &signal, 1, NX_INT32); // More properties const std::string axesNames="axis2,axis1"; NXputattr (fileID, "axes", reinterpret_cast<void*>(const_cast<char*>(axesNames.c_str())), static_cast<int>(axesNames.size()), NX_CHAR); std::string yUnits=localworkspace->YUnit(); std::string yUnitLabel=localworkspace->YUnitLabel(); NXputattr (fileID, "units", reinterpret_cast<void*>(const_cast<char*>(yUnits.c_str())), static_cast<int>(yUnits.size()), NX_CHAR); NXputattr (fileID, "unit_label", reinterpret_cast<void*>(const_cast<char*>(yUnitLabel.c_str())), static_cast<int>(yUnitLabel.size()), NX_CHAR); NXclosedata(fileID); // error name="errors"; NXcompmakedata(fileID, name.c_str(), NX_FLOAT64, 2, dims_array,m_nexuscompression,asize); NXopendata(fileID, name.c_str()); start[0]=0; for(size_t i=0;i<nSpect;i++) { int s = spec[i]; NXputslab(fileID, reinterpret_cast<void*>(const_cast<double*>(&(localworkspace->readE(s)[0]))),start,asize); start[0]++; } if(m_progress != 0) m_progress->reportIncrement(1, "Writing data"); // Fractional area for RebinnedOutput if (localworkspace->id() == "RebinnedOutput") { RebinnedOutput_const_sptr rebin_workspace = boost::dynamic_pointer_cast<const RebinnedOutput>(localworkspace); name="frac_area"; NXcompmakedata(fileID, name.c_str(), NX_FLOAT64, 2, dims_array,m_nexuscompression,asize); NXopendata(fileID, name.c_str()); start[0]=0; for(size_t i=0;i<nSpect;i++) { int s = spec[i]; NXputslab(fileID, reinterpret_cast<void*>(const_cast<double*>(&(rebin_workspace->readF(s)[0]))), start, asize); start[0]++; } if(m_progress != 0) m_progress->reportIncrement(1, "Writing data"); } NXclosedata(fileID); } // write X data, as single array or all values if "ragged" if(uniformSpectra) { dims_array[0]=static_cast<int>(localworkspace->readX(0).size()); NXmakedata(fileID, "axis1", NX_FLOAT64, 1, dims_array); NXopendata(fileID, "axis1"); NXputdata(fileID, reinterpret_cast<void*>(const_cast<double*>(&(localworkspace->readX(0)[0])))); } else { dims_array[0]=static_cast<int>(nSpect); dims_array[1]=static_cast<int>(localworkspace->readX(0).size()); NXmakedata(fileID, "axis1", NX_FLOAT64, 2, dims_array); NXopendata(fileID, "axis1"); start[0]=0; asize[1]=dims_array[1]; for(size_t i=0;i<nSpect;i++) { NXputslab(fileID, reinterpret_cast<void*>(const_cast<double*>(&(localworkspace->readX(i)[0]))),start,asize); start[0]++; } } std::string dist=(localworkspace->isDistribution()) ? "1" : "0"; NXputattr(fileID, "distribution", reinterpret_cast<void*>(const_cast<char*>(dist.c_str())), 2, NX_CHAR); NXputattr (fileID, "units", reinterpret_cast<void*>(const_cast<char*>(xLabel.c_str())), static_cast<int>(xLabel.size()), NX_CHAR); auto label = boost::dynamic_pointer_cast<Mantid::Kernel::Units::Label>(xAxis->unit()); if(label) { NXputattr (fileID, "caption", reinterpret_cast<void*>(const_cast<char*>(label->caption().c_str())), static_cast<int>(label->caption().size()), NX_CHAR); auto unitLbl = label->label(); NXputattr (fileID, "label", reinterpret_cast<void*>(const_cast<char*>(unitLbl.ascii().c_str())), static_cast<int>(unitLbl.ascii().size()), NX_CHAR); } NXclosedata(fileID); if ( ! sAxis->isText() ) { // write axis2, maybe just spectra number dims_array[0]=static_cast<int>(axis2.size()); NXmakedata(fileID, "axis2", NX_FLOAT64, 1, dims_array); NXopendata(fileID, "axis2"); NXputdata(fileID, (void*)&(axis2[0])); NXputattr (fileID, "units", reinterpret_cast<void*>(const_cast<char*>(sLabel.c_str())), static_cast<int>(sLabel.size()), NX_CHAR); auto label = boost::dynamic_pointer_cast<Mantid::Kernel::Units::Label>(sAxis->unit()); if(label) { NXputattr (fileID, "caption", reinterpret_cast<void*>(const_cast<char*>(label->caption().c_str())), static_cast<int>(label->caption().size()), NX_CHAR); auto unitLbl = label->label(); NXputattr (fileID, "label", reinterpret_cast<void*>(const_cast<char*>(unitLbl.ascii().c_str())), static_cast<int>(unitLbl.ascii().size()), NX_CHAR); } NXclosedata(fileID); } else { std::string textAxis; for ( size_t i = 0; i < sAxis->length(); i ++ ) { std::string label = sAxis->label(i); textAxis += label + "\n"; } dims_array[0] = static_cast<int>(textAxis.size()); NXmakedata(fileID, "axis2", NX_CHAR, 2, dims_array); NXopendata(fileID, "axis2"); NXputdata(fileID, reinterpret_cast<void*>(const_cast<char*>(textAxis.c_str()))); NXputattr (fileID, "units", reinterpret_cast<void*>(const_cast<char*>("TextAxis")), 8, NX_CHAR); auto label = boost::dynamic_pointer_cast<Mantid::Kernel::Units::Label>(sAxis->unit()); if(label) { NXputattr (fileID, "caption", reinterpret_cast<void*>(const_cast<char*>(label->caption().c_str())), static_cast<int>(label->caption().size()), NX_CHAR); auto unitLbl = label->label(); NXputattr (fileID, "label", reinterpret_cast<void*>(const_cast<char*>(unitLbl.ascii().c_str())), static_cast<int>(unitLbl.ascii().size()), NX_CHAR); } NXclosedata(fileID); } writeNexusBinMasking(localworkspace); status=NXclosegroup(fileID); return((status==NX_ERROR)?3:0); }