コード例 #1
0
ファイル: SaveAscii2.cpp プロジェクト: rosswhitfield/mantid
/**
 * Populate the map with the Q values associated with each spectrum in the
 * workspace
 */
void SaveAscii2::populateQMetaData() {
  std::vector<std::string> qValues;
  const auto nHist = m_ws->getNumberHistograms();
  for (size_t i = 0; i < nHist; i++) {
    const auto specNo = m_ws->getSpectrum(i).getSpectrumNo();
    const auto workspaceIndex = m_specToIndexMap[specNo];
    const auto detector = m_ws->getDetector(workspaceIndex);
    double twoTheta(0.0), efixed(0.0);
    if (!detector->isMonitor()) {
      twoTheta = 0.5 * m_ws->detectorTwoTheta(*detector);
      try {
        efixed = m_ws->getEFixed(detector);
      } catch (std::runtime_error) {
        throw;
      }
    } else {
      twoTheta = 0.0;
      efixed = DBL_MIN;
    }
    // Convert to MomentumTransfer
    auto qValue = Kernel::UnitConversion::run(twoTheta, efixed);
    auto qValueStr = boost::lexical_cast<std::string>(qValue);
    qValues.push_back(qValueStr);
  }
  m_metaDataMap["q"] = qValues;
}
コード例 #2
0
ファイル: DetectorInfo.cpp プロジェクト: DanNixon/mantid
/// Returns signed 2 theta (signed scattering angle w.r.t. to beam direction).
double
DetectorInfo::signedTwoTheta(const std::pair<size_t, size_t> &index) const {
  if (isMonitor(index))
    throw std::logic_error(
        "Two theta (scattering angle) is not defined for monitors.");

  const auto samplePos = samplePosition();
  const auto beamLine = samplePos - sourcePosition();

  if (beamLine.nullVector()) {
    throw Kernel::Exception::InstrumentDefinitionError(
        "Source and sample are at same position!");
  }
  // Get the axis defining the sign
  const auto &instrumentUpAxis =
      m_instrument->getReferenceFrame()->vecThetaSign();

  const auto sampleDetVec = position(index) - samplePos;
  double angle = sampleDetVec.angle(beamLine);

  const auto cross = beamLine.cross_prod(sampleDetVec);
  const auto normToSurface = beamLine.cross_prod(instrumentUpAxis);
  if (normToSurface.scalar_prod(cross) < 0) {
    angle *= -1;
  }
  return angle;
}
コード例 #3
0
/** Returns the signed scattering angle 2 theta (angle w.r.t. to beam
 * direction).
 *
 * Throws an exception if the spectrum is a monitor.
 */
double SpectrumInfo::signedTwoTheta(const size_t index) const {
  if (isMonitor(index))
    throw std::logic_error(
        "Two theta (scattering angle) is not defined for monitors.");

  double signedTwoTheta{0.0};
  const auto &dets = getDetectorVector(index);
  for (const auto &det : dets) {
    const auto &detIndex = m_detectorInfo.indexOf(det->getID());
    m_detectorInfo.setCachedDetector(detIndex, det);
    signedTwoTheta += m_detectorInfo.signedTwoTheta(detIndex);
  }
  return signedTwoTheta / static_cast<double>(dets.size());
}
コード例 #4
0
/**
 * Sum counts from the input workspace in lambda along lines of constant Q by
 * projecting to "virtual lambda" at a reference angle.
 *
 * @param detectorWS [in] :: the input workspace in wavelength
 * @param indices [in] :: an index set defining the foreground histograms
 * @return :: the single histogram output workspace in wavelength
 */
API::MatrixWorkspace_sptr
ReflectometrySumInQ::sumInQ(const API::MatrixWorkspace &detectorWS,
                            const Indexing::SpectrumIndexSet &indices) {

  const auto spectrumInfo = detectorWS.spectrumInfo();
  const auto refAngles = referenceAngles(spectrumInfo);
  // Construct the output workspace in virtual lambda
  API::MatrixWorkspace_sptr IvsLam =
      constructIvsLamWS(detectorWS, indices, refAngles);
  auto &outputE = IvsLam->dataE(0);
  // Loop through each spectrum in the detector group
  for (auto spIdx : indices) {
    if (spectrumInfo.isMasked(spIdx) || spectrumInfo.isMonitor(spIdx)) {
      continue;
    }
    // Get the size of this detector in twoTheta
    const auto twoThetaRange = twoThetaWidth(spIdx, spectrumInfo);
    // Check X length is Y length + 1
    const auto inputBinEdges = detectorWS.binEdges(spIdx);
    const auto inputCounts = detectorWS.counts(spIdx);
    const auto inputStdDevs = detectorWS.countStandardDeviations(spIdx);
    // Create a vector for the projected errors for this spectrum.
    // (Output Y values can simply be accumulated directly into the output
    // workspace, but for error values we need to create a separate error
    // vector for the projected errors from each input spectrum and then
    // do an overall sum in quadrature.)
    std::vector<double> projectedE(outputE.size(), 0.0);
    // Process each value in the spectrum
    const int ySize = static_cast<int>(inputCounts.size());
    for (int inputIdx = 0; inputIdx < ySize; ++inputIdx) {
      // Do the summation in Q
      processValue(inputIdx, twoThetaRange, refAngles, inputBinEdges,
                   inputCounts, inputStdDevs, *IvsLam, projectedE);
    }
    // Sum errors in quadrature
    const int eSize = static_cast<int>(outputE.size());
    for (int outIdx = 0; outIdx < eSize; ++outIdx) {
      outputE[outIdx] += projectedE[outIdx] * projectedE[outIdx];
    }
  }

  // Take the square root of all the accumulated squared errors for this
  // detector group. Assumes Gaussian errors
  double (*rs)(double) = std::sqrt;
  std::transform(outputE.begin(), outputE.end(), outputE.begin(), rs);

  return IvsLam;
}
コード例 #5
0
ファイル: DetectorInfo.cpp プロジェクト: DanNixon/mantid
/// Returns 2 theta (scattering angle w.r.t. to beam direction).
double DetectorInfo::twoTheta(const std::pair<size_t, size_t> &index) const {
  if (isMonitor(index))
    throw std::logic_error(
        "Two theta (scattering angle) is not defined for monitors.");

  const auto samplePos = samplePosition();
  const auto beamLine = samplePos - sourcePosition();

  if (beamLine.nullVector()) {
    throw Kernel::Exception::InstrumentDefinitionError(
        "Source and sample are at same position!");
  }

  const auto sampleDetVec = position(index) - samplePos;
  return sampleDetVec.angle(beamLine);
}
コード例 #6
0
ファイル: LoadRaw3.cpp プロジェクト: rosswhitfield/mantid
void LoadRaw3::separateMonitors(FILE *file, const int64_t &period,
                                const std::vector<specnum_t> &monitorList,
                                DataObjects::Workspace2D_sptr ws_sptr,
                                DataObjects::Workspace2D_sptr mws_sptr) {
  int64_t histCurrent = -1;
  int64_t wsIndex = 0;
  int64_t mwsIndex = 0;
  double histTotal = static_cast<double>(m_total_specs * m_numberOfPeriods);
  // loop through spectra
  for (specnum_t i = 1; i <= m_numberOfSpectra; ++i) {
    int64_t histToRead = i + period * (m_numberOfSpectra + 1);
    if ((i >= m_spec_min && i < m_spec_max) ||
        (m_list &&
         find(m_spec_list.begin(), m_spec_list.end(), i) !=
             m_spec_list.end())) {
      progress(m_prog, "Reading raw file data...");

      // read spectrum from raw file
      if (!readData(file, histToRead)) {
        throw std::runtime_error("Error reading raw file");
      }
      // if this a monitor  store that spectrum to monitor workspace
      if (isMonitor(monitorList, i)) {
        setWorkspaceData(mws_sptr, m_timeChannelsVec, mwsIndex, i,
                         m_noTimeRegimes, m_lengthIn, 1);
        ++mwsIndex;
      } else {
        // not a monitor,store the spectrum to normal output workspace
        setWorkspaceData(ws_sptr, m_timeChannelsVec, wsIndex, i,
                         m_noTimeRegimes, m_lengthIn, 1);
        ++wsIndex;
      }

      if (m_numberOfPeriods == 1) {
        if (++histCurrent % 100 == 0) {
          setProg(static_cast<double>(histCurrent) / histTotal);
        }
        interruption_point();
      }

    } else {
      skipData(file, histToRead);
    }
  }
}
コード例 #7
0
ファイル: LoadRaw3.cpp プロジェクト: rosswhitfield/mantid
/** This method creates outputworkspace excluding monitors
 *@param file :: -pointer to file
 *@param period :: period number
 *@param monitorList :: a list containing the spectrum numbers for monitors
 *@param ws_sptr :: shared pointer to workspace
 */
void LoadRaw3::excludeMonitors(FILE *file, const int &period,
                               const std::vector<specnum_t> &monitorList,
                               DataObjects::Workspace2D_sptr ws_sptr) {
  int64_t histCurrent = -1;
  int64_t wsIndex = 0;
  double histTotal = static_cast<double>(m_total_specs * m_numberOfPeriods);
  // loop through the spectra
  for (specnum_t i = 1; i <= m_numberOfSpectra; ++i) {
    specnum_t histToRead = i + period * (m_numberOfSpectra + 1);
    if ((i >= m_spec_min && i < m_spec_max) ||
        (m_list &&
         find(m_spec_list.begin(), m_spec_list.end(), i) !=
             m_spec_list.end())) {
      progress(m_prog, "Reading raw file data...");
      // skip monitor spectrum
      if (isMonitor(monitorList, i)) {
        skipData(file, histToRead);
        continue;
      }

      // read spectrum
      if (!readData(file, histToRead)) {
        throw std::runtime_error("Error reading raw file");
      }
      // set the workspace data
      setWorkspaceData(ws_sptr, m_timeChannelsVec, wsIndex, i, m_noTimeRegimes,
                       m_lengthIn, 1);
      // increment workspace index
      ++wsIndex;

      if (m_numberOfPeriods == 1) {
        if (++histCurrent % 100 == 0) {
          setProg(static_cast<double>(histCurrent) / histTotal);
        }
        interruption_point();
      }

    } // end of if loop for spec min,max check
    else {
      skipData(file, histToRead);
    }
  } // end of for loop
}
コード例 #8
0
ファイル: DetectorInfo.cpp プロジェクト: DanNixon/mantid
/** Returns L2 (distance from sample to spectrum).
 *
 * For monitors this is defined such that L1+L2 = source-detector distance,
 * i.e., for a monitor in the beamline between source and sample L2 is negative.
 */
double DetectorInfo::l2(const std::pair<size_t, size_t> &index) const {
  if (!isMonitor(index))
    return position(index).distance(samplePosition());
  else
    return position(index).distance(sourcePosition()) - l1();
}
コード例 #9
0
ファイル: MDNormDirectSC.cpp プロジェクト: mducle/mantid
/**
 * Computed the normalization for the input workspace. Results are stored in
 * m_normWS
 * @param otherValues
 * @param affineTrans
 */
void MDNormDirectSC::calculateNormalization(
    const std::vector<coord_t> &otherValues,
    const Kernel::Matrix<coord_t> &affineTrans) {
  constexpr double energyToK = 8.0 * M_PI * M_PI *
                               PhysicalConstants::NeutronMass *
                               PhysicalConstants::meV * 1e-20 /
                               (PhysicalConstants::h * PhysicalConstants::h);
  const auto &exptInfoZero = *(m_inputWS->getExperimentInfo(0));
  typedef Kernel::PropertyWithValue<std::vector<double>> VectorDoubleProperty;
  auto *rubwLog =
      dynamic_cast<VectorDoubleProperty *>(exptInfoZero.getLog("RUBW_MATRIX"));
  if (!rubwLog) {
    throw std::runtime_error(
        "Wokspace does not contain a log entry for the RUBW matrix."
        "Cannot continue.");
  } else {
    Kernel::DblMatrix rubwValue(
        (*rubwLog)()); // includes the 2*pi factor but not goniometer for now :)
    m_rubw = exptInfoZero.run().getGoniometerMatrix() * rubwValue;
    m_rubw.Invert();
  }
  const double protonCharge = exptInfoZero.run().getProtonCharge();

  auto instrument = exptInfoZero.getInstrument();
  std::vector<detid_t> detIDs = instrument->getDetectorIDs(true);
  // Prune out those that are part of a group and simply leave the head of the
  // group
  detIDs = removeGroupedIDs(exptInfoZero, detIDs);

  // Mapping
  const int64_t ndets = static_cast<int64_t>(detIDs.size());
  bool haveSA = false;
  API::MatrixWorkspace_const_sptr solidAngleWS =
      getProperty("SolidAngleWorkspace");
  detid2index_map solidAngDetToIdx;
  if (solidAngleWS != nullptr) {
    haveSA = true;
    solidAngDetToIdx = solidAngleWS->getDetectorIDToWorkspaceIndexMap();
  }

  auto prog = make_unique<API::Progress>(this, 0.3, 1.0, ndets);
  PARALLEL_FOR_NO_WSP_CHECK()
  for (int64_t i = 0; i < ndets; i++) {
    PARALLEL_START_INTERUPT_REGION

    const auto detID = detIDs[i];
    double theta(0.0), phi(0.0);
    bool skip(false);
    try {
      auto spectrum = getThetaPhi(detID, exptInfoZero, theta, phi);
      if (spectrum->isMonitor() || spectrum->isMasked())
        continue;
    } catch (
        std::exception &) // detector might not exist or has no been included
                          // in grouping
    {
      skip = true; // Intel compiler has a problem with continue inside a catch
                   // inside openmp...
    }
    if (skip)
      continue;

    // Intersections
    auto intersections = calculateIntersections(theta, phi);
    if (intersections.empty())
      continue;

    // Get solid angle for this contribution
    double solid = protonCharge;
    if (haveSA) {
      solid = solidAngleWS->readY(solidAngDetToIdx.find(detID)->second)[0] *
              protonCharge;
    }
    // Compute final position in HKL
    const size_t vmdDims = intersections.front().size();
    // pre-allocate for efficiency and copy non-hkl dim values into place
    std::vector<coord_t> pos(vmdDims + otherValues.size() + 1);
    std::copy(otherValues.begin(), otherValues.end(), pos.begin() + vmdDims);
    pos.push_back(1.);
    auto intersectionsBegin = intersections.begin();
    for (auto it = intersectionsBegin + 1; it != intersections.end(); ++it) {
      const auto &curIntSec = *it;
      const auto &prevIntSec = *(it - 1);
      // the full vector isn't used so compute only what is necessary
      double delta =
          (curIntSec[3] * curIntSec[3] - prevIntSec[3] * prevIntSec[3]) /
          energyToK;
      if (delta < 1e-10)
        continue; // Assume zero contribution if difference is small

      // Average between two intersections for final position
      std::transform(curIntSec.getBareArray(),
                     curIntSec.getBareArray() + vmdDims,
                     prevIntSec.getBareArray(), pos.begin(),
                     VectorHelper::SimpleAverage<coord_t>());

      // transform kf to energy transfer
      pos[3] = static_cast<coord_t>(m_Ei - pos[3] * pos[3] / energyToK);
      std::vector<coord_t> posNew = affineTrans * pos;
      size_t linIndex = m_normWS->getLinearIndexAtCoord(posNew.data());
      if (linIndex == size_t(-1))
        continue;

      // signal = integral between two consecutive intersections *solid angle
      // *PC
      double signal = solid * delta;

      PARALLEL_CRITICAL(updateMD) {
        signal += m_normWS->getSignalAt(linIndex);
        m_normWS->setSignalAt(linIndex, signal);
      }
    }
    prog->report();

    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION
}
コード例 #10
0
ファイル: MDNormSCD.cpp プロジェクト: dezed/mantid
/**
 * Computed the normalization for the input workspace. Results are stored in
 * m_normWS
 * @param otherValues
 * @param affineTrans
 */
void MDNormSCD::calculateNormalization(
    const std::vector<coord_t> &otherValues,
    const Kernel::Matrix<coord_t> &affineTrans) {
  API::MatrixWorkspace_const_sptr integrFlux = getProperty("FluxWorkspace");
  integrFlux->getXMinMax(m_kiMin, m_kiMax);
  API::MatrixWorkspace_const_sptr solidAngleWS =
      getProperty("SolidAngleWorkspace");

  const auto &exptInfoZero = *(m_inputWS->getExperimentInfo(0));
  typedef Kernel::PropertyWithValue<std::vector<double>> VectorDoubleProperty;
  auto *rubwLog =
      dynamic_cast<VectorDoubleProperty *>(exptInfoZero.getLog("RUBW_MATRIX"));
  if (!rubwLog) {
    throw std::runtime_error(
        "Wokspace does not contain a log entry for the RUBW matrix."
        "Cannot continue.");
  } else {
    Kernel::DblMatrix rubwValue(
        (*rubwLog)()); // includes the 2*pi factor but not goniometer for now :)
    m_rubw = exptInfoZero.run().getGoniometerMatrix() * rubwValue;
    m_rubw.Invert();
  }
  const double protonCharge = exptInfoZero.run().getProtonCharge();

  auto instrument = exptInfoZero.getInstrument();
  std::vector<detid_t> detIDs = instrument->getDetectorIDs(true);
  // Prune out those that are part of a group and simply leave the head of the
  // group
  detIDs = removeGroupedIDs(exptInfoZero, detIDs);

  // Mappings
  const int64_t ndets = static_cast<int64_t>(detIDs.size());
  const detid2index_map fluxDetToIdx =
      integrFlux->getDetectorIDToWorkspaceIndexMap();
  const detid2index_map solidAngDetToIdx =
      solidAngleWS->getDetectorIDToWorkspaceIndexMap();

  auto prog = make_unique<API::Progress>(this, 0.3, 1.0, ndets);
  PARALLEL_FOR1(integrFlux)
  for (int64_t i = 0; i < ndets; i++) {
    PARALLEL_START_INTERUPT_REGION

    const auto detID = detIDs[i];
    double theta(0.0), phi(0.0);
    bool skip(false);
    try {
      auto spectrum = getThetaPhi(detID, exptInfoZero, theta, phi);
      if (spectrum->isMonitor() || spectrum->isMasked())
        continue;
    } catch (
        std::exception &) // detector might not exist or has no been included
                          // in grouping
    {
      skip = true; // Intel compiler has a problem with continue inside a catch
                   // inside openmp...
    }
    if (skip)
      continue;

    // Intersections
    auto intersections = calculateIntersections(theta, phi);
    if (intersections.empty())
      continue;

    // get the flux spetrum number
    size_t wsIdx = fluxDetToIdx.find(detID)->second;
    // Get solid angle for this contribution
    double solid =
        solidAngleWS->readY(solidAngDetToIdx.find(detID)->second)[0] *
        protonCharge;

    // -- calculate integrals for the intersection --
    // momentum values at intersections
    auto intersectionsBegin = intersections.begin();
    std::vector<double> xValues(intersections.size()),
        yValues(intersections.size());
    {
      // copy momenta to xValues
      auto x = xValues.begin();
      for (auto it = intersectionsBegin; it != intersections.end(); ++it, ++x) {
        *x = (*it)[3];
      }
    }
    // calculate integrals at momenta from xValues by interpolating between
    // points in spectrum sp
    // of workspace integrFlux. The result is stored in yValues
    calcIntegralsForIntersections(xValues, *integrFlux, wsIdx, yValues);

    // Compute final position in HKL
    const size_t vmdDims = intersections.front().size();
    // pre-allocate for efficiency and copy non-hkl dim values into place
    std::vector<coord_t> pos(vmdDims + otherValues.size());
    std::copy(otherValues.begin(), otherValues.end(),
              pos.begin() + vmdDims - 1);
    pos.push_back(1.);

    for (auto it = intersectionsBegin + 1; it != intersections.end(); ++it) {
      const auto &curIntSec = *it;
      const auto &prevIntSec = *(it - 1);
      // the full vector isn't used so compute only what is necessary
      double delta = curIntSec[3] - prevIntSec[3];
      if (delta < 1e-07)
        continue; // Assume zero contribution if difference is small

      // Average between two intersections for final position
      std::transform(curIntSec.getBareArray(),
                     curIntSec.getBareArray() + vmdDims - 1,
                     prevIntSec.getBareArray(), pos.begin(),
                     VectorHelper::SimpleAverage<coord_t>());
      std::vector<coord_t> posNew = affineTrans * pos;
      size_t linIndex = m_normWS->getLinearIndexAtCoord(posNew.data());
      if (linIndex == size_t(-1))
        continue;

      // index of the current intersection
      size_t k = static_cast<size_t>(std::distance(intersectionsBegin, it));
      // signal = integral between two consecutive intersections
      double signal = (yValues[k] - yValues[k - 1]) * solid;

      PARALLEL_CRITICAL(updateMD) {
        signal += m_normWS->getSignalAt(linIndex);
        m_normWS->setSignalAt(linIndex, signal);
      }
    }
    prog->report();

    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION
}
コード例 #11
0
/**
 * Clear the vector of strings and then add pairs of strings giving information
 * about the specified point, x, y.  The first string in a pair should
 * generally be a string describing the value being presented and the second
 * string should contain the value.
 *
 * @param x    The x-coordinate of the point of interest in the data.
 * @param y    The y-coordinate of the point of interest in the data.
 * @param list Vector that will be filled out with the information strings.
 */
void MatrixWSDataSource::getInfoList( double x,
                                      double y,
                                      std::vector<std::string> &list )
{
  // First get the info that is always available for any matrix workspace
  list.clear();

  int row = (int)y;
  restrictRow( row );

  const ISpectrum* spec = m_matWs->getSpectrum( row );

  double spec_num = spec->getSpectrumNo();
  SVUtils::PushNameValue( "Spec Num", 8, 0, spec_num, list );

  std::string x_label = "";
  Unit_sptr& old_unit = m_matWs->getAxis(0)->unit();
  if ( old_unit != 0 )
  {
    x_label = old_unit->caption();
    SVUtils::PushNameValue( x_label, 8, 3, x, list );
  }

  std::set<detid_t> ids = spec->getDetectorIDs();
  if ( !ids.empty() )
  {
    list.push_back("Det ID");
    const int64_t id = static_cast<int64_t>(*(ids.begin()));
    list.push_back(boost::lexical_cast<std::string>(id));
  }

  /* Now try to do various unit conversions to get equivalent info */
  /* first make sure we can get the needed information */
  if ( !(m_instrument && m_source && m_sample) )
  {
    return;
  }

  try
  {

    if ( old_unit == 0 )
    {
      g_log.debug("No UNITS on MatrixWorkspace X-axis");
      return;
    }

    auto det = m_matWs->getDetector( row );
    if ( det == 0 )
    {
      g_log.debug() << "No DETECTOR for row " << row << " in MatrixWorkspace" << std::endl;
      return;
    }

    double l1        = m_source->getDistance(*m_sample);
    double l2        = 0.0;
    double two_theta = 0.0;
    double azi       = 0.0;
    if ( det->isMonitor() )
    {
      l2 = det->getDistance(*m_source);
      l2 = l2-l1;
    }
    else
    {
      l2 = det->getDistance(*m_sample);
      two_theta = m_matWs->detectorTwoTheta(det);
      azi = det->getPhi();
    }
    SVUtils::PushNameValue( "L2", 8, 4, l2, list );
    SVUtils::PushNameValue( "TwoTheta", 8, 2, two_theta*180./M_PI, list );
    SVUtils::PushNameValue( "Azimuthal", 8, 2, azi*180./M_PI, list );

    /* For now, only support diffractometers and monitors. */
    /* We need a portable way to determine emode and */
    /* and efixed that will work for any matrix workspace! */
    int    emode  = 0;
    double efixed = 0.0;
    double delta  = 0.0;

    // First try to get emode & efixed from the user
    if ( m_emodeHandler != NULL )
    {
      efixed = m_emodeHandler->getEFixed();
      if ( efixed != 0 )
      {
        emode = m_emodeHandler->getEMode();
        if ( emode == 0 )
        {
          g_log.information("EMode invalid, spectrometer needed if emode != 0");
          g_log.information("Assuming Direct Geometry Spectrometer....");
          emode = 1;
        }
      }
    }

    // Did NOT get emode & efixed from user, try getting direct geometry information from the run object
    if ( efixed == 0 )
    {
      const API::Run & run = m_matWs->run();
      if ( run.hasProperty("Ei") )
      {
        Kernel::Property* prop = run.getProperty("Ei");
        efixed = boost::lexical_cast<double,std::string>(prop->value());
        emode  = 1;                         // only correct if direct geometry
      }
      else if ( run.hasProperty("EnergyRequested") )
      {
        Kernel::Property* prop = run.getProperty("EnergyRequested");
        efixed = boost::lexical_cast<double,std::string>(prop->value());
        emode  = 1;
      }
      else if ( run.hasProperty("EnergyEstimate") )
      {
        Kernel::Property* prop = run.getProperty("EnergyEstimate");
        efixed = boost::lexical_cast<double,std::string>(prop->value());
        emode  = 1;
      }
    }

    // Finally, try getting indirect geometry information from the detector object
    if ( efixed == 0 )
    {
      if ( !(det->isMonitor() && det->hasParameter("Efixed")))
      {
        try
        {
          const ParameterMap& pmap = m_matWs->constInstrumentParameters();
          Parameter_sptr par = pmap.getRecursive(det.get(),"Efixed");
          if (par)
          {
            efixed = par->value<double>();
            emode = 2;
          }
        }
        catch ( std::runtime_error& )
        {
          g_log.debug() << "Failed to get Efixed from detector ID: "
                        << det->getID() << " in MatrixWSDataSource" << std::endl;
          efixed = 0;
        }
      }
    }

    if ( efixed == 0 )
      emode = 0;

    if ( m_emodeHandler != NULL )
    {
      m_emodeHandler -> setEFixed( efixed );
      m_emodeHandler -> setEMode ( emode );
    }

    double tof = old_unit->convertSingleToTOF( x, l1, l2, two_theta,
                                               emode, efixed, delta );
    if ( ! (x_label == "Time-of-flight") )
      SVUtils::PushNameValue( "Time-of-flight", 8, 1, tof, list );

    if ( ! (x_label == "Wavelength") )
    {
      const Unit_sptr& wl_unit = UnitFactory::Instance().create("Wavelength");
      double wavelength = wl_unit->convertSingleFromTOF( tof, l1, l2, two_theta,
                                                         emode, efixed, delta );
      SVUtils::PushNameValue( "Wavelength", 8, 4, wavelength, list );
    }

    if ( ! (x_label == "Energy") )
    {
      const Unit_sptr& e_unit = UnitFactory::Instance().create("Energy");
      double energy = e_unit->convertSingleFromTOF( tof, l1, l2, two_theta,
                                                    emode, efixed, delta );
      SVUtils::PushNameValue( "Energy", 8, 4, energy, list );
    }

    if ( (! (x_label == "d-Spacing")) && (two_theta != 0.0) && ( emode == 0 ) )
    {
      const Unit_sptr& d_unit = UnitFactory::Instance().create("dSpacing");
      double d_spacing = d_unit->convertSingleFromTOF( tof, l1, l2, two_theta,
                                                       emode, efixed, delta );
      SVUtils::PushNameValue( "d-Spacing", 8, 4, d_spacing, list );
    }

    if ( (! (x_label == "q")) && (two_theta != 0.0) )
    {
      const Unit_sptr& q_unit=UnitFactory::Instance().create("MomentumTransfer");
      double mag_q = q_unit->convertSingleFromTOF( tof, l1, l2, two_theta,
                                                   emode, efixed, delta );
      SVUtils::PushNameValue( "|Q|", 8, 4, mag_q, list );
    }

    if ( (! (x_label == "DeltaE")) && (two_theta != 0.0) && ( emode != 0 ) )
    {
      const Unit_sptr& deltaE_unit=UnitFactory::Instance().create("DeltaE");
      double delta_E = deltaE_unit->convertSingleFromTOF( tof, l1, l2, two_theta,
                                                          emode, efixed, delta );
      SVUtils::PushNameValue( "DeltaE", 8, 4, delta_E, list );
    }
  }
  catch (std::exception & e)
  {
    g_log.debug() << "Failed to get information from Workspace:" << e.what() << std::endl;
  }
}