/** Read a data file that contains only one spectrum into a workspace * @return the new workspace */ const API::MatrixWorkspace_sptr LoadRKH::read1D() { g_log.information() << "file appears to contain 1D information, reading in 1D data mode\n"; // The 3rd line contains information regarding the number of points in the // file and // start and end reading points int totalPoints(0), readStart(0), readEnd(0), buried(0); std::string fileline; getline(m_fileIn, fileline); std::istringstream is(fileline); // Get data information for (int counter = 1; counter < 8; ++counter) { switch (counter) { case 1: is >> totalPoints; break; case 5: is >> readStart; break; case 6: is >> readEnd; break; default: is >> buried; break; } } g_log.information() << "Total number of data points declared to be in the data file: " << totalPoints << "\n"; // What are we reading? std::string firstColVal = getProperty("FirstColumnValue"); bool colIsUnit(true); if (m_RKHKeys.find(firstColVal) != m_RKHKeys.end()) { colIsUnit = false; readStart = 1; readEnd = totalPoints; } if (readStart < 1 || readEnd < 1 || readEnd < readStart || readStart > totalPoints || readEnd > totalPoints) { g_log.error("Invalid data range specfied."); m_fileIn.close(); throw std::invalid_argument("Invalid data range specfied."); } g_log.information() << "Reading started on data line: " << readStart << "\n"; g_log.information() << "Reading finished on data line: " << readEnd << "\n"; // The 4th and 5th line do not contain useful information either skipLines(m_fileIn, 2); int pointsToRead = readEnd - readStart + 1; // Now stream sits at the first line of data std::vector<double> columnOne, ydata, errdata, xError; columnOne.reserve(readEnd); ydata.reserve(readEnd); errdata.reserve(readEnd); auto hasXError = hasXerror(m_fileIn); Progress prog(this, 0.0, 1.0, readEnd); if (hasXError) { xError.reserve(readEnd); readLinesWithXErrorForRKH1D(m_fileIn, readStart, readEnd, columnOne, ydata, errdata, xError, prog); } else { readLinesForRKH1D(m_fileIn, readStart, readEnd, columnOne, ydata, errdata, prog); } m_fileIn.close(); assert(pointsToRead == static_cast<int>(columnOne.size())); assert(pointsToRead == static_cast<int>(ydata.size())); assert(pointsToRead == static_cast<int>(errdata.size())); if (hasXError) { assert(pointsToRead == static_cast<int>(xError.size())); } if (colIsUnit) { MatrixWorkspace_sptr localworkspace = WorkspaceFactory::Instance().create( "Workspace2D", 1, pointsToRead, pointsToRead); localworkspace->getAxis(0)->unit() = UnitFactory::Instance().create(firstColVal); localworkspace->dataX(0) = columnOne; localworkspace->dataY(0) = ydata; localworkspace->dataE(0) = errdata; if (hasXError) { localworkspace->dataDx(0) = xError; } return localworkspace; } else { MatrixWorkspace_sptr localworkspace = WorkspaceFactory::Instance().create("Workspace2D", pointsToRead, 1, 1); // Set the appropriate values for (int index = 0; index < pointsToRead; ++index) { localworkspace->getSpectrum(index) .setSpectrumNo(static_cast<int>(columnOne[index])); localworkspace->dataY(index)[0] = ydata[index]; localworkspace->dataE(index)[0] = errdata[index]; } if (hasXError) { for (int index = 0; index < pointsToRead; ++index) { localworkspace->dataDx(index)[0] = xError[index]; } } return localworkspace; } }
/** * Reads the data from the file. It is assumed that the provided file stream has its position * set such that the first call to getline will be give the first line of data * @param file :: A reference to a file stream * @returns A pointer to a new workspace */ API::Workspace_sptr LoadAscii::readData(std::ifstream & file) const { // Get the first line and find the number of spectra from the number of columns std::string line; getline(file,line); boost::trim(line); std::list<std::string> columns; const int numCols = splitIntoColumns(columns, line); if( numCols < 2 ) { g_log.error() << "Invalid data format found in file \"" << getPropertyValue("Filename") << "\"\n"; throw std::runtime_error("Invalid data format. Fewer than 2 columns found."); } size_t numSpectra(0); bool haveErrors(false); bool haveXErrors(false); // Assume single data set with no errors if( numCols == 2 ) { numSpectra = numCols/2; } // Data with errors else if( (numCols-1) % 2 == 0 ) { numSpectra = (numCols - 1)/2; haveErrors = true; } // Data with errors on both X and Y (4-column file) else if( numCols == 4 ) { numSpectra = 1; haveErrors = true; haveXErrors = true; } else { g_log.error() << "Invalid data format found in file \"" << getPropertyValue("Filename") << "\"\n"; g_log.error() << "LoadAscii requires the number of columns to be an even multiple of either 2 or 3."; throw std::runtime_error("Invalid data format."); } // A quick check at the number of lines won't be accurate enough as potentially there // could be blank lines and comment lines int numBins(0), lineNo(0); std::vector<DataObjects::Histogram1D> spectra(numSpectra); std::vector<double> values(numCols, 0.); do { ++lineNo; boost::trim(line); if( this->skipLine(line) ) continue; columns.clear(); int lineCols = this->splitIntoColumns(columns, line); if( lineCols != numCols ) { std::ostringstream ostr; ostr << "Number of columns changed at line " << lineNo; throw std::runtime_error(ostr.str()); } try { fillInputValues(values, columns); //ignores nans and replaces them with 0 } catch(boost::bad_lexical_cast&) { g_log.error() << "Invalid value on line " << lineNo << " of \"" << getPropertyValue("Filename") << "\"\n"; throw std::runtime_error("Invalid value encountered."); } for (size_t i = 0; i < numSpectra; ++i) { spectra[i].dataX().push_back(values[0]); spectra[i].dataY().push_back(values[i*2+1]); if( haveErrors ) { spectra[i].dataE().push_back(values[i*2+2]); } if( haveXErrors ) { // Note: we only have X errors with 4-column files. // We are only here when i=0. spectra[i].dataDx().push_back(values[3]); } } ++numBins; } while(getline(file,line)); MatrixWorkspace_sptr localWorkspace = boost::dynamic_pointer_cast<MatrixWorkspace> (WorkspaceFactory::Instance().create("Workspace2D",numSpectra,numBins,numBins)); try { localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create(getProperty("Unit")); } catch (Exception::NotFoundError&) { // Asked for dimensionless workspace (obviously not in unit factory) } for (size_t i = 0; i < numSpectra; ++i) { localWorkspace->dataX(i) = spectra[i].dataX(); localWorkspace->dataY(i) = spectra[i].dataY(); /* If Y or E errors are not there, DON'T copy across as the 'spectra' vectors have not been filled above. The workspace will by default have vectors of the right length filled with zeroes. */ if ( haveErrors ) localWorkspace->dataE(i) = spectra[i].dataE(); if ( haveXErrors ) localWorkspace->dataDx(i) = spectra[i].dataDx(); // Just have spectrum number start at 1 and count up localWorkspace->getSpectrum(i)->setSpectrumNo(static_cast<specid_t>(i)+1); } return localWorkspace; }
/// Execute the algorithm in case of a histogrammed data. void ExtractSpectra::execHistogram() { m_histogram = m_inputWorkspace->isHistogramData(); // Check for common boundaries in input workspace m_commonBoundaries = WorkspaceHelpers::commonBoundaries(m_inputWorkspace); // Retrieve and validate the input properties this->checkProperties(); // Create the output workspace MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create( m_inputWorkspace, m_workspaceIndexList.size(), m_maxX - m_minX, m_maxX - m_minX - m_histogram); // If this is a Workspace2D, get the spectra axes for copying in the spectraNo // later Axis *inAxis1(nullptr); TextAxis *outTxtAxis(nullptr); NumericAxis *outNumAxis(nullptr); if (m_inputWorkspace->axes() > 1) { inAxis1 = m_inputWorkspace->getAxis(1); auto outAxis1 = outputWorkspace->getAxis(1); outTxtAxis = dynamic_cast<TextAxis *>(outAxis1); if (!outTxtAxis) outNumAxis = dynamic_cast<NumericAxis *>(outAxis1); } cow_ptr<MantidVec> newX; if (m_commonBoundaries) { const MantidVec &oldX = m_inputWorkspace->readX(m_workspaceIndexList.front()); newX.access().assign(oldX.begin() + m_minX, oldX.begin() + m_maxX); } Progress prog(this, 0.0, 1.0, (m_workspaceIndexList.size())); // Loop over the required workspace indices, copying in the desired bins for (int j = 0; j < static_cast<int>(m_workspaceIndexList.size()); ++j) { auto i = m_workspaceIndexList[j]; bool hasDx = m_inputWorkspace->hasDx(i); // Preserve/restore sharing if X vectors are the same if (m_commonBoundaries) { outputWorkspace->setX(j, newX); if (hasDx) { const MantidVec &oldDx = m_inputWorkspace->readDx(i); outputWorkspace->dataDx(j) .assign(oldDx.begin() + m_minX, oldDx.begin() + m_maxX); } } else { // Safe to just copy whole vector 'cos can't be cropping in X if not // common outputWorkspace->setX(j, m_inputWorkspace->refX(i)); if (hasDx) { outputWorkspace->setDx(j, m_inputWorkspace->refDx(i)); } } const MantidVec &oldY = m_inputWorkspace->readY(i); outputWorkspace->dataY(j) .assign(oldY.begin() + m_minX, oldY.begin() + (m_maxX - m_histogram)); const MantidVec &oldE = m_inputWorkspace->readE(i); outputWorkspace->dataE(j) .assign(oldE.begin() + m_minX, oldE.begin() + (m_maxX - m_histogram)); // copy over the axis entry for each spectrum, regardless of the type of // axes present if (inAxis1) { if (outTxtAxis) { outTxtAxis->setLabel(j, inAxis1->label(i)); } else if (outNumAxis) { outNumAxis->setValue(j, inAxis1->operator()(i)); } // spectra axis is handled by copyInfoFrom line } // Copy spectrum number & detectors outputWorkspace->getSpectrum(j) ->copyInfoFrom(*m_inputWorkspace->getSpectrum(i)); if (!m_commonBoundaries) this->cropRagged(outputWorkspace, static_cast<int>(i), j); // Propagate bin masking if there is any if (m_inputWorkspace->hasMaskedBins(i)) { const MatrixWorkspace::MaskList &inputMasks = m_inputWorkspace->maskedBins(i); MatrixWorkspace::MaskList::const_iterator it; for (it = inputMasks.begin(); it != inputMasks.end(); ++it) { const size_t maskIndex = (*it).first; if (maskIndex >= m_minX && maskIndex < m_maxX - m_histogram) outputWorkspace->flagMasked(j, maskIndex - m_minX, (*it).second); } } prog.report(); } setProperty("OutputWorkspace", outputWorkspace); }