コード例 #1
0
/// calculate distance from source to sample or detector
double ModeratorTzero::CalculateL1(Mantid::API::MatrixWorkspace_sptr inputWS, size_t i){
  double L1(0);
  // Get detector position
  IDetector_const_sptr det;
  try
  {
    det = inputWS->getDetector(i);
  }
  catch (Exception::NotFoundError&)
  {
    return 0;
  }

  if( det->isMonitor() )
  {
    L1=m_instrument->getSource()->getDistance(*det);
  }
  else
  {
    IComponent_const_sptr sample = m_instrument->getSample();
    try
    {
      L1 = m_instrument->getSource()->getDistance(*sample);
    }
    catch (Exception::NotFoundError &)
    {
      g_log.error("Unable to calculate source-sample distance");
      throw Exception::InstrumentDefinitionError("Unable to calculate source-sample distance", inputWS->getTitle());
    }
  }
  return L1;
}
コード例 #2
0
/*
 *  Sum up all the unmasked detector pixels.
 *
 * @param rebinnedWS: workspace where all the wavelength bins have been grouped together
 * @param sum: sum of all the unmasked detector pixels (counts)
 * @param error: error on sum (counts)
 * @param nPixels: number of unmasked detector pixels that contributed to sum
 */
void CalculateEfficiency::sumUnmaskedDetectors(MatrixWorkspace_sptr rebinnedWS,
    double& sum, double& error, int& nPixels)
{
    // Number of spectra
    const int numberOfSpectra = static_cast<int>(rebinnedWS->getNumberHistograms());
    sum = 0.0;
    error = 0.0;
    nPixels = 0;

    for (int i = 0; i < numberOfSpectra; i++)
    {
      progress(0.2+0.2*i/numberOfSpectra, "Computing sensitivity");
      // Get the detector object for this spectrum
      IDetector_const_sptr det = rebinnedWS->getDetector(i);
      // If this detector is masked, skip to the next one
      if ( det->isMasked() ) continue;
      // If this detector is a monitor, skip to the next one
      if ( det->isMonitor() ) continue;

      // Retrieve the spectrum into a vector
      const MantidVec& YValues = rebinnedWS->readY(i);
      const MantidVec& YErrors = rebinnedWS->readE(i);

      sum += YValues[0];
      error += YErrors[0]*YErrors[0];
      nPixels++;
    }

    error = std::sqrt(error);
}
コード例 #3
0
/** Get instrument geometry setup including L2 for each detector and L1
  */
void CreateLogTimeCorrection::getInstrumentSetup() {
  // 1. Get sample position and source position
  IComponent_const_sptr sample = m_instrument->getSample();
  if (!sample) {
    throw runtime_error("No sample has been set.");
  }
  V3D samplepos = sample->getPos();

  IComponent_const_sptr source = m_instrument->getSource();
  if (!source) {
    throw runtime_error("No source has been set.");
  }
  V3D sourcepos = source->getPos();
  m_L1 = sourcepos.distance(samplepos);

  // 2. Get detector IDs
  std::vector<detid_t> detids = m_instrument->getDetectorIDs(true);
  for (auto &detid : detids) {
    IDetector_const_sptr detector = m_instrument->getDetector(detid);
    V3D detpos = detector->getPos();
    double l2 = detpos.distance(samplepos);
    m_l2map.emplace(detid, l2);
  }

  // 3. Output information
  g_log.information() << "Sample position = " << samplepos << "; "
                      << "Source position = " << sourcepos << ", L1 = " << m_L1
                      << "; "
                      << "Number of detector/pixels = " << detids.size()
                      << ".\n";
}
コード例 #4
0
/** Extract mask information from a workspace containing instrument
  * @return vector of detector IDs of detectors that are masked
  */
std::vector<detid_t> ExtractMaskToTable::extractMaskFromMatrixWorkspace() {
  // Clear input
  std::vector<detid_t> maskeddetids;

  // Get on hold of instrument
  Instrument_const_sptr instrument = m_dataWS->getInstrument();
  if (!instrument)
    throw runtime_error("There is no instrument in input workspace.");

  // Extract
  size_t numdets = instrument->getNumberDetectors();
  vector<detid_t> detids = instrument->getDetectorIDs();

  for (size_t i = 0; i < numdets; ++i) {
    detid_t tmpdetid = detids[i];
    IDetector_const_sptr tmpdetector = instrument->getDetector(tmpdetid);
    bool masked = tmpdetector->isMasked();
    if (masked) {
      maskeddetids.push_back(tmpdetid);
    }
    g_log.debug() << "[DB] Detector No. " << i << ":  ID = " << tmpdetid
                  << ", Masked = " << masked << ".\n";
  }

  g_log.notice() << "Extract mask:  There are " << maskeddetids.size()
                 << " detectors that"
                    " are masked."
                 << ".\n";

  return maskeddetids;
}
コード例 #5
0
    /**
     * Execute the algorithm
     */
    void ExtractMasking::exec()
    {
      MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace");

      const int nHist = static_cast<int>(inputWS->getNumberHistograms());
      const int xLength(1), yLength(1);
      // Create a new workspace for the results, copy from the input to ensure that we copy over the instrument and current masking
      MatrixWorkspace_sptr outputWS = WorkspaceFactory::Instance().create(inputWS, nHist, xLength, yLength);

      Progress prog(this,0.0,1.0,nHist);
      MantidVecPtr xValues;
      xValues.access() = MantidVec(1, 0.0);

      PARALLEL_FOR2(inputWS, outputWS)
      for( int i = 0; i < nHist; ++i )
      {
        PARALLEL_START_INTERUPT_REGION
        // Spectrum in the output workspace
        ISpectrum * outSpec = outputWS->getSpectrum(i);
        // Spectrum in the input workspace
        const ISpectrum * inSpec = inputWS->getSpectrum(i);

        // Copy X, spectrum number and detector IDs
        outSpec->setX(xValues);
        outSpec->copyInfoFrom(*inSpec);

        IDetector_const_sptr inputDet;
        bool inputIsMasked(false);
        try
        {
          inputDet = inputWS->getDetector(i);
          if( inputDet->isMasked() )
          {
            inputIsMasked = true;
          }
        }
        catch(Kernel::Exception::NotFoundError &)
        {
          inputIsMasked = false;
        }

        if( inputIsMasked )
        {
          outSpec->dataY()[0] = 0.0;
          outSpec->dataE()[0] = 0.0;
        }
        else
        {
          outSpec->dataY()[0] = 1.0;
          outSpec->dataE()[0] = 1.0;
        }
        prog.report();

        PARALLEL_END_INTERUPT_REGION
      }
      PARALLEL_CHECK_INTERUPT_REGION

      setProperty("OutputWorkspace", outputWS);
    }
コード例 #6
0
void SANSSolidAngleCorrection::execEvent() {
  MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");

  // generate the output workspace pointer
  MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
  if (outputWS != inputWS) {
    outputWS = inputWS->clone();
    setProperty("OutputWorkspace", outputWS);
  }
  auto outputEventWS = boost::dynamic_pointer_cast<EventWorkspace>(outputWS);

  const int numberOfSpectra =
      static_cast<int>(outputEventWS->getNumberHistograms());
  Progress progress(this, 0.0, 1.0, numberOfSpectra);
  progress.report("Solid Angle Correction");

  PARALLEL_FOR1(outputEventWS)
  for (int i = 0; i < numberOfSpectra; i++) {
    PARALLEL_START_INTERUPT_REGION
    IDetector_const_sptr det;
    try {
      det = outputEventWS->getDetector(i);
    } catch (Exception::NotFoundError &) {
      g_log.warning() << "Workspace index " << i
                      << " has no detector assigned to it - discarding\n";
      // Catch if no detector. Next line tests whether this happened - test
      // placed
      // outside here because Mac Intel compiler doesn't like 'continue' in a
      // catch
      // in an openmp block.
    }
    if (!det)
      continue;

    // Skip if we have a monitor or if the detector is masked.
    if (det->isMonitor() || det->isMasked())
      continue;

    // Compute solid angle correction factor
    const bool is_tube = getProperty("DetectorTubes");
    const double tanTheta = tan(outputEventWS->detectorTwoTheta(*det));
    const double theta_term = sqrt(tanTheta * tanTheta + 1.0);
    double corr;
    if (is_tube) {
      const double tanAlpha = tan(getYTubeAngle(det, inputWS));
      const double alpha_term = sqrt(tanAlpha * tanAlpha + 1.0);
      corr = alpha_term * theta_term * theta_term;
    } else {
      corr = theta_term * theta_term * theta_term;
    }
    EventList &el = outputEventWS->getSpectrum(i);
    el *= corr;
    progress.report("Solid Angle Correction");
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION

  setProperty("OutputMessage", "Solid angle correction applied");
}
コード例 #7
0
/**
 *
 * @param filename filename A full path to the input RAW file
 */
void LoadDetectorInfo::loadFromIsisNXS(const std::string &filename) {
  ::NeXus::File nxsFile(filename,
                        NXACC_READ); // will throw if file can't be opened

  // two types of file:
  //   - new type entry per detector
  //   - old libisis with single pressure, thickness entry for whole file

  // hold data read from file
  DetectorInfo detInfo;

  std::map<std::string, std::string> entries;
  nxsFile.getEntries(entries);
  if (entries.find("full_reference_detector") != entries.end()) {
    nxsFile.openGroup("full_reference_detector", "NXIXTdetector");
    readLibisisNxs(nxsFile, detInfo);
    nxsFile.closeGroup();
  } else if (entries.find("detectors.dat") != entries.end()) {
    nxsFile.openGroup("detectors.dat", "NXEntry");
    readNXSDotDat(nxsFile, detInfo);
    nxsFile.closeGroup();
  } else {
    throw std::invalid_argument("Unknown NeXus file type");
  }
  nxsFile.close();

  // Start loop over detectors
  auto &pmap = m_workspace->instrumentParameters();
  int numDets = static_cast<int>(detInfo.ids.size());
  for (int i = 0; i < numDets; ++i) {
    detid_t detID = detInfo.ids[i];
    int code = detInfo.codes[i];
    IDetector_const_sptr det;
    try {
      det = m_baseInstrument->getDetector(detID);
    } catch (Exception::NotFoundError &) {
      continue;
    }
    if (det->isMonitor() || code == 1)
      continue;

    // Positions
    double l2 = detInfo.l2[i];
    double theta = detInfo.theta[i];
    double phi = detInfo.phi[i];

    // Parameters
    double delta = detInfo.delays[i];
    // offset value is be subtracted so store negative
    delta *= -1.0;
    // pressure, wall thickness
    double pressure = detInfo.pressures[i];
    double thickness = detInfo.thicknesses[i];

    updateParameterMap(pmap, det, l2, theta, phi, delta, pressure, thickness);
  }
}
コード例 #8
0
ファイル: SofQW2.cpp プロジェクト: BigShows/mantid
    /**
     * A map detector ID and Q ranges
     * This method looks unnecessary as it could be calculated on the fly but
     * the parallelization means that lazy instantation slows it down due to the
     * necessary CRITICAL sections required to update the cache. The Q range
     * values are required very frequently so the total time is more than
     * offset by this precaching step
     */
    void SofQW2::initThetaCache(API::MatrixWorkspace_const_sptr workspace)
    {
      const size_t nhist = workspace->getNumberHistograms();
      m_thetaPts = std::vector<double>(nhist);
      size_t ndets(0);
      double minTheta(DBL_MAX), maxTheta(-DBL_MAX);

      for(int64_t i = 0 ; i < (int64_t)nhist; ++i) //signed for OpenMP
      {

        m_progress->report("Calculating detector angles");
        IDetector_const_sptr det;
        try
        {
          det = workspace->getDetector(i);
          // Check to see if there is an EFixed, if not skip it
          try
          {
            m_EmodeProperties.getEFixed(det);
          }
          catch(std::runtime_error&)
          {
            det.reset();
          }
        }
        catch(Kernel::Exception::NotFoundError&)
        {
          // Catch if no detector. Next line tests whether this happened - test placed
          // outside here because Mac Intel compiler doesn't like 'continue' in a catch
          // in an openmp block.
        }
        // If no detector found, skip onto the next spectrum
        if( !det || det->isMonitor() )
        {
          m_thetaPts[i] = -1.0; // Indicates a detector to skip
        }
        else
        {
          ++ndets;
          const double theta = workspace->detectorTwoTheta(det);
          m_thetaPts[i] = theta;
          if( theta < minTheta )
          {
            minTheta = theta;
          }
          else if( theta > maxTheta )
          {
            maxTheta = theta;
          }
        }
      }

      m_thetaWidth = (maxTheta - minTheta)/static_cast<double>(ndets);
      g_log.information() << "Calculated detector width in theta=" << (m_thetaWidth*180.0/M_PI) << " degrees.\n";
    }
コード例 #9
0
/**
 * @param filename A full path to the input RAW file
 */
void LoadDetectorInfo::loadFromRAW(const std::string &filename) {
  ISISRAW2 iraw;
  if (iraw.readFromFile(filename.c_str(), false) != 0) {
    throw Exception::FileError("Unable to access raw file:", filename);
  }

  const int numDets = iraw.i_det;
  const int numUserTables = iraw.i_use;
  int pressureTabNum(0), thicknessTabNum(0);
  if (numUserTables == 10) {
    pressureTabNum = 7;
    thicknessTabNum = 8;
  } else if (numUserTables == 14) {
    pressureTabNum = 11;
    thicknessTabNum = 12;
  } else {
    throw std::invalid_argument(
        "RAW file contains unexpected number of user tables=" +
        std::to_string(numUserTables) + ". Expected 10 or 14.");
  }

  // Is ut01 (=phi) present? Sometimes an array is present but has wrong values
  // e.g.all 1.0 or all 2.0
  bool phiPresent = (iraw.ut[0] != 1.0 && iraw.ut[0] != 2.0);

  // Start loop over detectors
  auto &pmap = m_workspace->instrumentParameters();
  for (int i = 0; i < numDets; ++i) {
    detid_t detID = static_cast<detid_t>(iraw.udet[i]);
    int code = iraw.code[i];
    IDetector_const_sptr det;
    try {
      det = m_baseInstrument->getDetector(detID);
    } catch (Exception::NotFoundError &) {
      continue;
    }
    if (det->isMonitor() || code == 1)
      continue;

    // Positions
    float l2 = iraw.len2[i];
    float theta = iraw.tthe[i];
    float phi = (phiPresent ? iraw.ut[i] : 0.0f);

    // Parameters
    float delta = iraw.delt[i];
    // offset value is be subtracted so store negative
    delta *= -1.0f;
    // pressure, wall thickness
    float pressure = iraw.ut[i + pressureTabNum * numDets];
    float thickness = iraw.ut[i + thicknessTabNum * numDets];

    updateParameterMap(pmap, det, l2, theta, phi, delta, pressure, thickness);
  }
}
コード例 #10
0
ファイル: InstrumentActor.cpp プロジェクト: stothe2/mantid
/** If needed, cache the detector positions for all detectors.
 * Call this BEFORE getDetPos().
 * Does nothing if the positions have already been cached.
 */
void InstrumentActor::cacheDetPos() const
{
    if (m_detPos.size() != m_detIDs.size())
    {
        m_detPos.clear();
        for (size_t i=0; i<m_detIDs.size(); i++)
        {
            IDetector_const_sptr det = this->getDetector(i);
            m_detPos.push_back( det->getPos() );
        }
    }
}
コード例 #11
0
/// Calculate the distances traversed by the neutrons within the sample
/// @param detector :: The detector we are working on
/// @param L2s :: A vector of the sample-detector distance for  each segment of
/// the sample
void AbsorptionCorrection::calculateDistances(
    const IDetector_const_sptr &detector, std::vector<double> &L2s) const {
  V3D detectorPos(detector->getPos());
  if (detector->nDets() > 1) {
    // We need to make sure this is right for grouped detectors - should use
    // average theta & phi
    detectorPos.spherical(detectorPos.norm(),
                          detector->getTwoTheta(V3D(), V3D(0, 0, 1)) * 180.0 /
                              M_PI,
                          detector->getPhi() * 180.0 / M_PI);
  }

  for (size_t i = 0; i < m_numVolumeElements; ++i) {
    // Create track for distance in cylinder between scattering point and
    // detector
    V3D direction = detectorPos - m_elementPositions[i];
    direction.normalize();
    Track outgoing(m_elementPositions[i], direction);
    int temp = m_sampleObject->interceptSurface(outgoing);

    /* Most of the time, the number of hits is 1. Sometime, we have more than
     * one intersection due to
     * arithmetic imprecision. If it is the case, then selecting the first
     * intersection is valid.
     * In principle, one could check the consistency of all distances if hits is
     * larger than one by doing:
     * Mantid::Geometry::Track::LType::const_iterator it=outgoing.begin();
     * and looping until outgoing.end() checking the distances with it->Dist
     */
    // Not hitting the cylinder from inside, usually means detector is badly
    // defined,
    // i.e, position is (0,0,0).
    if (temp < 1) {
      // FOR NOW AT LEAST, JUST IGNORE THIS ERROR AND USE A ZERO PATH LENGTH,
      // WHICH I RECKON WILL MAKE A
      // NEGLIGIBLE DIFFERENCE ANYWAY (ALWAYS SEEMS TO HAPPEN WITH ELEMENT RIGHT
      // AT EDGE OF SAMPLE)
      L2s[i] = 0.0;

      // std::ostringstream message;
      // message << "Problem with detector at " << detectorPos << " ID:" <<
      // detector->getID() << std::endl;
      // message << "This usually means that this detector is defined inside the
      // sample cylinder";
      // g_log.error(message.str());
      // throw std::runtime_error("Problem in
      // AbsorptionCorrection::calculateDistances");
    } else // The normal situation
    {
      L2s[i] = outgoing.begin()->distFromStart;
    }
  }
}
コード例 #12
0
// calculate time from sample to detector
void ModeratorTzeroLinear::calculateTfLi(MatrixWorkspace_const_sptr inputWS,
                                         size_t i, double &t_f, double &L_i) {
  static const double convFact = 1.0e-6 * sqrt(2 * PhysicalConstants::meV /
                                               PhysicalConstants::NeutronMass);
  static const double TfError = -1.0; // signal error when calculating final
                                      // time
  // Get detector position
  IDetector_const_sptr det;
  try {
    det = inputWS->getDetector(i);
  } catch (Exception::NotFoundError &) {
    t_f = TfError;
    return;
  }

  if (det->isMonitor()) {
    L_i = m_instrument->getSource()->getDistance(*det);
    t_f = 0.0; // t_f=0.0 since there is no sample to detector path
  } else {
    IComponent_const_sptr sample = m_instrument->getSample();
    try {
      L_i = m_instrument->getSource()->getDistance(*sample);
    } catch (Exception::NotFoundError &) {
      g_log.error("Unable to calculate source-sample distance");
      throw Exception::InstrumentDefinitionError(
          "Unable to calculate source-sample distance", inputWS->getTitle());
    }
    // Get final energy E_f, final velocity v_f
    std::vector<double> wsProp = det->getNumberParameter("Efixed");
    if (!wsProp.empty()) {
      double E_f = wsProp.at(0);         //[E_f]=meV
      double v_f = convFact * sqrt(E_f); //[v_f]=meter/microsec

      try {
        // obtain L_f, calculate t_f
        double L_f = det->getDistance(*sample);
        t_f = L_f / v_f;
        // g_log.debug() << "detector: " << i << " L_f=" << L_f << " t_f=" <<
        // t_f << '\n';
      } catch (Exception::NotFoundError &) {
        g_log.error("Unable to calculate detector-sample distance");
        throw Exception::InstrumentDefinitionError(
            "Unable to calculate detector-sample distance",
            inputWS->getTitle());
      }
    } else {
      g_log.debug() << "Efixed not found for detector " << i << '\n';
      t_f = TfError;
    }
  }
} // end of CalculateTf(const MatrixWorkspace_sptr inputWS, size_t i)
コード例 #13
0
ファイル: GetEi.cpp プロジェクト: Mantid-Test-Account/mantid
/** Gets the distances between the source and detectors whose IDs you pass to it
*  @param WS :: the input workspace
*  @param mon0Spec :: Spectrum number of the output from the first monitor
*  @param mon1Spec :: Spectrum number of the output from the second monitor
*  @param monitor0Dist :: the calculated distance to the detector whose ID was
* passed to this function first
*  @param monitor1Dist :: calculated distance to the detector whose ID was
* passed to this function second
*  @throw NotFoundError if no detector is found for the detector ID given
*/
void GetEi::getGeometry(API::MatrixWorkspace_const_sptr WS, specid_t mon0Spec,
                        specid_t mon1Spec, double &monitor0Dist,
                        double &monitor1Dist) const {
    const IComponent_const_sptr source = WS->getInstrument()->getSource();

    // retrieve a pointer to the first detector and get its distance
    size_t monWI = 0;
    try {
        monWI = WS->getIndexFromSpectrumNumber(mon0Spec);
    } catch (std::runtime_error &) {
        g_log.error()
                << "Could not find the workspace index for the monitor at spectrum "
                << mon0Spec << "\n";
        g_log.error() << "Error retrieving data for the first monitor" << std::endl;
        throw std::bad_cast();
    }
    const std::set<detid_t> &dets = WS->getSpectrum(monWI)->getDetectorIDs();

    if (dets.size() != 1) {
        g_log.error() << "The detector for spectrum number " << mon0Spec
                      << " was either not found or is a group, grouped monitors "
                      "are not supported by this algorithm\n";
        g_log.error() << "Error retrieving data for the first monitor" << std::endl;
        throw std::bad_cast();
    }
    IDetector_const_sptr det = WS->getInstrument()->getDetector(*dets.begin());
    monitor0Dist = det->getDistance(*(source.get()));

    // repeat for the second detector
    try {
        monWI = WS->getIndexFromSpectrumNumber(mon0Spec);
    } catch (std::runtime_error &) {
        g_log.error()
                << "Could not find the workspace index for the monitor at spectrum "
                << mon0Spec << "\n";
        g_log.error() << "Error retrieving data for the second monitor\n";
        throw std::bad_cast();
    }
    const std::set<detid_t> &dets2 = WS->getSpectrum(monWI)->getDetectorIDs();
    if (dets2.size() != 1) {
        g_log.error() << "The detector for spectrum number " << mon1Spec
                      << " was either not found or is a group, grouped monitors "
                      "are not supported by this algorithm\n";
        g_log.error() << "Error retrieving data for the second monitor\n";
        throw std::bad_cast();
    }
    det = WS->getInstrument()->getDetector(*dets2.begin());
    monitor1Dist = det->getDistance(*(source.get()));
}
コード例 #14
0
double
ConvertSpectrumAxis::getEfixed(const Mantid::Geometry::IDetector &detector,
                               MatrixWorkspace_const_sptr inputWS,
                               int emode) const {
  double efixed(0);
  double efixedProp = getProperty("Efixed");
  if (efixedProp != EMPTY_DBL()) {
    efixed = efixedProp;
    g_log.debug() << "Detector: " << detector.getID() << " Efixed: " << efixed
                  << "\n";
  } else {
    if (emode == 1) {
      if (inputWS->run().hasProperty("Ei")) {
        Kernel::Property *p = inputWS->run().getProperty("Ei");
        Kernel::PropertyWithValue<double> *doublep =
            dynamic_cast<Kernel::PropertyWithValue<double> *>(p);
        if (doublep) {
          efixed = (*doublep)();
        } else {
          efixed = 0.0;
          g_log.warning() << "Efixed could not be found for detector "
                          << detector.getID() << ", set to 0.0\n";
        }
      } else {
        efixed = 0.0;
        g_log.warning() << "Efixed could not be found for detector "
                        << detector.getID() << ", set to 0.0\n";
      }
    } else if (emode == 2) {
      std::vector<double> efixedVec = detector.getNumberParameter("Efixed");
      if (efixedVec.empty()) {
        int detid = detector.getID();
        IDetector_const_sptr detectorSingle =
            inputWS->getInstrument()->getDetector(detid);
        efixedVec = detectorSingle->getNumberParameter("Efixed");
      }
      if (!efixedVec.empty()) {
        efixed = efixedVec.at(0);
        g_log.debug() << "Detector: " << detector.getID()
                      << " EFixed: " << efixed << "\n";
      } else {
        efixed = 0.0;
        g_log.warning() << "Efixed could not be found for detector "
                        << detector.getID() << ", set to 0.0\n";
      }
    }
  }
  return efixed;
}
コード例 #15
0
 /** Execute the algorithm.
  */
 void WeightedMeanOfWorkspace::exec()
 {
   MatrixWorkspace_sptr inputWS = this->getProperty("InputWorkspace");
   // Check if it is an event workspace
   EventWorkspace_const_sptr eventW = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS);
   if (eventW != NULL)
   {
     throw std::runtime_error("WeightedMeanOfWorkspace cannot handle EventWorkspaces!");
   }
   // Create the output workspace
   MatrixWorkspace_sptr singleValued = WorkspaceFactory::Instance().create("WorkspaceSingleValue", 1, 1, 1);
   // Calculate weighted mean
   std::size_t numHists = inputWS->getNumberHistograms();
   double averageValue = 0.0;
   double weightSum = 0.0;
   for (std::size_t i = 0; i < numHists; ++i)
   {
     try
     {
       IDetector_const_sptr det = inputWS->getDetector(i);
       if( det->isMonitor() || det->isMasked() )
       {
         continue;
       }
     }
     catch (...)
     {
       // Swallow these if no instrument is found
       ;
     }
     MantidVec y = inputWS->dataY(i);
     MantidVec e = inputWS->dataE(i);
     double weight = 0.0;
     for (std::size_t j = 0; j < y.size(); ++j)
     {
       if (!boost::math::isnan(y[j]) && !boost::math::isinf(y[j]) &&
           !boost::math::isnan(e[j]) && !boost::math::isinf(e[j]))
       {
         weight = 1.0 / (e[j] * e[j]);
         averageValue += (y[j] * weight);
         weightSum += weight;
       }
     }
   }
   singleValued->dataX(0)[0] = 0.0;
   singleValued->dataY(0)[0] = averageValue / weightSum;
   singleValued->dataE(0)[0] = std::sqrt(weightSum);
   this->setProperty("OutputWorkspace", singleValued);
 }
コード例 #16
0
ファイル: LoadDetectorInfo.cpp プロジェクト: BigShows/mantid
    /**
     * Full format is defined in doc text
     * @param filename A full path to the input DAT file
     */
    void LoadDetectorInfo::loadFromDAT(const std::string & filename)
    {
      std::ifstream datFile(filename.c_str());
      if(!datFile)
      {
        throw Exception::FileError("Unable to access dat file", filename);
      }

      std::string line;
      // skip 3 lines of header info
      for(int i = 0; i < 3; ++i) getline(datFile, line);

      // start loop over file
      auto & pmap = m_workspace->instrumentParameters();
      while(getline(datFile, line))
      {
        if(line.empty() || line[0] == '#') continue;

        std::istringstream is(line);
        detid_t detID(0);
        int code(0);
        float droppedFloat(0.0f);
        float delta(0.0f), l2(0.0f), theta(0.0f), phi(0.0f);
        is >> detID >> delta >> l2 >> code >> theta >> phi;
        // offset value is be subtracted so store negative
        delta *= -1.0f;

        IDetector_const_sptr det;
        try
        {
          det = m_baseInstrument->getDetector(detID);
        }
        catch(Exception::NotFoundError&)
        {
          continue;
        }
        if(det->isMonitor() || code == 1) continue;

        // drop 10 float columns
        for(int i = 0; i < 10; ++i) is >> droppedFloat;

        // pressure, wall thickness
        float pressure(0.0), thickness(0.0);
        is >> pressure >> thickness;

        updateParameterMap(pmap, det, l2, theta, phi, delta, pressure, thickness);
      }
    }
コード例 #17
0
//calculate time from sample to detector
double ModeratorTzero::CalculateT2(MatrixWorkspace_sptr inputWS, size_t i)
{
  static const double convFact = 1.0e-6*sqrt(2*PhysicalConstants::meV/PhysicalConstants::NeutronMass);
  double t2(-1.0); // negative initialization signals error
  // Get detector position
  IDetector_const_sptr det;
  try
  {
    det = inputWS->getDetector(i);
  }
  catch (Exception::NotFoundError&)
  {
    return t2;
  }

  if( det->isMonitor() )
  {
    t2 = 0.0; //t2=0.0 since there is no sample to detector path
  }
  else
  {
    IComponent_const_sptr sample = m_instrument->getSample();
    // Get final energy E_f, final velocity v_f
    std::vector< double >  wsProp=det->getNumberParameter("Efixed");
    if ( !wsProp.empty() )
    {
      double E2 = wsProp.at(0); //[E2]=meV
      double v2 = convFact * sqrt(E2); //[v2]=meter/microsec
      try
      {
        double L2 = det->getDistance(*sample);
        t2 = L2 / v2;
      }
      catch (Exception::NotFoundError &)
      {
        g_log.error("Unable to calculate detector-sample distance");
        throw Exception::InstrumentDefinitionError("Unable to calculate detector-sample distance", inputWS->getTitle());
      }
    }
    else
    {
      g_log.debug() <<"Efixed not found for detector "<< i << std::endl;
    }
  }
  return t2;
} // end of CalculateT2(const MatrixWorkspace_sptr inputWS, size_t i)
コード例 #18
0
/** Gets the results of the trace, then returns the first detector
 * (that is NOT a monitor) found in the results.
 * @return sptr to IDetector, or an invalid sptr if not found
 */
IDetector_const_sptr InstrumentRayTracer::getDetectorResult() const {
  Links results = this->getResults();

  // Go through all results
  Links::const_iterator resultItr = results.begin();
  for (; resultItr != results.end(); ++resultItr) {
    IComponent_const_sptr component =
        m_instrument->getComponentByID(resultItr->componentID);
    IDetector_const_sptr det =
        boost::dynamic_pointer_cast<const IDetector>(component);
    if (det) {
      if (!det->isMonitor()) {
        return det;
      }
    } // (is a detector)
  }   // each ray tracer result
  return IDetector_const_sptr();
}
コード例 #19
0
/**
 * Get the list of detectors associated with a spectra
 * @param instrument :: A pointer to the instrument
 * @param spectraMap :: A reference to the spectra map
 * @returns A map of spectra number to detector pointer
 */
std::map<specid_t, IDetector_const_sptr> NearestNeighbours::getSpectraDetectors(
    boost::shared_ptr<const Instrument> instrument,
    const ISpectrumDetectorMapping &spectraMap) {
  std::map<specid_t, IDetector_const_sptr> spectra;
  if (spectraMap.empty())
    return spectra;
  ISpectrumDetectorMapping::const_iterator cend = spectraMap.cend();
  for (ISpectrumDetectorMapping::const_iterator citr = spectraMap.cbegin();
       citr != cend; ++citr) {
    const std::vector<detid_t> detIDs(citr->second.begin(), citr->second.end());
    IDetector_const_sptr det = instrument->getDetectorG(detIDs);
    // Always ignore monitors and ignore masked detectors if requested.
    bool heedMasking = !m_bIgnoreMaskedDetectors && det->isMasked();
    if (!det->isMonitor() && !heedMasking) {
      spectra.insert(std::make_pair(citr->first, det));
    }
  }
  return spectra;
}
コード例 #20
0
Correction
TimeAtSampleStrategyIndirect::calculate(const size_t &workspace_index) const {

  // A constant among all spectra
  double twomev_d_mass =
      2. * PhysicalConstants::meV / PhysicalConstants::NeutronMass;
  V3D samplepos = m_ws->getInstrument()->getSample()->getPos();

  // Get the parameter map
  const ParameterMap &pmap = m_ws->constInstrumentParameters();

  double shift;
  IDetector_const_sptr det = m_ws->getDetector(workspace_index);
  if (!det->isMonitor()) {
    // Get E_fix
    double efix = 0.;
    try {
      Parameter_sptr par = pmap.getRecursive(det.get(), "Efixed");
      if (par) {
        efix = par->value<double>();
      }
    } catch (std::runtime_error &) {
      // Throws if a DetectorGroup, use single provided value
      std::stringstream errmsg;
      errmsg << "Inelastic instrument detector " << det->getID()
             << " of spectrum " << workspace_index << " does not have EFixed ";
      throw std::runtime_error(errmsg.str());
    }

    // Get L2
    double l2 = det->getPos().distance(samplepos);

    // Calculate shift
    shift = -1. * l2 / sqrt(efix * twomev_d_mass);

  } else {
    std::stringstream errormsg;
    errormsg << "Workspace index " << workspace_index << " is a monitor. ";
    throw std::invalid_argument(errormsg.str());
  }
  return Correction(1.0, shift);
}
コード例 #21
0
ファイル: AnvredCorrection.cpp プロジェクト: BigShows/mantid
  void AnvredCorrection::scale_init(IDetector_const_sptr det, Instrument_const_sptr inst, int& bank, double& L2, double& depth, double& pathlength, std::string bankName)
  {
	bankName = det->getParent()->getParent()->getName();
	std::string bankNameStr = bankName;
	// Take out the "bank" part of the bank name and convert to an int
	bankNameStr.erase(remove_if(bankNameStr.begin(), bankNameStr.end(), not1(std::ptr_fun (::isdigit))), bankNameStr.end());
	Strings::convert(bankNameStr, bank);
	IComponent_const_sptr sample = inst->getSample();
	double cosA = inst->getComponentByName(bankName)->getDistance(*sample) / L2;
	pathlength = depth / cosA;
  }
コード例 #22
0
/** Convert X axis to Elastic Q representation
* @param progress :: Progress indicator
* @param targetUnit :: Target conversion unit
* @param inputWS :: Input workspace
* @param nHist :: Stores the number of histograms
*/
void ConvertSpectrumAxis2::createElasticQMap(API::Progress &progress,
                                             const std::string &targetUnit,
                                             API::MatrixWorkspace_sptr &inputWS,
                                             size_t nHist) {
  IComponent_const_sptr source = inputWS->getInstrument()->getSource();
  IComponent_const_sptr sample = inputWS->getInstrument()->getSample();

  const std::string emodeStr = getProperty("EMode");
  int emode = 0;
  if (emodeStr == "Direct")
    emode = 1;
  else if (emodeStr == "Indirect")
    emode = 2;

  for (size_t i = 0; i < nHist; i++) {
    IDetector_const_sptr detector = inputWS->getDetector(i);
    double twoTheta(0.0), efixed(0.0);
    if (!detector->isMonitor()) {
      twoTheta = 0.5 * inputWS->detectorTwoTheta(*detector);
      efixed = getEfixed(detector, inputWS, emode); // get efixed
    } else {
      twoTheta = 0.0;
      efixed = DBL_MIN;
    }

    // Convert to MomentumTransfer
    double elasticQInAngstroms = Kernel::UnitConversion::run(twoTheta, efixed);

    if (targetUnit == "ElasticQ") {
      m_indexMap.emplace(elasticQInAngstroms, i);
    } else if (targetUnit == "ElasticQSquared") {
      // The QSquared value.
      double elasticQSquaredInAngstroms =
          elasticQInAngstroms * elasticQInAngstroms;

      m_indexMap.emplace(elasticQSquaredInAngstroms, i);
    }

    progress.report("Converting to Elastic Q...");
  }
}
コード例 #23
0
double ConvertSpectrumAxis2::getEfixed(IDetector_const_sptr detector,
                                       MatrixWorkspace_const_sptr inputWS,
                                       int emode) const {
  double efixed(0);
  double efixedProp = getProperty("Efixed");
  if (efixedProp != EMPTY_DBL()) {
    efixed = efixedProp;
    g_log.debug() << "Detector: " << detector->getID() << " Efixed: " << efixed
                  << "\n";
  } else {
    if (emode == 1) {
      if (inputWS->run().hasProperty("Ei")) {
        efixed = inputWS->run().getLogAsSingleValue("Ei");
      } else {
        throw std::invalid_argument("Could not retrieve Efixed from the "
                                    "workspace. Please provide a value.");
      }
    } else if (emode == 2) {
      std::vector<double> efixedVec = detector->getNumberParameter("Efixed");
      if (efixedVec.empty()) {
        int detid = detector->getID();
        IDetector_const_sptr detectorSingle =
            inputWS->getInstrument()->getDetector(detid);
        efixedVec = detectorSingle->getNumberParameter("Efixed");
      }
      if (!efixedVec.empty()) {
        efixed = efixedVec.at(0);
        g_log.debug() << "Detector: " << detector->getID()
                      << " EFixed: " << efixed << "\n";
      } else {
        g_log.warning() << "Efixed could not be found for detector "
                        << detector->getID() << ", please provide a value\n";
        throw std::invalid_argument("Could not retrieve Efixed from the "
                                    "detector. Please provide a value.");
      }
    }
  }
  return efixed;
}
コード例 #24
0
/**
 * Execution path for NormalisedPolygon Rebinning
 * @param inputWS : Workspace to be rebinned
 * @param vertexes : TableWorkspace for debugging purposes
 * @param dumpVertexes : determines whether vertexes will be written to for
 * debugging purposes or not
 * @param outputDimensions : used for the column headings for Dump Vertexes
 */
MatrixWorkspace_sptr ReflectometryTransform::executeNormPoly(
    MatrixWorkspace_const_sptr inputWS,
    boost::shared_ptr<Mantid::DataObjects::TableWorkspace> &vertexes,
    bool dumpVertexes, std::string outputDimensions) const {
  MatrixWorkspace_sptr temp = WorkspaceFactory::Instance().create(
      "RebinnedOutput", m_d1NumBins, m_d0NumBins, m_d0NumBins);
  RebinnedOutput_sptr outWS = boost::static_pointer_cast<RebinnedOutput>(temp);

  const double widthD0 = (m_d0Max - m_d0Min) / double(m_d0NumBins);
  const double widthD1 = (m_d1Max - m_d1Min) / double(m_d1NumBins);

  std::vector<double> xBinsVec;
  std::vector<double> zBinsVec;
  VectorHelper::createAxisFromRebinParams({m_d1Min, widthD1, m_d1Max},
                                          zBinsVec);
  VectorHelper::createAxisFromRebinParams({m_d0Min, widthD0, m_d0Max},
                                          xBinsVec);

  // Put the correct bin boundaries into the workspace
  auto verticalAxis = new BinEdgeAxis(zBinsVec);
  outWS->replaceAxis(1, verticalAxis);
  for (size_t i = 0; i < zBinsVec.size() - 1; ++i)
    outWS->setX(i, xBinsVec);

  verticalAxis->title() = m_d1Label;

  // Prepare the required theta values
  DetectorAngularCache cache = initAngularCaches(inputWS.get());
  m_theta = cache.thetas;
  m_thetaWidths = cache.thetaWidths;

  const size_t nHistos = inputWS->getNumberHistograms();
  const size_t nBins = inputWS->blocksize();

  // Holds the spectrum-detector mapping
  std::vector<specnum_t> specNumberMapping;
  std::vector<detid_t> detIDMapping;
  // Create a table for the output if we want to debug vertex positioning
  addColumnHeadings(vertexes, outputDimensions);
  for (size_t i = 0; i < nHistos; ++i) {
    IDetector_const_sptr detector = inputWS->getDetector(i);
    if (!detector || detector->isMasked() || detector->isMonitor()) {
      continue;
    }

    // Compute polygon points
    const double theta = m_theta[i];
    const double thetaWidth = m_thetaWidths[i];
    const double thetaHalfWidth = 0.5 * thetaWidth;
    const double thetaLower = theta - thetaHalfWidth;
    const double thetaUpper = theta + thetaHalfWidth;

    const MantidVec &X = inputWS->readX(i);
    const MantidVec &Y = inputWS->readY(i);
    const MantidVec &E = inputWS->readE(i);
    for (size_t j = 0; j < nBins; ++j) {
      const double lamLower = X[j];
      const double lamUpper = X[j + 1];
      const double signal = Y[j];
      const double error = E[j];

      auto inputQ =
          m_calculator->createQuad(lamUpper, lamLower, thetaUpper, thetaLower);
      FractionalRebinning::rebinToFractionalOutput(inputQ, inputWS, i, j, outWS,
                                                   zBinsVec);
      // Find which qy bin this point lies in
      const auto qIndex =
          std::upper_bound(zBinsVec.begin(), zBinsVec.end(), inputQ[0].Y()) -
          zBinsVec.begin();
      if (qIndex != 0 && qIndex < static_cast<int>(zBinsVec.size())) {
        // Add this spectra-detector pair to the mapping
        specNumberMapping.push_back(
            outWS->getSpectrum(qIndex - 1).getSpectrumNo());
        detIDMapping.push_back(detector->getID());
      }
      // Debugging
      if (dumpVertexes) {
        writeRow(vertexes, inputQ[0], i, j, signal, error);
        writeRow(vertexes, inputQ[1], i, j, signal, error);
        writeRow(vertexes, inputQ[2], i, j, signal, error);
        writeRow(vertexes, inputQ[3], i, j, signal, error);
      }
    }
  }
  outWS->finalize();
  FractionalRebinning::normaliseOutput(outWS, inputWS);
  // Set the output spectrum-detector mapping
  SpectrumDetectorMapping outputDetectorMap(specNumberMapping, detIDMapping);
  outWS->updateSpectraUsing(outputDetectorMap);
  outWS->getAxis(0)->title() = m_d0Label;
  outWS->setYUnit("");
  outWS->setYUnitLabel("Intensity");

  return outWS;
}
コード例 #25
0
/**
 * A map detector ID and Q ranges
 * This method looks unnecessary as it could be calculated on the fly but
 * the parallelization means that lazy instantation slows it down due to the
 * necessary CRITICAL sections required to update the cache. The Q range
 * values are required very frequently so the total time is more than
 * offset by this precaching step
 */
DetectorAngularCache initAngularCaches(const MatrixWorkspace *const workspace) {
  const size_t nhist = workspace->getNumberHistograms();
  std::vector<double> thetas(nhist);
  std::vector<double> thetaWidths(nhist);
  std::vector<double> detectorHeights(nhist);

  auto inst = workspace->getInstrument();
  const auto samplePos = inst->getSample()->getPos();
  const V3D upDirVec = inst->getReferenceFrame()->vecPointingUp();

  for (size_t i = 0; i < nhist; ++i) // signed for OpenMP
  {
    IDetector_const_sptr det;
    try {
      det = workspace->getDetector(i);
    } catch (Exception::NotFoundError &) {
      // Catch if no detector. Next line tests whether this happened - test
      // placed
      // outside here because Mac Intel compiler doesn't like 'continue' in a
      // catch
      // in an openmp block.
    }
    // If no detector found, skip onto the next spectrum
    if (!det || det->isMonitor()) {
      thetas[i] = -1.0; // Indicates a detector to skip
      thetaWidths[i] = -1.0;
      continue;
    }
    // We have to convert theta from radians to degrees
    const double theta = workspace->detectorSignedTwoTheta(*det) * rad2deg;
    thetas[i] = theta;
    /**
     * Determine width from shape geometry. A group is assumed to contain
     * detectors with the same shape & r, theta value, i.e. a ring mapped-group
     * The shape is retrieved and rotated to match the rotation of the detector.
     * The angular width is computed using the l2 distance from the sample
     */
    if (auto group = boost::dynamic_pointer_cast<const DetectorGroup>(det)) {
      // assume they all have same shape and same r,theta
      auto dets = group->getDetectors();
      det = dets[0];
    }
    const auto pos = det->getPos() - samplePos;
    double l2(0.0), t(0.0), p(0.0);
    pos.getSpherical(l2, t, p);
    // Get the shape
    auto shape =
        det->shape(); // Defined in its own reference frame with centre at 0,0,0
    BoundingBox bbox = shape->getBoundingBox();
    auto maxPoint(bbox.maxPoint());
    auto minPoint(bbox.minPoint());
    auto span = maxPoint - minPoint;
    detectorHeights[i] = span.scalar_prod(upDirVec);
    thetaWidths[i] = 2.0 * std::fabs(std::atan((detectorHeights[i] / 2) / l2)) *
                     180.0 / M_PI;
  }
  DetectorAngularCache cache;
  cache.thetas = thetas;
  cache.thetaWidths = thetaWidths;
  cache.detectorHeights = detectorHeights;
  return cache;
}
コード例 #26
0
ファイル: Q1D2.cpp プロジェクト: trnielsen/mantid
/**
  @ throw invalid_argument if the workspaces are not mututially compatible
*/
void Q1D2::exec()
{
  m_dataWS = getProperty("DetBankWorkspace");
  MatrixWorkspace_const_sptr waveAdj = getProperty("WavelengthAdj");
  MatrixWorkspace_const_sptr pixelAdj = getProperty("PixelAdj");
  MatrixWorkspace_const_sptr wavePixelAdj = getProperty("WavePixelAdj");
  const bool doGravity = getProperty("AccountForGravity");
  m_doSolidAngle = getProperty("SolidAngleWeighting");

  //throws if we don't have common binning or another incompatibility
  Qhelper helper;
  helper.examineInput(m_dataWS, waveAdj, pixelAdj);
  // FIXME: how to examine the wavePixelAdj? 
  g_log.debug() << "All input workspaces were found to be valid\n";
  // normalization as a function of wavelength (i.e. centers of x-value bins)
  double const * const binNorms = waveAdj ? &(waveAdj->readY(0)[0]) : NULL;
  // error on the wavelength normalization
  double const * const binNormEs = waveAdj ? &(waveAdj->readE(0)[0]) : NULL;

  //define the (large number of) data objects that are going to be used in all iterations of the loop below

  // this will become the output workspace from this algorithm
  MatrixWorkspace_sptr outputWS = setUpOutputWorkspace(getProperty("OutputBinning"));

  const MantidVec & QOut = outputWS->readX(0);
  MantidVec & YOut = outputWS->dataY(0);
  MantidVec & EOutTo2 = outputWS->dataE(0);
  // normalisation that is applied to counts in each Q bin
  MantidVec normSum(YOut.size(), 0.0);
  // the error on the normalisation
  MantidVec normError2(YOut.size(), 0.0);

  const int numSpec = static_cast<int>(m_dataWS->getNumberHistograms());
  Progress progress(this, 0.05, 1.0, numSpec+1);

  PARALLEL_FOR3(m_dataWS, outputWS, pixelAdj)
  for (int i = 0; i < numSpec; ++i)
  {
    PARALLEL_START_INTERUPT_REGION
    // Get the pixel relating to this spectrum
    IDetector_const_sptr det;
    try {
      det = m_dataWS->getDetector(i);
    } catch (Exception::NotFoundError&) {
      g_log.warning() << "Workspace index " << i << " (SpectrumIndex = " << m_dataWS->getSpectrum(i)->getSpectrumNo() << ") has no detector assigned to it - discarding" << std::endl;
      // Catch if no detector. Next line tests whether this happened - test placed
      // outside here because Mac Intel compiler doesn't like 'continue' in a catch
      // in an openmp block.
    }
    // If no detector found or if detector is masked shouldn't be included skip onto the next spectrum
    if ( !det || det->isMonitor() || det->isMasked() )
    {
      continue;
    }

    //get the bins that are included inside the RadiusCut/WaveCutcut off, those to calculate for
    //const size_t wavStart = waveLengthCutOff(i);
    const size_t wavStart = helper.waveLengthCutOff(m_dataWS, getProperty("RadiusCut"), getProperty("WaveCut"), i);
    if (wavStart >=  m_dataWS->readY(i).size())
    {
      // all the spectra in this detector are out of range
      continue;
    }
    
    const size_t numWavbins = m_dataWS->readY(i).size()-wavStart;
    // make just one call to new to reduce CPU overhead on each thread, access to these 
    // three "arrays" is via iterators
    MantidVec _noDirectUseStorage_(3*numWavbins);
    //normalization term
    MantidVec::iterator norms = _noDirectUseStorage_.begin();
    // the error on these weights, it contributes to the error calculation on the output workspace
    MantidVec::iterator normETo2s = norms + numWavbins;
    // the Q values calculated from input wavelength workspace
    MantidVec::iterator QIn = normETo2s + numWavbins;

    // the weighting for this input spectrum that is added to the normalization
    calculateNormalization(wavStart, i, pixelAdj, wavePixelAdj, binNorms, binNormEs, norms, normETo2s);

    // now read the data from the input workspace, calculate Q for each bin
    convertWavetoQ(i, doGravity, wavStart, QIn);

    // Pointers to the counts data and it's error
    MantidVec::const_iterator YIn = m_dataWS->readY(i).begin()+wavStart;
    MantidVec::const_iterator EIn = m_dataWS->readE(i).begin()+wavStart;

    //when finding the output Q bin remember that the input Q bins (from the convert to wavelength) start high and reduce
    MantidVec::const_iterator loc = QOut.end();
    // sum the Q contributions from each individual spectrum into the output array
    const MantidVec::const_iterator end = m_dataWS->readY(i).end();
    for( ; YIn != end; ++YIn, ++EIn, ++QIn, ++norms, ++normETo2s)
    {
      //find the output bin that each input y-value will fall into, remembering there is one more bin boundary than bins
      getQBinPlus1(QOut, *QIn, loc);
      // ignore counts that are out of the output range
      if ( (loc != QOut.begin()) && (loc != QOut.end()) )
      {
        // the actual Q-bin to add something to
        const size_t bin = loc - QOut.begin() - 1;
        PARALLEL_CRITICAL(q1d_counts_sum)
        {
          YOut[bin] += *YIn;
          normSum[bin] += *norms;
          //these are the errors squared which will be summed and square rooted at the end
          EOutTo2[bin] += (*EIn)*(*EIn);
          normError2[bin] += *normETo2s;
        }
      }
    }
    
    PARALLEL_CRITICAL(q1d_spectra_map)
    {
      progress.report("Computing I(Q)");

      // Add up the detector IDs in the output spectrum at workspace index 0
      const ISpectrum * inSpec = m_dataWS->getSpectrum(i);
      ISpectrum * outSpec = outputWS->getSpectrum(0);
      outSpec->addDetectorIDs( inSpec->getDetectorIDs() );
    }

    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION

  bool doOutputParts = getProperty("OutputParts");
  if (doOutputParts)
  {
      MatrixWorkspace_sptr ws_sumOfCounts = WorkspaceFactory::Instance().create(outputWS);
      ws_sumOfCounts->dataX(0) = outputWS->dataX(0);
      ws_sumOfCounts->dataY(0) = outputWS->dataY(0);
      for (size_t i = 0; i < outputWS->dataE(0).size(); i++)
      {
        ws_sumOfCounts->dataE(0)[i] = sqrt(outputWS->dataE(0)[i]);
      }      

      MatrixWorkspace_sptr ws_sumOfNormFactors = WorkspaceFactory::Instance().create(outputWS);
      ws_sumOfNormFactors->dataX(0) = outputWS->dataX(0);
      for (size_t i = 0; i < ws_sumOfNormFactors->dataY(0).size(); i++)
      {
        ws_sumOfNormFactors->dataY(0)[i] = normSum[i];
        ws_sumOfNormFactors->dataE(0)[i] = sqrt(normError2[i]);
      }

      helper.outputParts(this, ws_sumOfCounts, ws_sumOfNormFactors);
  }


  progress.report("Normalizing I(Q)");
  //finally divide the number of counts in each output Q bin by its weighting
  normalize(normSum, normError2, YOut, EOutTo2);

  outputWS->updateSpectraUsingMap();

  setProperty("OutputWorkspace",outputWS);
}
コード例 #27
0
void TOFSANSResolution::exec()
{
  Workspace2D_sptr iqWS = getProperty("InputWorkspace");
  MatrixWorkspace_sptr reducedWS = getProperty("ReducedWorkspace");
  EventWorkspace_sptr reducedEventWS = boost::dynamic_pointer_cast<EventWorkspace>(reducedWS);
  const double min_wl = getProperty("MinWavelength");
  const double max_wl = getProperty("MaxWavelength");
  double pixel_size_x = getProperty("PixelSizeX");
  double pixel_size_y = getProperty("PixelSizeY");
  double R1 = getProperty("SourceApertureRadius");
  double R2 = getProperty("SampleApertureRadius");
  // Convert to meters
  pixel_size_x /= 1000.0;
  pixel_size_y /= 1000.0;
  R1 /= 1000.0;
  R2 /= 1000.0;
  wl_resolution = getProperty("DeltaT");

  // Although we want the 'ReducedWorkspace' to be an event workspace for this algorithm to do
  // anything, we don't want the algorithm to 'fail' if it isn't
  if (!reducedEventWS)
  {
    g_log.warning() << "An Event Workspace is needed to compute dQ. Calculation skipped." << std::endl;
    return;
  }

  // Calculate the output binning
  const std::vector<double> binParams = getProperty("OutputBinning");

  // Count histogram for normalization
  const int xLength = static_cast<int>(iqWS->readX(0).size());
  std::vector<double> XNorm(xLength-1, 0.0);

  // Create workspaces with each component of the resolution for debugging purposes
  MatrixWorkspace_sptr thetaWS = WorkspaceFactory::Instance().create(iqWS);
  declareProperty(new WorkspaceProperty<>("ThetaError","",Direction::Output));
  setPropertyValue("ThetaError","__"+iqWS->getName()+"_theta_error");
  setProperty("ThetaError",thetaWS);
  thetaWS->setX(0,iqWS->readX(0));
  MantidVec& ThetaY = thetaWS->dataY(0);

  MatrixWorkspace_sptr tofWS = WorkspaceFactory::Instance().create(iqWS);
  declareProperty(new WorkspaceProperty<>("TOFError","",Direction::Output));
  setPropertyValue("TOFError","__"+iqWS->getName()+"_tof_error");
  setProperty("TOFError",tofWS);
  tofWS->setX(0,iqWS->readX(0));
  MantidVec& TOFY = tofWS->dataY(0);

  // Initialize Dq
  MantidVec& DxOut = iqWS->dataDx(0);
  for ( int i = 0; i<xLength-1; i++ ) DxOut[i] = 0.0;

  const V3D samplePos = reducedWS->getInstrument()->getSample()->getPos();
  const V3D sourcePos = reducedWS->getInstrument()->getSource()->getPos();
  const V3D SSD = samplePos - sourcePos;
  const double L1 = SSD.norm();

  const int numberOfSpectra = static_cast<int>(reducedWS->getNumberHistograms());
  Progress progress(this,0.0,1.0,numberOfSpectra);

  PARALLEL_FOR2(reducedEventWS, iqWS)
  for (int i = 0; i < numberOfSpectra; i++)
  {
    PARALLEL_START_INTERUPT_REGION
    IDetector_const_sptr det;
    try {
      det = reducedEventWS->getDetector(i);
    } catch (Exception::NotFoundError&) {
      g_log.warning() << "Spectrum index " << i << " has no detector assigned to it - discarding" << std::endl;
      // Catch if no detector. Next line tests whether this happened - test placed
      // outside here because Mac Intel compiler doesn't like 'continue' in a catch
      // in an openmp block.
    }
    // If no detector found or if it's masked or a monitor, skip onto the next spectrum
    if ( !det || det->isMonitor() || det->isMasked() ) continue;

    // Get the flight path from the sample to the detector pixel
    const V3D scattered_flight_path = det->getPos() - samplePos;

    // Multiplicative factor to go from lambda to Q
    // Don't get fooled by the function name...
    const double theta = reducedEventWS->detectorTwoTheta(det);
    const double factor = 4.0 * M_PI * sin( theta/2.0 );

    EventList& el = reducedEventWS->getEventList(i);
    el.switchTo(WEIGHTED);

    std::vector<WeightedEvent>::iterator itev;
    std::vector<WeightedEvent>::iterator itev_end = el.getWeightedEvents().end();

    for (itev = el.getWeightedEvents().begin(); itev != itev_end; ++itev)
    {
      if ( itev->m_weight != itev->m_weight ) continue;
      if (std::abs(itev->m_weight) == std::numeric_limits<double>::infinity()) continue;
      if ( !isEmpty(min_wl) && itev->m_tof < min_wl ) continue;
      if ( !isEmpty(max_wl) && itev->m_tof > max_wl ) continue;

      const double q = factor/itev->m_tof;
      int iq = 0;

      // Bin assignment depends on whether we have log or linear bins
      if(binParams[1]>0.0)
      {
        iq = (int)floor( (q-binParams[0])/ binParams[1] );
      } else {
        iq = (int)floor(log(q/binParams[0])/log(1.0-binParams[1]));
      }

      const double L2 = scattered_flight_path.norm();
      const double src_to_pixel = L1+L2;
      const double dTheta2 = ( 3.0*R1*R1/(L1*L1) + 3.0*R2*R2*src_to_pixel*src_to_pixel/(L1*L1*L2*L2)
            + 2.0*(pixel_size_x*pixel_size_x+pixel_size_y*pixel_size_y)/(L2*L2) )/12.0;

      const double dwl_over_wl = 3.9560*getTOFResolution(itev->m_tof)/(1000.0*(L1+L2)*itev->m_tof);
      const double dq_over_q = std::sqrt(dTheta2/(theta*theta)+dwl_over_wl*dwl_over_wl);

      PARALLEL_CRITICAL(iq)    /* Write to shared memory - must protect */
      if (iq>=0 && iq < xLength-1 && !dq_over_q!=dq_over_q && dq_over_q>0)
      {
        DxOut[iq] += q*dq_over_q*itev->m_weight;
        XNorm[iq] += itev->m_weight;
        TOFY[iq] += q*std::fabs(dwl_over_wl)*itev->m_weight;
        ThetaY[iq] += q*std::sqrt(dTheta2)/theta*itev->m_weight;
      }
    }

    progress.report("Computing Q resolution");
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION
  // Normalize according to the chosen weighting scheme
  for ( int i = 0; i<xLength-1; i++ )
  {
    if (XNorm[i]>0)
    {
      DxOut[i] /= XNorm[i];
      TOFY[i] /= XNorm[i];
      ThetaY[i] /= XNorm[i];
    }
  }
}
コード例 #28
0
ファイル: ExtractMask.cpp プロジェクト: AlistairMills/mantid
    /**
     * Execute the algorithm
     */
    void ExtractMask::exec()
    {
      MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace");
      Geometry::Instrument_const_sptr instr = inputWS->getInstrument();

      // convert input to a mask workspace
      DataObjects::MaskWorkspace_const_sptr inputMaskWS
          = boost::dynamic_pointer_cast<const DataObjects::MaskWorkspace>(inputWS);
      bool inputWSIsSpecial = bool(inputMaskWS);
      if (inputWSIsSpecial)
      {
        g_log.notice() << "Input workspace is a MaskWorkspace.\n";
      }

      DataObjects::MaskWorkspace_sptr maskWS;
      // List masked of detector IDs
      std::vector<detid_t> detectorList;

      if (instr)
      {
        const int nHist = static_cast<int>(inputWS->getNumberHistograms());

        // Create a new workspace for the results, copy from the input to ensure that we copy over the instrument and current masking
        maskWS = DataObjects::MaskWorkspace_sptr(new DataObjects::MaskWorkspace(inputWS));
        maskWS->setTitle(inputWS->getTitle());

        Progress prog(this,0.0,1.0,nHist);

        MantidVecPtr xValues;
        xValues.access() = MantidVec(1, 0.0);

        PARALLEL_FOR2(inputWS, maskWS)
        for( int i = 0; i < nHist; ++i )
        {
          PARALLEL_START_INTERUPT_REGION

          bool inputIsMasked(false);
          IDetector_const_sptr inputDet;
          try
          {
            inputDet = inputWS->getDetector(i);
            if (inputWSIsSpecial) {
              inputIsMasked = inputMaskWS->isMaskedIndex(i);
            }
            // special workspaces can mysteriously have the mask bit set
            // but only check if we haven't already decided to mask the spectrum
            if( !inputIsMasked && inputDet->isMasked() )
            {
              inputIsMasked = true;
            }

            if (inputIsMasked)
            {
              detid_t id = inputDet->getID();
              PARALLEL_CRITICAL(name)
              {
                detectorList.push_back(id);
              }
            }
          }
          catch(Kernel::Exception::NotFoundError &)
          {
            inputIsMasked = false;
          }

          maskWS->setMaskedIndex(i, inputIsMasked);

          prog.report();

          PARALLEL_END_INTERUPT_REGION
        }
        PARALLEL_CHECK_INTERUPT_REGION

        // Clear all the "masked" bits on the output masked workspace
        Geometry::ParameterMap & pmap = maskWS->instrumentParameters();
        pmap.clearParametersByName("masked");
      }
      else // no instrument
      {
        // TODO should fill this in
        throw std::runtime_error("No instrument");
コード例 #29
0
/** Corrects a spectra for the detector efficiency calculated from detector information
Gets the detector information and uses this to calculate its efficiency
*  @param spectraIn :: index of the spectrum to get the efficiency for
*  @throw invalid_argument if the shape of a detector is isn't a cylinder aligned along one axis
*  @throw runtime_error if the SpectraDetectorMap has not been filled
*  @throw NotFoundError if the detector or its gas pressure or wall thickness were not found
*/
void DetectorEfficiencyCor::correctForEfficiency(int64_t spectraIn)
{
  IDetector_const_sptr det = m_inputWS->getDetector(spectraIn);
  if( det->isMonitor() || det->isMasked() )
  {
    return;
  }

  MantidVec & yout = m_outputWS->dataY(spectraIn);
  MantidVec & eout = m_outputWS->dataE(spectraIn);
  // Need the original values so this is not a reference
  const MantidVec yValues = m_inputWS->readY(spectraIn);
  const MantidVec eValues = m_inputWS->readE(spectraIn);

  // get a pointer to the detectors that created the spectrum
  const std::set<detid_t> dets = m_inputWS->getSpectrum(spectraIn)->getDetectorIDs();

  std::set<detid_t>::const_iterator it = dets.begin();
  std::set<detid_t>::const_iterator iend = dets.end();
  if ( it == iend )
  {
    throw Exception::NotFoundError("No detectors found", spectraIn);
  }
  
  // Storage for the reciprocal wave vectors that are calculated as the 
  //correction proceeds
  std::vector<double> oneOverWaveVectors(yValues.size());
  for( ; it != iend ; ++it )
  {
    IDetector_const_sptr det_member = m_inputWS->getInstrument()->getDetector(*it);
    
    Parameter_sptr par = m_paraMap->get(det_member.get(),"3He(atm)");
    if ( !par )
    {
      throw Exception::NotFoundError("3He(atm)", spectraIn);
    }
    const double atms = par->value<double>();
    par = m_paraMap->get(det_member.get(),"wallT(m)");
    if ( !par )
    {
      throw Exception::NotFoundError("wallT(m)", spectraIn);
    }
    const double wallThickness = par->value<double>();
    double detRadius(0.0);
    V3D detAxis;
    getDetectorGeometry(det_member, detRadius, detAxis);

   // now get the sin of the angle, it's the magnitude of the cross product of unit vector along the detector tube axis and a unit vector directed from the sample to the detector centre
    V3D vectorFromSample = det_member->getPos() - m_samplePos;
    vectorFromSample.normalize();
    Quat rot = det_member->getRotation();
    // rotate the original cylinder object axis to get the detector axis in the actual instrument
    rot.rotate(detAxis); 
    detAxis.normalize();
    // Scalar product is quicker than cross product
    double cosTheta = detAxis.scalar_prod(vectorFromSample);
    double sinTheta = std::sqrt(1.0 - cosTheta*cosTheta);
    // Detector constant
    const double det_const = g_helium_prefactor*(detRadius - wallThickness)*atms/sinTheta;

    MantidVec::const_iterator yinItr = yValues.begin();
    MantidVec::const_iterator einItr = eValues.begin();
    MantidVec::iterator youtItr = yout.begin();
    MantidVec::iterator eoutItr = eout.begin();
    MantidVec::const_iterator xItr = m_inputWS->readX(spectraIn).begin();
    std::vector<double>::iterator wavItr = oneOverWaveVectors.begin();

    for( ; youtItr != yout.end(); ++youtItr, ++eoutItr)
    {
      if( it == dets.begin() )
      {
        *youtItr = 0.0;
        *eoutItr = 0.0;
        *wavItr = calculateOneOverK(*xItr, *(xItr + 1 ));
      }
      const double oneOverWave = *wavItr;
      const double factor = 1.0/detectorEfficiency(det_const*oneOverWave);
      *youtItr += (*yinItr)*factor;
      *eoutItr += (*einItr)*factor;
      ++yinItr; ++einItr;
      ++xItr; ++wavItr;
    }
  }
}
コード例 #30
0
void ConvertToDiffractionMDWorkspace::convertEventList(int workspaceIndex,
                                                       EventList &el) {
  size_t numEvents = el.getNumberEvents();
  DataObjects::MDBoxBase<DataObjects::MDLeanEvent<3>, 3> *box = ws->getBox();

  // Get the position of the detector there.
  const std::set<detid_t> &detectors = el.getDetectorIDs();
  if (!detectors.empty()) {
    // Get the detector (might be a detectorGroup for multiple detectors)
    // or might return an exception if the detector is not in the instrument
    // definition
    IDetector_const_sptr det;
    try {
      det = m_inWS->getDetector(workspaceIndex);
    } catch (Exception::NotFoundError &) {
      this->failedDetectorLookupCount++;
      return;
    }

    // Vector between the sample and the detector
    V3D detPos = det->getPos() - samplePos;

    // Neutron's total travelled distance
    double distance = detPos.norm() + l1;

    // Detector direction normalized to 1
    V3D detDir = detPos / detPos.norm();

    // The direction of momentum transfer in the inelastic convention ki-kf
    //  = input beam direction (normalized to 1) - output beam direction
    //  (normalized to 1)
    V3D Q_dir_lab_frame = beamDir - detDir;
    double qSign = -1.0;
    std::string convention =
        ConfigService::Instance().getString("Q.convention");
    if (convention == "Crystallography")
      qSign = 1.0;
    Q_dir_lab_frame *= qSign;

    // Multiply by the rotation matrix to convert to Q in the sample frame (take
    // out goniometer rotation)
    // (or to HKL, if that's what the matrix is)
    V3D Q_dir = mat * Q_dir_lab_frame;

    // For speed we extract the components.
    coord_t Q_dir_x = coord_t(Q_dir.X());
    coord_t Q_dir_y = coord_t(Q_dir.Y());
    coord_t Q_dir_z = coord_t(Q_dir.Z());

    // For lorentz correction, calculate  sin(theta))^2
    double sin_theta_squared = 0;
    if (LorentzCorrection) {
      // Scattering angle = 2 theta = angle between neutron beam direction and
      // the detector (scattering) direction
      // The formula for Lorentz Correction is sin(theta), i.e. sin(half the
      // scattering angle)
      double theta = detDir.angle(beamDir) / 2.0;
      sin_theta_squared = sin(theta);
      sin_theta_squared = sin_theta_squared * sin_theta_squared; // square it
    }

    /** Constant that you divide by tof (in usec) to get wavenumber in ang^-1 :
     * Wavenumber (in ang^-1) =  (PhysicalConstants::NeutronMass * distance) /
     * ((tof (in usec) * 1e-6) * PhysicalConstants::h_bar) * 1e-10; */
    const double wavenumber_in_angstrom_times_tof_in_microsec =
        (PhysicalConstants::NeutronMass * distance * 1e-10) /
        (1e-6 * PhysicalConstants::h_bar);

    // PARALLEL_CRITICAL( convert_tester_output ) { std::cout << "Spectrum " <<
    // el.getSpectrumNo() << " beamDir = " << beamDir << " detDir = " << detDir
    // << " Q_dir = " << Q_dir << " conversion factor " <<
    // wavenumber_in_angstrom_times_tof_in_microsec << std::endl;  }

    // g_log.information() << wi << " : " << el.getNumberEvents() << " events.
    // Pos is " << detPos << std::endl;
    // g_log.information() << Q_dir.norm() << " Qdir norm" << std::endl;

    // This little dance makes the getting vector of events more general (since
    // you can't overload by return type).
    typename std::vector<T> *events_ptr;
    getEventsFrom(el, events_ptr);
    typename std::vector<T> &events = *events_ptr;

    // Iterators to start/end
    auto it = events.begin();
    auto it_end = events.end();

    for (; it != it_end; it++) {
      // Get the wavenumber in ang^-1 using the previously calculated constant.
      coord_t wavenumber =
          coord_t(wavenumber_in_angstrom_times_tof_in_microsec / it->tof());

      // Q vector = K_final - K_initial = wavenumber * (output_direction -
      // input_direction)
      coord_t center[3] = {Q_dir_x * wavenumber, Q_dir_y * wavenumber,
                           Q_dir_z * wavenumber};

      // Check that the event is within bounds
      if (center[0] < m_extentsMin[0] || center[0] >= m_extentsMax[0])
        continue;
      if (center[1] < m_extentsMin[1] || center[1] >= m_extentsMax[1])
        continue;
      if (center[2] < m_extentsMin[2] || center[2] >= m_extentsMax[2])
        continue;

      if (LorentzCorrection) {
        // double lambda = 1.0/wavenumber;
        // (sin(theta))^2 / wavelength^4
        float correct = float(sin_theta_squared * wavenumber * wavenumber *
                              wavenumber * wavenumber);
        // Push the MDLeanEvent but correct the weight.
        box->addEvent(MDE(float(it->weight() * correct),
                          float(it->errorSquared() * correct * correct),
                          center));
      } else {
        // Push the MDLeanEvent with the same weight
        box->addEvent(
            MDE(float(it->weight()), float(it->errorSquared()), center));
      }
    }

    // Clear out the EventList to save memory
    if (ClearInputWorkspace) {
      // Track how much memory you cleared
      size_t memoryCleared = el.getMemorySize();
      // Clear it now
      el.clear();
      // For Linux with tcmalloc, make sure memory goes back, if you've cleared
      // 200 Megs
      MemoryManager::Instance().releaseFreeMemoryIfAccumulated(
          memoryCleared, static_cast<size_t>(2e8));
    }
  }
  prog->reportIncrement(numEvents, "Adding Events");
}