/**
 * Get the detector component. Use the name provided as a property as the basis
 *for the lookup as a priority.
 *
 * Throws if the name is invalid.
 * @param workspace : Workspace from instrument with detectors
 * @param isPointDetector : True if this is a point detector. Used to guess a
 *name.
 * @return The component : The component object found.
 */
boost::shared_ptr<const Mantid::Geometry::IComponent>
SpecularReflectionAlgorithm::getDetectorComponent(
    MatrixWorkspace_sptr workspace, const bool isPointDetector) const {
  boost::shared_ptr<const IComponent> searchResult;
  if (!isPropertyDefault("SpectrumNumbersOfDetectors")) {
    const std::vector<int> spectrumNumbers =
        this->getProperty("SpectrumNumbersOfDetectors");
    const bool strictSpectrumChecking =
        this->getProperty("StrictSpectrumChecking");
    checkSpectrumNumbers(spectrumNumbers, strictSpectrumChecking, g_log);
    auto specToWorkspaceIndex = workspace->getSpectrumToWorkspaceIndexMap();
    DetectorGroup_sptr allDetectors = boost::make_shared<DetectorGroup>();
    const auto &spectrumInfo = workspace->spectrumInfo();
    for (auto index : spectrumNumbers) {
      const size_t spectrumNumber{static_cast<size_t>(index)};
      auto it = specToWorkspaceIndex.find(index);
      if (it == specToWorkspaceIndex.end()) {
        std::stringstream message;
        message << "Spectrum number " << spectrumNumber
                << " does not exist in the InputWorkspace";
        throw std::invalid_argument(message.str());
      }
      const size_t workspaceIndex = it->second;
      auto detector = workspace->getDetector(workspaceIndex);
      if (spectrumInfo.isMasked(workspaceIndex))
        g_log.warning() << "Adding a detector (ID:" << detector->getID()
                        << ") that is flagged as masked.\n";
      allDetectors->addDetector(detector);
    }
    searchResult = allDetectors;
  } else {
    Mantid::Geometry::Instrument_const_sptr inst = workspace->getInstrument();
    std::string componentToCorrect =
        isPointDetector ? "point-detector" : "linedetector";

    if (!isPropertyDefault("DetectorComponentName")) {
      componentToCorrect = this->getPropertyValue("DetectorComponentName");
    }
    searchResult = inst->getComponentByName(componentToCorrect);
    if (searchResult == nullptr) {
      throw std::invalid_argument(componentToCorrect +
                                  " does not exist. Check input properties.");
    }
  }

  return searchResult;
}
Example #2
0
MatrixWorkspace_sptr
CreateFloodWorkspace::scaleToCentralPixel(MatrixWorkspace_sptr ws) {
  int const centralSpectrum = getProperty(Prop::CENTRAL_PIXEL);
  auto const nHisto = static_cast<int>(ws->getNumberHistograms());
  if (centralSpectrum >= nHisto) {
    throw std::invalid_argument(
        "Spectrum index " + std::to_string(centralSpectrum) +
        " passed to property " + Prop::CENTRAL_PIXEL +
        " is outside the range 0-" + std::to_string(nHisto - 1));
  }
  auto const spectraMap = ws->getSpectrumToWorkspaceIndexMap();
  auto const centralIndex = spectraMap.at(centralSpectrum);
  auto const scaleFactor = ws->y(centralIndex).front();
  g_log.information() << "Scale to central pixel, factor = " << scaleFactor
                      << '\n';
  if (scaleFactor <= 0.0) {
    throw std::runtime_error("Scale factor muhst be > 0, found " +
                             std::to_string(scaleFactor));
  }
  auto const axis = ws->getAxis(1);
  auto const sa = dynamic_cast<const SpectraAxis *>(axis);
  double const startX =
      isDefault(Prop::START_X) ? sa->getMin() : getProperty(Prop::START_X);
  double const endX =
      isDefault(Prop::END_X) ? sa->getMax() : getProperty(Prop::END_X);
  PARALLEL_FOR_IF(Kernel::threadSafe(*ws))
  for (int i = 0; i < nHisto; ++i) {
    PARALLEL_START_INTERUPT_REGION
    auto const spec = ws->getSpectrum(i).getSpectrumNo();
    if (isExcludedSpectrum(spec)) {
      ws->mutableY(i)[0] = VERY_BIG_VALUE;
      ws->mutableE(i)[0] = 0.0;
    } else if (spec >= startX && spec <= endX) {
      ws->mutableY(i)[0] /= scaleFactor;
      ws->mutableE(i)[0] /= scaleFactor;
    } else {
      ws->mutableY(i)[0] = 1.0;
      ws->mutableE(i)[0] = 0.0;
    }
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION
  return ws;
}
Example #3
0
/** Execute the algorithm.
 */
void EditInstrumentGeometry::exec() {
  // Lots of things have to do with the input workspace
  MatrixWorkspace_sptr workspace = getProperty("Workspace");
  Geometry::Instrument_const_sptr originstrument = workspace->getInstrument();

  // Get and check the primary flight path
  double l1 = this->getProperty("PrimaryFlightPath");
  if (isEmpty(l1)) {
    // Use the original L1
    if (!originstrument) {
      std::string errmsg(
          "It is not supported that L1 is not given, ",
          "while there is no instrument associated to input workspace.");
      g_log.error(errmsg);
      throw std::runtime_error(errmsg);
    }
    Geometry::IComponent_const_sptr source = originstrument->getSource();
    Geometry::IComponent_const_sptr sample = originstrument->getSample();
    l1 = source->getDistance(*sample);
    g_log.information() << "Retrieve L1 from input data workspace. \n";
  }
  g_log.information() << "Using L1 = " << l1 << "\n";

  // Get spectra number in case they are in a funny order
  std::vector<int32_t> specids = this->getProperty("SpectrumIDs");
  if (specids.empty()) // they are using the order of the input workspace
  {
    size_t numHist = workspace->getNumberHistograms();
    for (size_t i = 0; i < numHist; ++i) {
      specids.push_back(workspace->getSpectrum(i).getSpectrumNo());
      g_log.information() << "Add spectrum "
                          << workspace->getSpectrum(i).getSpectrumNo() << ".\n";
    }
  }

  // Get the detector ids - empsy means ignore it
  const vector<int> vec_detids = getProperty("DetectorIDs");
  const bool renameDetID(!vec_detids.empty());

  // Get individual detector geometries ordered by input spectrum Numbers
  const std::vector<double> l2s = this->getProperty("L2");
  const std::vector<double> tths = this->getProperty("Polar");
  std::vector<double> phis = this->getProperty("Azimuthal");

  // empty list of L2 and 2-theta is not allowed
  if (l2s.empty()) {
    throw std::runtime_error("User must specify L2 for all spectra. ");
  }
  if (tths.empty()) {
    throw std::runtime_error("User must specify 2theta for all spectra.");
  }

  // empty list of phi means that they are all zero
  if (phis.empty()) {
    phis.assign(l2s.size(), 0.);
  }

  // Validate
  for (size_t ib = 0; ib < l2s.size(); ib++) {
    g_log.information() << "Detector " << specids[ib] << "  L2 = " << l2s[ib]
                        << "  2Theta = " << tths[ib] << '\n';
    if (specids[ib] < 0) {
      // Invalid spectrum Number : less than 0.
      stringstream errmsgss;
      errmsgss << "Detector ID = " << specids[ib] << " cannot be less than 0.";
      throw std::invalid_argument(errmsgss.str());
    }
    if (l2s[ib] <= 0.0) {
      throw std::invalid_argument("L2 cannot be less or equal to 0");
    }
  }

  // Keep original instrument and set the new instrument, if necessary
  const auto spec2indexmap = workspace->getSpectrumToWorkspaceIndexMap();

  // ??? Condition: spectrum has 1 and only 1 detector
  size_t nspec = workspace->getNumberHistograms();

  // Initialize another set of L2/2-theta/Phi/DetectorIDs vector ordered by
  // workspace index
  std::vector<double> storL2s(nspec, 0.);
  std::vector<double> stor2Thetas(nspec, 0.);
  std::vector<double> storPhis(nspec, 0.);
  vector<int> storDetIDs(nspec, 0);

  // Map the properties from spectrum Number to workspace index
  for (size_t i = 0; i < specids.size(); i++) {
    // Find spectrum's workspace index
    auto it = spec2indexmap.find(specids[i]);
    if (it == spec2indexmap.end()) {
      stringstream errss;
      errss << "Spectrum Number " << specids[i] << " is not found. "
            << "Instrument won't be edited for this spectrum. \n";
      g_log.error(errss.str());
      throw std::runtime_error(errss.str());
    }

    // Store and set value
    size_t workspaceindex = it->second;

    storL2s[workspaceindex] = l2s[i];
    stor2Thetas[workspaceindex] = tths[i];
    storPhis[workspaceindex] = phis[i];
    if (renameDetID)
      storDetIDs[workspaceindex] = vec_detids[i];

    g_log.debug() << "workspace index = " << workspaceindex
                  << " is for Spectrum " << specids[i] << '\n';
  }

  // Generate a new instrument
  // Name of the new instrument
  std::string name = std::string(getProperty("InstrumentName"));
  if (name.empty()) {
    // Use the original L1
    if (!originstrument) {
      std::string errmsg(
          "It is not supported that InstrumentName is not given, ",
          "while there is no instrument associated to input workspace.");
      g_log.error(errmsg);
      throw std::runtime_error(errmsg);
    }
    name = originstrument->getName();
  }

  // Create a new instrument from scratch any way.
  auto instrument = boost::make_shared<Geometry::Instrument>(name);
  if (!bool(instrument)) {
    stringstream errss;
    errss << "Trying to use a Parametrized Instrument as an Instrument.";
    g_log.error(errss.str());
    throw std::runtime_error(errss.str());
  }

  // Set up source and sample information
  Geometry::ObjComponent *samplepos =
      new Geometry::ObjComponent("Sample", instrument.get());
  instrument->add(samplepos);
  instrument->markAsSamplePos(samplepos);
  samplepos->setPos(0.0, 0.0, 0.0);

  Geometry::ObjComponent *source =
      new Geometry::ObjComponent("Source", instrument.get());
  instrument->add(source);
  instrument->markAsSource(source);
  source->setPos(0.0, 0.0, -1.0 * l1);

  // Add/copy detector information
  auto indexInfo = workspace->indexInfo();
  std::vector<detid_t> detIDs;
  for (size_t i = 0; i < workspace->getNumberHistograms(); i++) {
    // Create a new detector.
    //    (Instrument will take ownership of pointer so no need to delete.)
    detid_t newdetid;
    if (renameDetID)
      newdetid = storDetIDs[i];
    else
      newdetid = detid_t(i) + 100;
    Geometry::Detector *detector =
        new Geometry::Detector("det", newdetid, samplepos);

    // Set up new detector parameters related to new instrument
    double l2 = storL2s[i];
    double tth = stor2Thetas[i];
    double phi = storPhis[i];

    Kernel::V3D pos;
    pos.spherical(l2, tth, phi);
    detector->setPos(pos);

    // Add new detector to spectrum and instrument
    // Good and do some debug output
    g_log.debug() << "Orignal spectrum " << indexInfo.spectrumNumber(i)
                  << "has " << indexInfo.detectorIDs(i).size()
                  << " detectors. \n";

    detIDs.push_back(newdetid);
    instrument->add(detector);
    instrument->markAsDetector(detector);

  } // ENDFOR workspace index
  indexInfo.setDetectorIDs(std::move(detIDs));
  workspace->setIndexInfo(indexInfo);

  // Add the new instrument
  workspace->setInstrument(instrument);
}