Exemplo n.º 1
0
/** The function expects that the string passed to it contains a series of integers,
*  ranges specified with a '-' are possible
*  @param line :: a line read from the file, we'll interpret this
*  @param specs2index :: a map with spectra numbers as indexes and index numbers as values
*  @param output :: the list of integers, with any ranges expanded
*  @param unUsedSpec :: the list of spectra indexes that have been included in a group (so far)
*  @param seperator :: the symbol for the index range separator
*  @throw invalid_argument when a number couldn't be found or the number is not in the spectra map
*/
void GroupDetectors2::readSpectraIndexes(std::string line, spec2index_map &specs2index,
    std::vector<size_t> &output, std::vector<int64_t> &unUsedSpec, std::string seperator)
{
  // remove comments and white space
  Poco::StringTokenizer dataComment(line, seperator, IGNORE_SPACES);
  Poco::StringTokenizer::Iterator iend = dataComment.end();
  for( Poco::StringTokenizer::Iterator itr = dataComment.begin(); itr != iend; ++itr )
  {
    std::vector<size_t> specNums;
    specNums.reserve(output.capacity());

    RangeHelper::getList(*itr, specNums);

    std::vector<size_t>::const_iterator specN = specNums.begin();
    for( ;specN!=specNums.end(); ++specN)
    {
      specid_t spectrumNum = static_cast<specid_t>(*specN);
      spec2index_map::const_iterator ind = specs2index.find(spectrumNum);
      if ( ind == specs2index.end() )
      {
        g_log.debug() << name() << ": spectrum number " << spectrumNum << " refered to in the input file was not found in the input workspace\n";
        throw std::invalid_argument("Spectrum number " + boost::lexical_cast<std::string>(spectrumNum) + " not found");
      } 
      if ( unUsedSpec[ind->second] != USED )
      {// this array is used when the user sets KeepUngroupedSpectra, as well as to find duplicates
        unUsedSpec[ind->second] = USED;
        output.push_back( ind->second );
      }
      else
      {// the spectra was already included in a group
        output.push_back( ind->second );
      }
    }
  }
}
Exemplo n.º 2
0
/** Set the mask on the spectrum numbers or convert them to detector-s id if
 *  sample workspace is provided
 *@param  mask           -- to mask or unmask appropriate spectra
 *@param maskedSpecID    -- vector of the spectra numbers to process
 *@param singleDetIds    -- vector of det-id-s to extend if workspace-
 *                          source of spectra-detector map is provided
 */
void LoadMask::processMaskOnWorkspaceIndex(bool mask,
                                           std::vector<int32_t> &maskedSpecID,
                                           std::vector<int32_t> &singleDetIds) {
  // 1. Check
  if (maskedSpecID.empty())
    return;

  if (m_sourceMapWS) {
    // convert spectra masks into det-id mask using source workspace
    convertSpMasksToDetIDs(*m_sourceMapWS, maskedSpecID, singleDetIds);
    maskedSpecID
        .clear(); // spectra ID not needed any more as all converted to det-ids
    return;
  }
  // 2. Get Map
  const spec2index_map s2imap = m_maskWS->getSpectrumToWorkspaceIndexMap();

  spec2index_map::const_iterator s2iter;

  // 3. Set mask
  auto spec0 = maskedSpecID[0];
  auto prev_masks = spec0;
  for (size_t i = 0; i < maskedSpecID.size(); i++) {

    auto spec2mask = maskedSpecID[i];

    s2iter = s2imap.find(spec2mask);
    if (s2iter == s2imap.end()) {
      // spectrum not found.  bad branch
      g_log.error()
          << "Spectrum " << spec2mask
          << " does not have an entry in GroupWorkspace's spec2index map\n";
      throw std::runtime_error("Logic error");
    } else {
      size_t wsindex = s2iter->second;
      if (wsindex >= m_maskWS->getNumberHistograms()) {
        // workspace index is out of range.  bad branch
        g_log.error() << "Group workspace's spec2index map is set wrong: "
                      << " Found workspace index = " << wsindex
                      << " for spectrum No " << spec2mask
                      << " with workspace size = "
                      << m_maskWS->getNumberHistograms() << '\n';
      } else {
        // Finally set the masking;
        m_maskWS->mutableY(wsindex)[0] = (mask) ? 1.0 : 0.0;
      } // IF-ELSE: ws index out of range
    }   // IF-ELSE: spectrum No has an entry

    if (spec2mask > prev_masks + 1) {
      g_log.debug() << "Masked Spectrum " << spec0 << "  To " << prev_masks
                    << '\n';
      spec0 = spec2mask;
    }
  } // FOR EACH SpecNo
}
Exemplo n.º 3
0
/** Set the mask on the spectrum Nos
 */
void LoadMask::processMaskOnWorkspaceIndex(bool mask,
                                           std::vector<int32_t> pairslow,
                                           std::vector<int32_t> pairsup) {
  // 1. Check
  if (pairslow.empty())
    return;
  if (pairslow.size() != pairsup.size()) {
    g_log.error() << "Input spectrum Nos are not paired.  Size(low) = "
                  << pairslow.size() << ", Size(up) = " << pairsup.size()
                  << std::endl;
    throw std::invalid_argument("Input spectrum Nos are not paired. ");
  }

  // 2. Get Map
  const spec2index_map s2imap = m_maskWS->getSpectrumToWorkspaceIndexMap();
  spec2index_map::const_iterator s2iter;

  // 3. Set mask
  for (size_t i = 0; i < pairslow.size(); i++) {
    // TODO Make this function work!
    g_log.debug() << "Mask Spectrum " << pairslow[i] << "  To " << pairsup[i]
                  << std::endl;

    for (int32_t specNo = pairslow[i]; specNo <= pairsup[i]; specNo++) {
      s2iter = s2imap.find(specNo);
      if (s2iter == s2imap.end()) {
        // spectrum not found.  bad branch
        g_log.error()
            << "Spectrum " << specNo
            << " does not have an entry in GroupWorkspace's spec2index map"
            << std::endl;
        throw std::runtime_error("Logic error");
      } else {
        size_t wsindex = s2iter->second;
        if (wsindex >= m_maskWS->getNumberHistograms()) {
          // workspace index is out of range.  bad branch
          g_log.error() << "Group workspace's spec2index map is set wrong: "
                        << " Found workspace index = " << wsindex
                        << " for spectrum No " << specNo
                        << " with workspace size = "
                        << m_maskWS->getNumberHistograms() << std::endl;
        } else {
          // Finally set the group workspace.  only good branch
          if (mask)
            m_maskWS->dataY(wsindex)[0] = 1.0;
          else
            m_maskWS->dataY(wsindex)[0] = 0.0;
        } // IF-ELSE: ws index out of range
      }   // IF-ELSE: spectrum No has an entry
    }     // FOR EACH SpecNo
  }       // FOR EACH Pair

  return;
}
Exemplo n.º 4
0
/** A memory efficient function that adjusts the X-value bin boundaries that only creates a new
*  cow_ptr array when the offset has changed
* @param offsets :: an array of times to adjust all the bins in each workspace histogram by
* @param spectraList :: a list of spectra numbers in the same order as the offsets
* @param specs2index :: a map that allows finding a spectra indexes from spectra numbers
* @param missingDetectors :: this will be filled with the array indices of the detector offsets that we can't find spectra indices for
*/
void LoadDetectorInfo::adjustXsCommon(const std::vector<float> &offsets, const std::vector<specid_t> &spectraList,
    spec2index_map &specs2index, std::vector<detid_t> missingDetectors)
{
  // space for cached values
  float cachedOffSet = UNSETOFFSET;
  MantidVecPtr monitorXs;
  MantidVecPtr cachedXs;

  double fracCompl = 1.0/3.0;
  
  for ( std::vector<int>::size_type j = 0; j < spectraList.size(); ++j )
  {// first check that our spectranumber to spectra index map is working for us
    if ( specs2index.find(spectraList[j]) == specs2index.end() )
    {// we can't find the spectrum associated the detector prepare to log that
      missingDetectors.push_back(static_cast<int>(j));
      // and then move on to the next detector in the loop
      continue;
    }

    const size_t specIndex = specs2index[spectraList[j]];
    // check if we dealing with a monitor as these are dealt by a different function
    const std::set<detid_t> & dets = m_workspace->getSpectrum(specIndex)->getDetectorIDs();

    if ( dets.size() > 0 )
    {// is it in the monitors list
      if ( m_monitors.find(*dets.begin()) == m_monitors.end() )
      {// it's not a monitor, it's a regular detector
        if ( offsets[j] != cachedOffSet )
        {
          setUpXArray(cachedXs, specIndex, offsets[j]);
          cachedOffSet = offsets[j];
        }
        else m_workspace->setX(specIndex, cachedXs);
      }
      else
      {// it's a monitor 
        if ( (*monitorXs).empty() )
        {
          // negative because we add the monitor offset, not take away as for detectors, the difference between the monitor delay and the detectors that counts
          setUpXArray(monitorXs, specIndex, -m_monitOffset);
        }
        else m_workspace->setX(specIndex, monitorXs);
      }
    }
    if ( j % INTERVAL == INTERVAL/2 )
    {
      fracCompl += (2.0*INTERVAL/3.0)/static_cast<double>(spectraList.size());
      progress( fracCompl );
      interruption_point();
    }
  }
}
/*
 * Set workspace index/group id by spectrum IDs
 */
void LoadDetectorsGroupingFile::setBySpectrumIDs() {
  // 1. Get map
  const spec2index_map s2imap = m_groupWS->getSpectrumToWorkspaceIndexMap();
  spec2index_map::const_iterator s2iter;

  // 2. Locate in loop
  //      std::map<int, std::vector<int> > m_groupSpectraMap;
  std::map<int, std::vector<int>>::iterator gsiter;
  for (gsiter = m_groupSpectraMap.begin(); gsiter != m_groupSpectraMap.end();
       ++gsiter) {
    int groupid = gsiter->first;
    for (auto specid : gsiter->second) {
      s2iter = s2imap.find(specid);
      if (s2iter == s2imap.end()) {
        g_log.error()
            << "Spectrum " << specid
            << " does not have an entry in GroupWorkspace's spec2index map"
            << std::endl;
        throw std::runtime_error("Logic error");
      } else {
        size_t wsindex = s2iter->second;
        if (wsindex >= m_groupWS->getNumberHistograms()) {
          g_log.error() << "Group workspace's spec2index map is set wrong: "
                        << " Found workspace index = " << wsindex
                        << " for spectrum ID " << specid
                        << " with workspace size = "
                        << m_groupWS->getNumberHistograms() << std::endl;
        } else {
          // Finally set the group workspace
          m_groupWS->dataY(wsindex)[0] = groupid;
        } // IF-ELSE: ws index out of range
      }   // IF-ELSE: spectrum ID has an entry
    }     // FOR: each spectrum ID
  }       // FOR: each group ID

  return;
}
Exemplo n.º 6
0
/** Reads from the file getting in order: an unused integer, on the next line the number of
*  spectra in the group and next one or more lines the spectra numbers, (format in GroupDetectors.h)
* @param specs2index :: a map that links spectra numbers to indexes
* @param File :: the input stream that is linked to the file
* @param lineNum :: the last line read in the file, is updated by this function
* @param unUsedSpec :: list of spectra that haven't yet been included in a group
* @throw invalid_argument if there is any problem with the file
*/
void GroupDetectors2::readFile(spec2index_map &specs2index, std::ifstream &File, size_t &lineNum, std::vector<int64_t> &unUsedSpec)
{
  // used in writing the spectra to the outData map. The groups are just labelled incrementally from 1
  int spectrumNo = 1;
  // go through the rest of the file reading in lists of spectra number to group
  while ( File )
  {
    std::string thisLine;
    do
    {
      std::getline( File, thisLine ), lineNum ++;
      // we haven't started reading a new group and so if the file ends here it is OK
      if ( ! File ) return;
    }
    while( readInt(thisLine) == EMPTY_LINE && File );

    // the number of spectra that will be combined in the group
    int numberOfSpectra = EMPTY_LINE;
    do
    {
      if ( ! File ) throw std::invalid_argument("Premature end of file, expecting an integer with the number of spectra in the group");
      std::getline( File, thisLine ), lineNum ++;
      numberOfSpectra = readInt(thisLine);
    }
    while( numberOfSpectra == EMPTY_LINE );

    // the value of this map is the list of spectra numbers that will be combined into a group
    m_GroupSpecInds[spectrumNo].reserve(numberOfSpectra);
    do
    {
      if ( ! File ) throw std::invalid_argument("Premature end of file, found number of spectra specification but no spectra list");
      std::getline( File, thisLine ), lineNum ++;
      // the spectra numbers that will be included in the group
      readSpectraIndexes(
        thisLine, specs2index, m_GroupSpecInds[spectrumNo], unUsedSpec);
    }
    while (static_cast<int>(m_GroupSpecInds[spectrumNo].size()) < numberOfSpectra);
    if ( static_cast<int>(m_GroupSpecInds[spectrumNo].size()) != numberOfSpectra )
    {// it makes no sense to continue reading the file, we'll stop here
      throw std::invalid_argument(std::string("Bad number of spectra specification or spectra list near line number ") + boost::lexical_cast<std::string>(lineNum));
    }
    // make regular progress reports and check for a cancellastion notification
    if ( (m_GroupSpecInds.size() % INTERVAL) == 1 )
    {
      fileReadProg( m_GroupSpecInds.size(), specs2index.size() );
    }
    spectrumNo++;
  }
}
    /**
     * Updates from a more generic ascii file
     * @param filename :: The input filename
     */
    void UpdateInstrumentFromFile::updateFromAscii(const std::string & filename)
    {
      AsciiFileHeader header;
      const bool isSpectrum = parseAsciiHeader(header);

      Geometry::Instrument_const_sptr inst = m_workspace->getInstrument();
      // Throws for multiple detectors
      const spec2index_map specToIndex(m_workspace->getSpectrumToWorkspaceIndexMap());

      std::ifstream datfile(filename.c_str(), std::ios_base::in);
      const int skipNLines = getProperty("SkipFirstNLines");
      std::string line;
      int lineCount(0);
      while(lineCount < skipNLines)
      {
        std::getline(datfile,line);
        ++lineCount;
      }

      std::vector<double> colValues(header.colCount - 1, 0.0);
      while(std::getline(datfile,line))
      {
        boost::trim(line);
        std::istringstream is(line);
        // Column 0 should be ID/spectrum number
        int32_t detOrSpec(-1000);
        is >> detOrSpec;
        // If first thing read is not a number then skip the line
        if(is.fail())
        {
          g_log.debug() << "Skipping \"" << line << "\". Cannot interpret as list of numbers.\n";
          continue;
        }

        Geometry::IDetector_const_sptr det;
        try
        {
          if(isSpectrum)
          {
            auto it = specToIndex.find(detOrSpec);
            if(it != specToIndex.end())
            {
              const size_t wsIndex = it->second;
              det = m_workspace->getDetector(wsIndex);
            }
            else
            {
              g_log.debug() << "Skipping \"" << line << "\". Spectrum is not in workspace.\n";
              continue;
            }
          }
          else
          {
            det = inst->getDetector(detOrSpec);
          }
        }
        catch(Kernel::Exception::NotFoundError&)
        {
          g_log.debug() << "Skipping \"" << line << "\". Spectrum in workspace but cannot find associated detector.\n";
          continue;
        }

        // Special cases for detector r,t,p. Everything else is
        // attached as an detector parameter
        double R(0.0),theta(0.0), phi(0.0);
        for(size_t i = 1; i < header.colCount; ++i)
        {
          double value(0.0);
          is >> value;
          if(i < header.colCount - 1 && is.eof())
          {
            //If stringstream is at EOF & we are not at the last column then
            // there aren't enought columns in the file
            throw std::runtime_error("UpdateInstrumentFromFile::updateFromAscii - "
                          "File contains fewer than expected number of columns, check AsciiHeader property.");
          }

          if(i == header.rColIdx) R = value;
          else if(i == header.thetaColIdx) theta = value;
          else if(i == header.phiColIdx) phi = value;
          else if(header.detParCols.count(i) == 1)
          {
            Geometry::ParameterMap & pmap = m_workspace->instrumentParameters();
            pmap.addDouble(det->getComponentID(), header.colToName[i],value);
          }
        }
        // Check stream state. stringstream::EOF should have been reached, if not then there is still more to
        // read and the file has more columns than the header indicated
        if(!is.eof())
        {
          throw std::runtime_error("UpdateInstrumentFromFile::updateFromAscii - "
              "File contains more than expected number of columns, check AsciiHeader property.");
        }

        // If not supplied use current values
        double r,t,p;
        det->getPos().getSpherical(r,t,p);
        if(header.rColIdx == 0) R = r;
        if(header.thetaColIdx == 0) theta = t;
        if(header.phiColIdx == 0) phi = p;

        setDetectorPosition(det, static_cast<float>(R), static_cast<float>(theta), static_cast<float>(phi));
      }
    }
Exemplo n.º 8
0
/** Use NearestNeighbours to find the neighbours for any instrument
 */
void SmoothNeighbours::findNeighboursUbiqutious() {
  g_log.debug(
      "SmoothNeighbours processing NOT assuming rectangular detectors.");

  m_progress->resetNumSteps(inWS->getNumberHistograms(), 0.2, 0.5);
  this->progress(0.2, "Building Neighbour Map");

  Instrument_const_sptr inst = inWS->getInstrument();
  const spec2index_map spec2index = inWS->getSpectrumToWorkspaceIndexMap();

  // Resize the vector we are setting
  m_neighbours.resize(inWS->getNumberHistograms());

  bool ignoreMaskedDetectors = getProperty("IgnoreMaskedDetectors");
  WorkspaceNearestNeighbourInfo neighbourInfo(*inWS, ignoreMaskedDetectors,
                                              nNeighbours);

  // Cull by radius
  RadiusFilter radiusFilter(Radius);

  // Go through every input workspace pixel
  outWI = 0;
  int sum = getProperty("SumNumberOfNeighbours");
  boost::shared_ptr<const Geometry::IComponent> parent, neighbParent,
      grandparent, neighbGParent;
  auto used = new bool[inWS->getNumberHistograms()];
  if (sum > 1) {
    for (size_t wi = 0; wi < inWS->getNumberHistograms(); wi++)
      used[wi] = false;
  }
  const auto &detectorInfo = inWS->detectorInfo();
  for (size_t wi = 0; wi < inWS->getNumberHistograms(); wi++) {
    if (sum > 1)
      if (used[wi])
        continue;
    // We want to skip monitors
    try {
      // Get the list of detectors in this pixel
      const auto &dets = inWS->getSpectrum(wi).getDetectorIDs();
      const auto index = detectorInfo.indexOf(*dets.begin());
      if (detectorInfo.isMonitor(index))
        continue; // skip monitor
      if (detectorInfo.isMasked(index)) {
        // Calibration masks many detectors, but there should be 0s after
        // smoothing
        if (sum == 1)
          outWI++;
        continue; // skip masked detectors
      }
      if (sum > 1) {
        const auto &det = detectorInfo.detector(index);
        parent = det.getParent();
        if (parent)
          grandparent = parent->getParent();
      }
    } catch (Kernel::Exception::NotFoundError &) {
      continue; // skip missing detector
    }

    specnum_t inSpec = inWS->getSpectrum(wi).getSpectrumNo();

    // Step one - Get the number of specified neighbours
    SpectraDistanceMap insideGrid = neighbourInfo.getNeighboursExact(inSpec);

    // Step two - Filter the results by the radius cut off.
    SpectraDistanceMap neighbSpectra = radiusFilter.apply(insideGrid);

    // Force the central pixel to always be there
    // There seems to be a bug in nearestNeighbours, returns distance != 0.0 for
    // the central pixel. So we force distance = 0
    neighbSpectra[inSpec] = V3D(0.0, 0.0, 0.0);

    // Neighbours and weights list
    double totalWeight = 0;
    int noNeigh = 0;
    std::vector<weightedNeighbour> neighbours;

    // Convert from spectrum numbers to workspace indices
    for (auto &specDistance : neighbSpectra) {
      specnum_t spec = specDistance.first;

      // Use the weighting strategy to calculate the weight.
      double weight = WeightedSum->weightAt(specDistance.second);

      if (weight > 0) {
        // Find the corresponding workspace index
        auto mapIt = spec2index.find(spec);
        if (mapIt != spec2index.end()) {
          size_t neighWI = mapIt->second;
          if (sum > 1) {
            // Get the list of detectors in this pixel
            const std::set<detid_t> &dets =
                inWS->getSpectrum(neighWI).getDetectorIDs();
            const auto &det = detectorInfo.detector(*dets.begin());
            neighbParent = det.getParent();
            neighbGParent = neighbParent->getParent();
            if (noNeigh >= sum ||
                neighbParent->getName() != parent->getName() ||
                neighbGParent->getName() != grandparent->getName() ||
                used[neighWI])
              continue;
            noNeigh++;
            used[neighWI] = true;
          }
          neighbours.emplace_back(neighWI, weight);
          totalWeight += weight;
        }
      }
    }

    // Adjust the weights of each neighbour to normalize to unity
    if (sum == 1)
      for (auto &neighbour : neighbours)
        neighbour.second /= totalWeight;

    // Save the list of neighbours for this output workspace index.
    m_neighbours[outWI] = neighbours;
    outWI++;

    m_progress->report("Finding Neighbours");
  } // each workspace index

  delete[] used;
}
Exemplo n.º 9
0
/**
 * Updates from a more generic ascii file
 * @param filename :: The input filename
 */
void UpdateInstrumentFromFile::updateFromAscii(const std::string &filename) {
  AsciiFileHeader header;
  const bool isSpectrum = parseAsciiHeader(header);

  // Throws for multiple detectors
  const spec2index_map specToIndex(
      m_workspace->getSpectrumToWorkspaceIndexMap());

  std::ifstream datfile(filename.c_str(), std::ios_base::in);
  const int skipNLines = getProperty("SkipFirstNLines");
  std::string line;
  int lineCount(0);
  while (lineCount < skipNLines) {
    std::getline(datfile, line);
    ++lineCount;
  }

  Geometry::ParameterMap &pmap = m_workspace->instrumentParameters();
  auto &detectorInfo = m_workspace->mutableDetectorInfo();
  const auto &spectrumInfo = m_workspace->spectrumInfo();

  std::vector<double> colValues(header.colCount - 1, 0.0);
  while (std::getline(datfile, line)) {
    boost::trim(line);
    std::istringstream is(line);
    // Column 0 should be ID/spectrum number
    int32_t detOrSpec(-1000);
    is >> detOrSpec;
    // If first thing read is not a number then skip the line
    if (is.fail()) {
      g_log.debug() << "Skipping \"" << line
                    << "\". Cannot interpret as list of numbers.\n";
      continue;
    }

    bool skip{false};
    size_t index = static_cast<size_t>(-1);
    const Geometry::IDetector *det{nullptr};
    if (isSpectrum) {
      auto it = specToIndex.find(detOrSpec);
      if (it != specToIndex.end()) {
        index = it->second;
        if (spectrumInfo.hasDetectors(index)) {
          det = &spectrumInfo.detector(index);
        } else {
          skip = true;
        }
      } else {
        g_log.debug() << "Skipping \"" << line
                      << "\". Spectrum is not in workspace.\n";
        continue;
      }
    } else {
      try {
        index = detectorInfo.indexOf(detOrSpec);
        det = &detectorInfo.detector(index);
      } catch (std::out_of_range &) {
        skip = true;
      }
    }
    if (skip || index == static_cast<size_t>(-1)) {
      g_log.debug()
          << "Skipping \"" << line
          << "\". Spectrum in workspace but cannot find associated detector.\n";
      continue;
    }

    std::vector<size_t> indices;
    if (isSpectrum) {
      if (auto group = dynamic_cast<const Geometry::DetectorGroup *>(det)) {
        for (const auto detID : group->getDetectorIDs())
          indices.push_back(detectorInfo.indexOf(detID));
      } else {
        indices.push_back(detectorInfo.indexOf(det->getID()));
      }
    } else {
      indices.push_back(index);
    }

    // Special cases for detector r,t,p. Everything else is
    // attached as an detector parameter
    double R(0.0), theta(0.0), phi(0.0);
    for (size_t i = 1; i < header.colCount; ++i) {
      double value(0.0);
      is >> value;
      if (i < header.colCount - 1 && is.eof()) {
        // If stringstream is at EOF & we are not at the last column then
        // there aren't enought columns in the file
        throw std::runtime_error("UpdateInstrumentFromFile::updateFromAscii - "
                                 "File contains fewer than expected number of "
                                 "columns, check AsciiHeader property.");
      }

      if (i == header.rColIdx)
        R = value;
      else if (i == header.thetaColIdx)
        theta = value;
      else if (i == header.phiColIdx)
        phi = value;
      else if (header.detParCols.count(i) == 1) {
        for (const auto index : indices) {
          auto id = detectorInfo.detector(index).getComponentID();
          pmap.addDouble(id, header.colToName[i], value);
        }
      }
    }
    // Check stream state. stringstream::EOF should have been reached, if not
    // then there is still more to
    // read and the file has more columns than the header indicated
    if (!is.eof()) {
      throw std::runtime_error("UpdateInstrumentFromFile::updateFromAscii - "
                               "File contains more than expected number of "
                               "columns, check AsciiHeader property.");
    }

    // If not supplied use current values
    double r, t, p;
    if (isSpectrum)
      spectrumInfo.position(index).getSpherical(r, t, p);
    else
      detectorInfo.position(index).getSpherical(r, t, p);
    if (header.rColIdx == 0)
      R = r;
    if (header.thetaColIdx == 0)
      theta = t;
    if (header.phiColIdx == 0 || m_ignorePhi)
      phi = p;

    for (const auto index : indices)
      setDetectorPosition(detectorInfo, index, static_cast<float>(R),
                          static_cast<float>(theta), static_cast<float>(phi));
  }
}