예제 #1
0
double getSourceToSampleDistance(API::MatrixWorkspace_sptr dataWS) {
  const int nguides =
      dataWS->run().getPropertyValueAsType<int>("number-of-guides");

  std::vector<std::string> pars =
      dataWS->getInstrument()->getStringParameter("aperture-distances");
  if (pars.empty())
    throw Kernel::Exception::InstrumentDefinitionError(
        "Unable to find [aperture-distances] instrument parameter");

  double SSD = 0;
  Mantid::Kernel::StringTokenizer tok(
      pars[0], ",", Mantid::Kernel::StringTokenizer::TOK_IGNORE_EMPTY);
  if (tok.count() > 0 && tok.count() < 10 && nguides >= 0 && nguides < 9) {
    const std::string distance_as_string = tok[8 - nguides];
    if (!Poco::NumberParser::tryParseFloat(distance_as_string, SSD))
      throw Kernel::Exception::InstrumentDefinitionError(
          "Bad value for source-to-sample distance");
  } else
    throw Kernel::Exception::InstrumentDefinitionError(
        "Unable to get source-to-sample distance");

  // Check for an offset
  if (dataWS->getInstrument()->hasParameter("source-distance-offset")) {
    const double offset =
        readInstrumentParameter("source-distance-offset", dataWS);
    SSD += offset;
  }
  return SSD;
}
예제 #2
0
/** Initialization method:
@param bkgWS    -- shared pointer to the workspace which contains background
@param sourceWS -- shared pointer to the workspace to remove background from
@param emode    -- energy conversion mode used during internal units conversion
(0 -- elastic, 1-direct, 2 indirect, as defined in Units conversion
@param pLog     -- pointer to the logger class which would report errors
@param nThreads -- number of threads to be used for background removal
@param inPlace  -- if the background removal occurs from the existing workspace
or target workspace has to be cloned.
*/
void BackgroundHelper::initialize(const API::MatrixWorkspace_const_sptr &bkgWS,
                                  const API::MatrixWorkspace_sptr &sourceWS,
                                  int emode, Kernel::Logger *pLog, int nThreads,
                                  bool inPlace) {
  m_bgWs = bkgWS;
  m_wkWS = sourceWS;
  m_Emode = emode;
  m_pgLog = pLog;
  m_inPlace = inPlace;

  std::string bgUnits = bkgWS->getAxis(0)->unit()->unitID();
  if (bgUnits != "TOF")
    throw std::invalid_argument(" Background Workspace: " + bkgWS->getName() +
                                " should be in the units of TOF");

  if (!(bkgWS->getNumberHistograms() == 1 ||
        sourceWS->getNumberHistograms() == bkgWS->getNumberHistograms()))
    throw std::invalid_argument(" Background Workspace: " + bkgWS->getName() +
                                " should have the same number of spectra as "
                                "source workspace or be a single histogram "
                                "workspace");

  auto WSUnit = sourceWS->getAxis(0)->unit();
  if (!WSUnit)
    throw std::invalid_argument(" Source Workspace: " + sourceWS->getName() +
                                " should have units");

  Geometry::IComponent_const_sptr source =
      sourceWS->getInstrument()->getSource();
  m_Sample = sourceWS->getInstrument()->getSample();
  if ((!source) || (!m_Sample))
    throw std::invalid_argument(
        "Instrument on Source workspace:" + sourceWS->getName() +
        "is not sufficiently defined: failed to get source and/or sample");
  m_L1 = source->getDistance(*m_Sample);

  // just in case.
  this->deleteUnitsConverters();
  // allocate the array of units converters to avoid units reallocation within a
  // loop
  m_WSUnit.assign(nThreads, NULL);
  for (int i = 0; i < nThreads; i++) {
    m_WSUnit[i] = WSUnit->clone();
  }

  m_singleValueBackground = false;
  if (bkgWS->getNumberHistograms() == 0)
    m_singleValueBackground = true;
  const MantidVec &dataX = bkgWS->dataX(0);
  const MantidVec &dataY = bkgWS->dataY(0);
  // const MantidVec& dataE = bkgWS->dataE(0);
  m_NBg = dataY[0];
  m_dtBg = dataX[1] - dataX[0];
  // m_ErrSq  = dataE[0]*dataE[0]; // needs further clarification

  m_Efix = this->getEi(sourceWS);
}
예제 #3
0
 double LoadHelper::getL1(const API::MatrixWorkspace_sptr& workspace)
 {
   Geometry::Instrument_const_sptr instrument = workspace->getInstrument();
   Geometry::IComponent_const_sptr sample = instrument->getSample();
   double l1 = instrument->getSource()->getDistance(*sample);
   return l1;
 }
예제 #4
0
/** Execute the algorithm.
 */
void CalculateDIFC::exec() {

  DataObjects::OffsetsWorkspace_const_sptr offsetsWs =
      getProperty("OffsetsWorkspace");
  API::ITableWorkspace_const_sptr calibWs = getProperty("CalibrationWorkspace");
  API::MatrixWorkspace_sptr inputWs = getProperty("InputWorkspace");
  API::MatrixWorkspace_sptr outputWs = getProperty("OutputWorkspace");

  if ((!bool(inputWs == outputWs)) ||
      (!bool(boost::dynamic_pointer_cast<SpecialWorkspace2D>(outputWs)))) {
    outputWs = boost::dynamic_pointer_cast<MatrixWorkspace>(
        boost::make_shared<SpecialWorkspace2D>(inputWs->getInstrument()));
    outputWs->setTitle("DIFC workspace");
  }

  // convert to actual type being used
  DataObjects::SpecialWorkspace2D_sptr outputSpecialWs =
      boost::dynamic_pointer_cast<DataObjects::SpecialWorkspace2D>(outputWs);

  API::Progress progress(this, 0.0, 1.0, inputWs->getNumberHistograms());
  if (bool(calibWs)) {
    calculateFromTable(progress, *outputSpecialWs, *calibWs);
  } else {
    // this method handles calculating from instrument geometry as well
    const auto &detectorInfo = inputWs->detectorInfo();
    calculateFromOffset(progress, *outputSpecialWs, offsetsWs.get(),
                        detectorInfo);
  }

  setProperty("OutputWorkspace", outputWs);
}
예제 #5
0
void FindDetectorsPar::populate_values_from_file(
    const API::MatrixWorkspace_sptr &inputWS) {
  size_t nHist = inputWS->getNumberHistograms();

  if (this->current_ASCII_file.Type == PAR_type) {
    // in this case data in azimuthal width and polar width are in fact real
    // sizes in meters; have to transform it in into angular values
    for (size_t i = 0; i < nHist; i++) {
      azimuthalWidth[i] =
          atan2(azimuthalWidth[i], secondaryFlightpath[i]) * rad2deg;
      polarWidth[i] = atan2(polarWidth[i], secondaryFlightpath[i]) * rad2deg;
    }
    m_SizesAreLinear = false;
  } else {

    Geometry::IComponent_const_sptr sample =
        inputWS->getInstrument()->getSample();
    secondaryFlightpath.resize(nHist);
    // Loop over the spectra
    for (size_t i = 0; i < nHist; i++) {
      Geometry::IDetector_const_sptr spDet;
      try {
        spDet = inputWS->getDetector(i);
      } catch (Kernel::Exception::NotFoundError &) {
        continue;
      }
      // Check that we aren't writing a monitor...
      if (spDet->isMonitor())
        continue;
      /// this is the only value, which is not defined in phx file, so we
      /// calculate it
      secondaryFlightpath[i] = spDet->getDistance(*sample);
    }
  }
}
예제 #6
0
/** Checks and retrieves the monitor spectrum out of the input workspace
 *  @param inputWorkspace The input workspace.
 *  @param wsID The workspace ID.
 *  @returns A workspace containing the monitor spectrum only
 *  @throw std::runtime_error If the properties are invalid
 */
API::MatrixWorkspace_sptr NormaliseToMonitor::getMonitorWorkspace(API::MatrixWorkspace_sptr inputWorkspace,int &wsID)
{
  // Get the workspace from the ADS. Will throw if it's not there.
  MatrixWorkspace_sptr monitorWS = getProperty("MonitorWorkspace");
  wsID = getProperty("MonitorWorkspaceIndex");
  // Check that it's a single spectrum workspace
  if ( static_cast<int>(monitorWS->getNumberHistograms()) < wsID )
  {
    throw std::runtime_error("The MonitorWorkspace must contain the MonitorWorkspaceIndex");
  }
  // Check that the two workspace come from the same instrument
  if ( monitorWS->getInstrument()->getName() != inputWorkspace->getInstrument()->getName() )
  {
    throw std::runtime_error("The Input and Monitor workspaces must come from the same instrument");
  }
  // Check that they're in the same units
  if ( monitorWS->getAxis(0)->unit()->unitID() != inputWorkspace->getAxis(0)->unit()->unitID() )
  {
    throw std::runtime_error("The Input and Monitor workspaces must have the same unit");
  }

  // In this case we need to test whether the bins in the monitor workspace match
  m_commonBins = (m_commonBins &&
                  API::WorkspaceHelpers::matchingBins(inputWorkspace,monitorWS,true) );

  // If the workspace passes all these tests, make a local copy because it will get changed
  return this->extractMonitorSpectrum(monitorWS,wsID);
}
/**
 * Correct the position of the detectors based on the input theta value.
 * @param toCorrect : Workspace to correct detector posisitions on.
 * @param twoThetaInDeg : 2* Theta in degrees to use in correction calculations.
 * @param sample : Pointer to the sample
 * @param detector : Pointer to a given detector
 */
void SpecularReflectionPositionCorrect::correctPosition(
    API::MatrixWorkspace_sptr toCorrect, const double &twoThetaInDeg,
    IComponent_const_sptr sample, IComponent_const_sptr detector) {

  auto instrument = toCorrect->getInstrument();

  const V3D detectorPosition = detector->getPos();

  const V3D samplePosition = sample->getPos();

  const V3D sampleToDetector = detectorPosition - samplePosition;

  auto referenceFrame = instrument->getReferenceFrame();

  const double twoThetaInRad = twoThetaInDeg * (M_PI / 180.0);

  double acrossOffset = 0;

  double beamOffset = sampleToDetector.scalar_prod(
      referenceFrame
          ->vecPointingAlongBeam()); // We just recalculate beam offset.

  double upOffset =
      (beamOffset *
       std::tan(0.5 * twoThetaInRad)); // We only correct vertical position

  // Apply the movements.
  moveDetectors(toCorrect, detector, sample, upOffset, acrossOffset,
                detector->getPos());
}
예제 #8
0
    /** This function will check how to group spectra when calculating median
     *
     *
     */
    std::vector<std::vector<size_t> > DetectorDiagnostic::makeMap(API::MatrixWorkspace_sptr countsWS)
    {
      std::multimap<Mantid::Geometry::ComponentID,size_t> mymap;

      Geometry::Instrument_const_sptr instrument = countsWS->getInstrument();
      if (m_parents==0)
      {
        return makeInstrumentMap(countsWS);
      }
      if (!instrument)
      {
        g_log.warning("Workspace has no instrument. LevelsUP is ignored");
        return makeInstrumentMap(countsWS);
      }

      //check if not grouped. If grouped, it will throw
      if ( countsWS->hasGroupedDetectors() )
      {
        throw std::runtime_error("Median detector test: not able to create detector to spectra map. Try with LevelUp=0.");
      }

      for(size_t i=0;i < countsWS->getNumberHistograms();i++)
      {
        detid_t d=(*((countsWS->getSpectrum(i))->getDetectorIDs().begin()));
        std::vector<boost::shared_ptr<const Mantid::Geometry::IComponent> > anc=instrument->getDetector(d)->getAncestors();
        //std::vector<boost::shared_ptr<const IComponent> > anc=(*(countsWS->getSpectrum(i)->getDetectorIDs().begin()))->getAncestors();
        if (anc.size()<static_cast<size_t>(m_parents))
        {
          g_log.warning("Too many levels up. Will ignore LevelsUp");
          m_parents=0;
          return makeInstrumentMap(countsWS);
        }
        mymap.insert(std::pair<Mantid::Geometry::ComponentID,size_t>(anc[m_parents-1]->getComponentID(),i));
      }

      std::vector<std::vector<size_t> > speclist;
      std::vector<size_t>  speclistsingle;

      std::multimap<Mantid::Geometry::ComponentID,size_t>::iterator m_it, s_it;

      for (m_it = mymap.begin();  m_it != mymap.end();  m_it = s_it)
      {
        Mantid::Geometry::ComponentID theKey = (*m_it).first;

        std::pair<std::multimap<Mantid::Geometry::ComponentID,size_t>::iterator,std::multimap<Mantid::Geometry::ComponentID,size_t>::iterator> keyRange = mymap.equal_range(theKey);

        // Iterate over all map elements with key == theKey
        speclistsingle.clear();
        for (s_it = keyRange.first;  s_it != keyRange.second;  ++s_it)
        {
          speclistsingle.push_back( (*s_it).second );
        }
        speclist.push_back(speclistsingle);
      }

      return speclist;
    }
예제 #9
0
/*
 * Read a parameter from the instrument description
 */
double readInstrumentParameter(const std::string &parameter,
                               API::MatrixWorkspace_sptr dataWS) {
  std::vector<double> pars =
      dataWS->getInstrument()->getNumberParameter(parameter);
  if (pars.empty())
    throw Kernel::Exception::InstrumentDefinitionError(
        "Unable to find [" + parameter + "] instrument parameter");
  return pars[0];
}
/**
 * Execute the MoveInstrumentComponent on all (named) subcomponents
 * @param toCorrect : Workspace to correct
 * @param detector : Detector or DetectorGroup
 * @param sample : Sample Component
 * @param upOffset : Up offset to apply
 * @param acrossOffset : Across offset to apply
 * @param detectorPosition: Actual detector or detector group position.
 */
void SpecularReflectionPositionCorrect::moveDetectors(
    API::MatrixWorkspace_sptr toCorrect, IComponent_const_sptr detector,
    IComponent_const_sptr sample, const double &upOffset,
    const double &acrossOffset, const V3D &detectorPosition) {
  auto instrument = toCorrect->getInstrument();
  const V3D samplePosition = sample->getPos();
  auto referenceFrame = instrument->getReferenceFrame();
  if (auto groupDetector = boost::dynamic_pointer_cast<const DetectorGroup>(
          detector)) // Do we have a group of detectors
  {
    const std::vector<IDetector_const_sptr> detectors =
        groupDetector->getDetectors();
    const bool commonParent = hasCommonParent(detectors);
    if (commonParent) {
      /*
       * Same parent component. So lets move that.
       */
      moveDetectors(toCorrect, detectors[0], sample, upOffset, acrossOffset,
                    detectorPosition); // Recursive call
    } else {
      /*
       * We have to move individual components.
       */
      for (size_t i = 0; i < detectors.size(); ++i) {
        moveDetectors(toCorrect, detectors[i], sample, upOffset, acrossOffset,
                      detectorPosition); // Recursive call
      }
    }
  } else {
    auto moveComponentAlg =
        this->createChildAlgorithm("MoveInstrumentComponent");
    moveComponentAlg->initialize();
    moveComponentAlg->setProperty("Workspace", toCorrect);
    IComponent_const_sptr root = getParentComponent(detector);
    const std::string componentName = root->getName();
    moveComponentAlg->setProperty("ComponentName", componentName);
    moveComponentAlg->setProperty("RelativePosition", false);
    // Movements
    moveComponentAlg->setProperty(
        referenceFrame->pointingAlongBeamAxis(),
        detectorPosition.scalar_prod(referenceFrame->vecPointingAlongBeam()));
    moveComponentAlg->setProperty(referenceFrame->pointingHorizontalAxis(),
                                  acrossOffset);
    const double detectorVerticalPosition =
        detectorPosition.scalar_prod(referenceFrame->vecPointingUp());
    const double rootVerticalPosition =
        root->getPos().scalar_prod(referenceFrame->vecPointingUp());

    const double dm = rootVerticalPosition - detectorVerticalPosition;
    moveComponentAlg->setProperty(
        referenceFrame->pointingUpAxis(),
        samplePosition.scalar_prod(referenceFrame->vecPointingUp()) + upOffset +
            dm);
    // Execute the movement.
    moveComponentAlg->execute();
  }
}
예제 #11
0
 double LoadHelper::getL2(const API::MatrixWorkspace_sptr& workspace, int detId)
 {
   // Get a pointer to the instrument contained in the workspace
   Geometry::Instrument_const_sptr instrument = workspace->getInstrument();
   // Get the distance between the source and the sample (assume in metres)
   Geometry::IComponent_const_sptr sample = instrument->getSample();
   // Get the sample-detector distance for this detector (in metres)
   double l2 = workspace->getDetector(detId)->getPos().distance(sample->getPos());
   return l2;
 }
/** Put the parameters into one workspace
  * @param column :: [input] column of the output table workspace
  * @param ws :: [input/output] the group workspace parameters are to be put in
  * @param nProf :: the PROF Number, which is used to determine fitting function
 * for the parameters.
  * @param parameterXMLString :: string where the XML document filename is
 * stored
  */
void LoadFullprofResolution::putParametersIntoWorkspace(
    API::Column_const_sptr column, API::MatrixWorkspace_sptr ws, int nProf,
    std::string &parameterXMLString) {

  // Get instrument name from matrix workspace
  std::string instrumentName = ws->getInstrument()->getName();

  // Convert table workspace column into DOM XML document
  //   Set up writer to Paremeter file
  DOMWriter writer;
  writer.setNewLine("\n");
  writer.setOptions(XMLWriter::PRETTY_PRINT);

  //   Get current time
  Kernel::DateAndTime date = Kernel::DateAndTime::getCurrentTime();
  std::string ISOdate = date.toISO8601String();
  std::string ISOdateShort =
      ISOdate.substr(0, 19); // Remove fraction of seconds

  //   Create document
  AutoPtr<Document> mDoc = new Document();
  AutoPtr<Element> rootElem = mDoc->createElement("parameter-file");
  rootElem->setAttribute("date", ISOdateShort);
  mDoc->appendChild(rootElem);

  //   Add instrument
  AutoPtr<Element> instrumentElem = mDoc->createElement("component-link");
  instrumentElem->setAttribute("name", instrumentName);
  rootElem->appendChild(instrumentElem);
  if (nProf == 9) // put parameters into BackToBackExponential function
  {
    addBBX_S_Parameters(column, mDoc, instrumentElem);
    addBBX_A_Parameters(column, mDoc, instrumentElem);
    addBBX_B_Parameters(column, mDoc, instrumentElem);
  } else // Assume IkedaCarpenter PV
  {
    addALFBEParameter(column, mDoc, instrumentElem, "Alph0");
    addALFBEParameter(column, mDoc, instrumentElem, "Beta0");
    addALFBEParameter(column, mDoc, instrumentElem, "Alph1");
    addALFBEParameter(column, mDoc, instrumentElem, "Beta1");
    addSigmaParameters(column, mDoc, instrumentElem);
    addGammaParameters(column, mDoc, instrumentElem);
  }

  // Convert DOM XML document into string
  std::ostringstream outFile;
  writer.writeNode(outFile, mDoc);
  parameterXMLString = outFile.str();

  // Useful code for testing upgrades commented out for production use
  // std::ofstream outfileDebug("C:/Temp/test4_fullprof.xml");
  // outfileDebug << parameterXMLString;
  // outfileDebug.close();
}
예제 #13
0
/** Loads, checks and passes back the values passed to the algorithm
 * @param whiteBeam1 :: A white beam vanadium spectrum that will be used to
 * check detector efficiency variations
 * @param whiteBeam2 :: The other white beam vanadium spectrum from the same
 * instrument to use for comparison
 * @param variation :: The maximum fractional variation above the median that is
 * allowed for god detectors
 * @param startWsIndex :: Index number of the first spectrum to use
 * @param endWsIndex :: Index number of the last spectrum to use
 * @throw invalid_argument if there is an incapatible property value and so the
 * algorithm can't continue
 */
void DetectorEfficiencyVariation::retrieveProperties(
    API::MatrixWorkspace_sptr &whiteBeam1,
    API::MatrixWorkspace_sptr &whiteBeam2, double &variation, int &startWsIndex,
    int &endWsIndex) {
  whiteBeam1 = getProperty("WhiteBeamBase");
  whiteBeam2 = getProperty("WhiteBeamCompare");
  if (whiteBeam1->getInstrument()->getName() !=
      whiteBeam2->getInstrument()->getName()) {
    throw std::invalid_argument("The two input white beam vanadium workspaces "
                                "must be from the same instrument");
  }
  int maxWsIndex = static_cast<int>(whiteBeam1->getNumberHistograms()) - 1;
  if (maxWsIndex !=
      static_cast<int>(whiteBeam2->getNumberHistograms()) -
          1) { // we would get a crash later on if this were not true
    throw std::invalid_argument("The input white beam vanadium workspaces must "
                                "be have the same number of histograms");
  }

  variation = getProperty("Variation");

  startWsIndex = getProperty("StartWorkspaceIndex");
  if ((startWsIndex < 0) || (startWsIndex > maxWsIndex)) {
    g_log.warning("StartWorkspaceIndex out of range, changed to 0");
    startWsIndex = 0;
  }
  endWsIndex = getProperty("EndWorkspaceIndex");
  if (endWsIndex == Mantid::EMPTY_INT())
    endWsIndex = maxWsIndex;
  if ((endWsIndex < 0) || (endWsIndex > maxWsIndex)) {
    g_log.warning(
        "EndWorkspaceIndex out of range, changed to max Workspace number");
    endWsIndex = maxWsIndex;
  }
  if ((endWsIndex < startWsIndex)) {
    g_log.warning(
        "EndWorkspaceIndex can not be less than the StartWorkspaceIndex, "
        "changed to max Workspace number");
    endWsIndex = maxWsIndex;
  }
}
예제 #14
0
/*
 * Get instrument property as double
 * @s - input property name
 *
 */
double
LoadHelper::getInstrumentProperty(const API::MatrixWorkspace_sptr &workspace,
                                  std::string s) {
    std::vector<std::string> prop =
        workspace->getInstrument()->getStringParameter(s);
    if (prop.empty()) {
        g_log.debug("Property <" + s + "> doesn't exist!");
        return EMPTY_DBL();
    } else {
        g_log.debug() << "Property <" + s + "> = " << prop[0] << '\n';
        return boost::lexical_cast<double>(prop[0]);
    }
}
예제 #15
0
 V3D LoadHelper::getComponentPosition(API::MatrixWorkspace_sptr ws, const std::string &componentName)
 {
   try
   {
     Geometry::Instrument_const_sptr instrument = ws->getInstrument();
     Geometry::IComponent_const_sptr component = instrument->getComponentByName(componentName);
     V3D pos = component->getPos();
     return pos;
   } catch (Mantid::Kernel::Exception::NotFoundError&)
   {
     throw std::runtime_error("Error when trying to move the " + componentName + " : NotFoundError");
   }
 }
예제 #16
0
    /**
     * Mask the outlier values to get a better median value.
     * @param medianvec The median value calculated from the current counts.
     * @param countsWS The counts workspace. Any outliers will be masked here.
     * @param indexmap Index map.
     * @returns The number failed.
     */
    int MedianDetectorTest::maskOutliers(const std::vector<double> medianvec, API::MatrixWorkspace_sptr countsWS,std::vector<std::vector<size_t> > indexmap)
    {

      // Fractions of the median
      const double out_lo = getProperty("LowOutlier");
      const double out_hi = getProperty("HighOutlier");

      int numFailed(0);

      bool checkForMask = false;
      Geometry::Instrument_const_sptr instrument = countsWS->getInstrument();
      if (instrument != NULL)
      {
        checkForMask = ((instrument->getSource() != NULL) && (instrument->getSample() != NULL));
      }

      for (size_t i=0; i<indexmap.size();  ++i)
      {
        std::vector<size_t> hists=indexmap.at(i);
        double median=medianvec.at(i);

        PARALLEL_FOR1(countsWS)
        for(int j = 0; j < static_cast<int>(hists.size()); ++j)
        {
          const double value = countsWS->readY(hists.at(j))[0];
          if ((value == 0.) && checkForMask)
          {
            const std::set<detid_t>& detids = countsWS->getSpectrum(hists.at(j))->getDetectorIDs();
            if (instrument->isDetectorMasked(detids))
            {
              numFailed -= 1; // it was already masked
            }
          }
          if( (value < out_lo*median) && (value > 0.0) )
          {
            countsWS->maskWorkspaceIndex(hists.at(j));
            PARALLEL_ATOMIC
            ++numFailed;
          }
          else if( value > out_hi*median )
          {
            countsWS->maskWorkspaceIndex(hists.at(j));
            PARALLEL_ATOMIC
            ++numFailed;
          }
        }
        PARALLEL_CHECK_INTERUPT_REGION
      }

      return numFailed;
    }
예제 #17
0
/**
 * If grouping was not provided, find the instrument from the input workspace
 * and read the default grouping from its IDF. Returns the forward and backward
 * groupings as arrays of integers.
 * @param ws :: [input] Workspace to find grouping for
 * @param forward :: [output] Forward spectrum indices for given instrument
 * @param backward :: [output] Backward spectrum indices for given instrument
 */
void CalMuonDetectorPhases::getGroupingFromInstrument(
    const API::MatrixWorkspace_sptr &ws, std::vector<int> &forward,
    std::vector<int> &backward) {
  // make sure both arrays are empty
  forward.clear();
  backward.clear();

  const auto instrument = ws->getInstrument();
  auto loader = Kernel::make_unique<API::GroupingLoader>(instrument);

  if (instrument->getName() == "MUSR" || instrument->getName() == "CHRONUS") {
    // Two possibilities for grouping - use workspace log
    auto fieldDir = ws->run().getLogData("main_field_direction");
    if (fieldDir) {
      loader = Kernel::make_unique<API::GroupingLoader>(instrument,
                                                        fieldDir->value());
    }
    if (!fieldDir) {
      throw std::invalid_argument(
          "Cannot use default instrument grouping for MUSR "
          "as main field direction is unknown");
    }
  }

  // Load grouping and find forward, backward groups
  std::string fwdRange, bwdRange;
  const auto grouping = loader->getGroupingFromIDF();
  size_t nGroups = grouping->groups.size();
  for (size_t iGroup = 0; iGroup < nGroups; iGroup++) {
    const std::string name = grouping->groupNames[iGroup];
    if (name == "fwd" || name == "left") {
      fwdRange = grouping->groups[iGroup];
    } else if (name == "bwd" || name == "bkwd" || name == "right") {
      bwdRange = grouping->groups[iGroup];
    }
  }

  // Use ArrayProperty's functionality to convert string ranges to groups
  this->setProperty("ForwardSpectra", fwdRange);
  this->setProperty("BackwardSpectra", bwdRange);
  forward = getProperty("ForwardSpectra");
  backward = getProperty("BackwardSpectra");
}
예제 #18
0
/**Validates if either input workspace or instrument name is defined
@return the inconsistency between Instrument/Workspace properties or empty list
if no errors is found.
*/
std::map<std::string, std::string> LoadMask::validateInputs() {

  std::map<std::string, std::string> result;

  API::MatrixWorkspace_sptr inputWS = getProperty("RefWorkspace");
  std::string InstrName = getProperty("Instrument");
  if (inputWS) {
    boost::trim(InstrName);
    boost::algorithm::to_lower(InstrName);
    size_t len = InstrName.size();
    /// input property contains name of instrument definition file rather than
    /// instrument name itself
    bool IDF_provided{false};
    // Check if the name ends up with .xml which means that idf file name
    // is provided rather then an instrument name.
    if (len > 4) {
      if (InstrName.compare(len - 4, len, ".xml") == 0) {
        IDF_provided = true;
      } else {
        IDF_provided = false;
      }
    } else {
      IDF_provided = false;
    }
    try {
      auto inst = inputWS->getInstrument();
      std::string Name = inst->getName();
      boost::algorithm::to_lower(Name);
      if (Name != InstrName && !IDF_provided) {
        result["RefWorkspace"] =
            "If both reference workspace and instrument name are defined, "
            "workspace has to have the instrument with the same name\n"
            "'Instrument' value: " +
            InstrName + " Workspace Instrument name: " + Name;
      }
    } catch (Kernel::Exception::NotFoundError &) {
      result["RefWorkspace"] =
          "If reference workspace is defined, it mast have an instrument";
    }
  }

  return result;
}
예제 #19
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...");
  }
}
예제 #20
0
    /** Executes the algorithm. Moving detectors of input workspace to positions indicated in table workspace
    *
    *  @throw FileError Thrown if unable to get instrument from workspace, 
    *                   table workspace is incompatible with instrument
    */
    void ApplyCalibration::exec()
    {
      // Get pointers to the workspace, parameter map and table
      API::MatrixWorkspace_sptr inputWS = getProperty("Workspace");
      m_pmap = &(inputWS->instrumentParameters()); // Avoids a copy if you get the reference before the instrument

      API::ITableWorkspace_sptr PosTable = getProperty("PositionTable");
      Geometry::Instrument_const_sptr instrument = inputWS->getInstrument();
      if(!instrument)
      {
        throw std::runtime_error("Workspace to apply calibration to has no defined instrument");
      }

      size_t numDetector = PosTable->rowCount();
      ColumnVector<int> detID = PosTable->getVector("Detector ID");
      ColumnVector<V3D> detPos = PosTable->getVector("Detector Position");
      // numDetector needs to be got as the number of rows in the table and the detID got from the (i)th row of table.
      for (size_t i = 0; i < numDetector; ++i)
      {
        setDetectorPosition(instrument, detID[i], detPos[i], false );
      }
      // Ensure pointer is only valid for execution
      m_pmap = NULL;
    }
예제 #21
0
    void LoadHelper::rotateComponent(API::MatrixWorkspace_sptr ws, const std::string &componentName,
        const Kernel::Quat & rot)
    {

      try
      {

        Geometry::Instrument_const_sptr instrument = ws->getInstrument();
        Geometry::IComponent_const_sptr component = instrument->getComponentByName(componentName);

        //g_log.debug() << tube->getName() << " : t = " << theta << " ==> t = " << newTheta << "\n";
        Geometry::ParameterMap& pmap = ws->instrumentParameters();
        Geometry::ComponentHelper::rotateComponent(*component, pmap, rot,
            Geometry::ComponentHelper::Absolute);

      } catch (Mantid::Kernel::Exception::NotFoundError&)
      {
        throw std::runtime_error("Error when trying to move the " + componentName + " : NotFoundError");
      } catch (std::runtime_error &)
      {
        throw std::runtime_error("Error when trying to move the " + componentName + " : runtime_error");
      }

    }
예제 #22
0
    /** 
     * Takes a single valued histogram workspace and assesses which histograms are within the limits. 
     * Those that are not are masked on the input workspace.
     * @param countsWS :: Input/Output Integrated workspace to diagnose.
     * @param medianvec The median value calculated from the current counts.
     * @param indexmap Index map.
     * @param maskWS :: A mask workspace to apply.
     * @return The number of detectors that failed the tests, not including those skipped.
     */
    int MedianDetectorTest::doDetectorTests(const API::MatrixWorkspace_sptr countsWS, const std::vector<double> medianvec,
                                            std::vector<std::vector<size_t> > indexmap, API::MatrixWorkspace_sptr maskWS)
    {
      g_log.debug("Applying the criteria to find failing detectors");

      // A spectra can't fail if the statistics show its value is consistent with the mean value, 
      // check the error and how many errorbars we are away
      const double minSigma = getProperty("SignificanceTest");

      // prepare to report progress
      const int numSpec(m_maxSpec - m_minSpec);
      const int progStep = static_cast<int>(ceil(numSpec/30.0));
      int steps(0);

      const double deadValue(1.0);
      int numFailed(0);


      bool checkForMask = false;
      Geometry::Instrument_const_sptr instrument = countsWS->getInstrument();
      if (instrument != NULL)
      {
        checkForMask = ((instrument->getSource() != NULL) && (instrument->getSample() != NULL));
      }

      PARALLEL_FOR2(countsWS, maskWS)
      for (int j=0;j<static_cast<int>(indexmap.size());++j)
      {
        std::vector<size_t> hists=indexmap.at(j);
        double median=medianvec.at(j);
        const size_t nhist = hists.size();
        g_log.debug() << "new component with " <<nhist <<" spectra.\n";
        for (size_t i = 0; i < nhist; ++i)
        {
          g_log.debug() << "Counts workspace index=" << i 
                        << ", Mask workspace index=" << hists.at(i) << std::endl;
          PARALLEL_START_INTERUPT_REGION
          ++steps;
          // update the progressbar information
          if (steps % progStep == 0)
          {
            progress(advanceProgress(progStep*static_cast<double>(RTMarkDetects)/numSpec));
          }

          if (checkForMask)
          {
            const std::set<detid_t>& detids = countsWS->getSpectrum(i)->getDetectorIDs();
            if (instrument->isDetectorMasked(detids))
            {
              maskWS->dataY(hists.at(i))[0] = deadValue;
              continue;
            }
            if (instrument->isMonitor(detids))
            {
              // Don't include in calculation but don't mask it
              continue;
            }
          }

          const double signal = countsWS->dataY(hists.at(i))[0];

          // Mask out NaN and infinite
          if( boost::math::isinf(signal) || boost::math::isnan(signal) )
          {
            maskWS->dataY(hists.at(i))[0] = deadValue;
            PARALLEL_ATOMIC
            ++numFailed;
            continue;
          }

          const double error = minSigma*countsWS->readE(hists.at(i))[0];

          if( (signal < median*m_loFrac && (signal-median < -error)) ||
              (signal > median*m_hiFrac && (signal-median > error)) )
          {
            maskWS->dataY(hists.at(i))[0] = deadValue;
            PARALLEL_ATOMIC
            ++numFailed;
          }

          PARALLEL_END_INTERUPT_REGION
        }
        PARALLEL_CHECK_INTERUPT_REGION

      // Log finds
      g_log.information() << numFailed << " spectra failed the median tests.\n";

      }
      return numFailed;
    }
예제 #23
0
    /** 
     *  Finds the median of values in single bin histograms rejecting spectra from masked
     *  detectors and the results of divide by zero (infinite and NaN).  
     * The median is an average that is less affected by small numbers of very large values.
     * @param input :: A histogram workspace with one entry in each bin
     * @param excludeZeroes :: If true then zeroes will not be included in the median calculation
     * @param indexmap :: indexmap
     * @return The median value of the histograms in the workspace that was passed to it
     * @throw out_of_range if a value is negative
     */
    std::vector<double> DetectorDiagnostic::calculateMedian(const API::MatrixWorkspace_sptr input, bool excludeZeroes, std::vector<std::vector<size_t> > indexmap)
    {
      std::vector<double> medianvec;
      g_log.debug("Calculating the median count rate of the spectra");

      for (size_t j=0;  j< indexmap.size(); ++j)
      {
        std::vector<double> medianInput;
        std::vector<size_t> hists=indexmap.at(j);

        const int nhists = static_cast<int>(hists.size());
        // The maximum possible length is that of workspace length
        medianInput.reserve(nhists);

        bool checkForMask = false;
        Geometry::Instrument_const_sptr instrument = input->getInstrument();
        if (instrument != NULL)
        {
          checkForMask = ((instrument->getSource() != NULL) && (instrument->getSample() != NULL));
        }

        PARALLEL_FOR1(input)
        for (int i = 0; i<static_cast<int>(hists.size()); ++i)
        {
          PARALLEL_START_INTERUPT_REGION

          if (checkForMask) {
            const std::set<detid_t>& detids = input->getSpectrum(hists[i])->getDetectorIDs();
            if (instrument->isDetectorMasked(detids))
              continue;
            if (instrument->isMonitor(detids))
              continue;
          }

          const double yValue = input->readY(hists[i])[0];
          if ( yValue  < 0.0 )
          {
            throw std::out_of_range("Negative number of counts found, could be corrupted raw counts or solid angle data");
          }
          if( boost::math::isnan(yValue) || boost::math::isinf(yValue) ||
              (excludeZeroes && yValue < DBL_EPSILON)) // NaNs/Infs
          {
            continue;
          }
          // Now we have a good value
          PARALLEL_CRITICAL(DetectorDiagnostic_median_d)
          {
            medianInput.push_back(yValue);
          }

          PARALLEL_END_INTERUPT_REGION
        }
        PARALLEL_CHECK_INTERUPT_REGION

        if(medianInput.empty())
        {
          g_log.information("some group has no valid histograms. Will use 0 for median.");
          medianInput.push_back(0.);
        }

        // We need a sorted array to calculate the median
        std::sort(medianInput.begin(), medianInput.end());
        double median = gsl_stats_median_from_sorted_data( &medianInput[0], 1, medianInput.size() );

        if ( median < 0 || median > DBL_MAX/10.0 )
        {
          throw std::out_of_range("The calculated value for the median was either negative or unreliably large");
        }
        medianvec.push_back(median);
      }
      return medianvec;
    }