/** Checks if workspaces input to Q1D or Qxy are reasonable @param dataWS data workspace @param binWS (WavelengthAdj) workpace that will be checked to see if it has one spectrum and the same number of bins as dataWS @param detectWS (PixelAdj) passing NULL for this wont raise an error, if set it will be checked this workspace has as many histograms as dataWS each with one bin @throw invalid_argument if the workspaces are not mututially compatible */ void Qhelper::examineInput(API::MatrixWorkspace_const_sptr dataWS, API::MatrixWorkspace_const_sptr binAdj, API::MatrixWorkspace_const_sptr detectAdj) { if ( dataWS->getNumberHistograms() < 1 ) { throw std::invalid_argument("Empty data workspace passed, can not continue"); } //it is not an error for these workspaces not to exist if (binAdj) { if ( binAdj->getNumberHistograms() != 1 ) { throw std::invalid_argument("The WavelengthAdj workspace must have one spectrum"); } if ( binAdj->readY(0).size() != dataWS->readY(0).size() ) { throw std::invalid_argument("The WavelengthAdj workspace's bins must match those of the detector bank workspace"); } MantidVec::const_iterator reqX = dataWS->readX(0).begin(); MantidVec::const_iterator testX = binAdj->readX(0).begin(); for ( ; reqX != dataWS->readX(0).end(); ++reqX, ++testX) { if ( *reqX != *testX ) { throw std::invalid_argument("The WavelengthAdj workspace must have matching bins with the detector bank workspace"); } } if ( binAdj->isDistribution() != dataWS->isDistribution() ) { throw std::invalid_argument("The distrbution/raw counts status of the wavelengthAdj and DetBankWorkspace must be the same, use ConvertToDistribution"); } } else if( ! dataWS->isDistribution() ) { //throw std::invalid_argument("The data workspace must be a distrbution if there is no Wavelength dependent adjustment"); } if (detectAdj) { if ( detectAdj->blocksize() != 1 ) { throw std::invalid_argument("The PixelAdj workspace must point to a workspace with single bin spectra, as only the first bin is used"); } if ( detectAdj->getNumberHistograms() != dataWS->getNumberHistograms() ) { throw std::invalid_argument("The PixelAdj workspace must have one spectrum for each spectrum in the detector bank workspace"); } } }
/** * 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; }
/** * Return true if the units and distribution-type of the workspaces make them * compatible * @param lhs :: first workspace to check for compatibility * @param rhs :: second workspace to check for compatibility * @return workspace unit compatibility flag */ bool Plus::checkUnitCompatibility( const API::MatrixWorkspace_const_sptr lhs, const API::MatrixWorkspace_const_sptr rhs) const { if (lhs->size() > 1 && rhs->size() > 1) { if (lhs->YUnit() != rhs->YUnit()) { g_log.error("The two workspaces are not compatible because they have " "different units for the data (Y)."); return false; } if (lhs->isDistribution() != rhs->isDistribution()) { g_log.error("The two workspaces are not compatible because one is " "flagged as a distribution."); return false; } } return true; }
/** 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); }
/** 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); }
/** * Calculate the Y and E values for the given possible overlap * @param inputWS :: A pointer to the inputWS * @param newPoly :: A reference to a polygon to test for overlap * @returns A pair of Y and E values */ std::pair<double,double> SofQW2::calculateYE(API::MatrixWorkspace_const_sptr inputWS, const ConvexPolygon & newPoly) const { // Build a list intersection locations in terms of workspace indices // along with corresponding weights from that location std::vector<BinWithWeight> overlaps = findIntersections(inputWS, newPoly); std::pair<double,double> binValues(0,0); if( inputWS->isDistribution() ) { const double newWidth = newPoly[3].X() - newPoly[0].X(); // For distribution binValues = calculateDistYE(inputWS, overlaps, newWidth); } else { binValues = calculateYE(inputWS, overlaps); } return binValues; }
void Multiply::setOutputUnits(const API::MatrixWorkspace_const_sptr lhs,const API::MatrixWorkspace_const_sptr rhs,API::MatrixWorkspace_sptr out) { if ( !lhs->isDistribution() || !rhs->isDistribution() ) out->isDistribution(false); }
/** Checks if workspaces input to Q1D or Qxy are reasonable @param dataWS data workspace @param binAdj (WavelengthAdj) workpace that will be checked to see if it has one spectrum and the same number of bins as dataWS @param detectAdj (PixelAdj) passing NULL for this wont raise an error, if set it will be checked this workspace has as many histograms as dataWS each with one bin @throw invalid_argument if the workspaces are not mututially compatible */ void Qhelper::examineInput(API::MatrixWorkspace_const_sptr dataWS, API::MatrixWorkspace_const_sptr binAdj, API::MatrixWorkspace_const_sptr detectAdj) { if (dataWS->getNumberHistograms() < 1) { throw std::invalid_argument( "Empty data workspace passed, can not continue"); } // it is not an error for these workspaces not to exist if (binAdj) { if (binAdj->getNumberHistograms() != 1) { throw std::invalid_argument( "The WavelengthAdj workspace must have one spectrum"); } if (binAdj->readY(0).size() != dataWS->readY(0).size()) { throw std::invalid_argument("The WavelengthAdj workspace's bins must " "match those of the detector bank workspace"); } MantidVec::const_iterator reqX = dataWS->readX(0).begin(); MantidVec::const_iterator testX = binAdj->readX(0).begin(); for (; reqX != dataWS->readX(0).end(); ++reqX, ++testX) { if (*reqX != *testX) { throw std::invalid_argument("The WavelengthAdj workspace must have " "matching bins with the detector bank " "workspace"); } } if (binAdj->isDistribution() != dataWS->isDistribution()) { throw std::invalid_argument("The distrbution/raw counts status of the " "wavelengthAdj and DetBankWorkspace must be " "the same, use ConvertToDistribution"); } } else if (!dataWS->isDistribution()) { // throw std::invalid_argument("The data workspace must be a distrbution if // there is no Wavelength dependent adjustment"); } // Perform tests on detectAdj if (detectAdj) { if (detectAdj->blocksize() != 1) { throw std::invalid_argument("The PixelAdj workspace must point to a " "workspace with single bin spectra, as only " "the first bin is used"); } if (detectAdj->getNumberHistograms() != dataWS->getNumberHistograms()) { throw std::invalid_argument("The PixelAdj workspace must have one " "spectrum for each spectrum in the detector " "bank workspace"); } // test that when detector adjustment value less than or equal to zero that // the corresponding detector // in the workspace is masked size_t num_histograms = dataWS->getNumberHistograms(); for (size_t i = 0; i < num_histograms; i++) { double adj = (double)detectAdj->readY(i)[0]; if (adj <= 0.0) { bool det_is_masked; try { det_is_masked = dataWS->getDetector(i)->isMasked(); } catch (...) { // just ignore. There are times, when the detector is not masked // because it does not exist at all. det_is_masked = true; } if (!det_is_masked) { throw std::invalid_argument( "Every detector with non-positive PixelAdj value must be masked"); } } } } }
/** 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); }