コード例 #1
0
void ALCDataLoadingPresenter::load()
{
    m_view->setWaitingCursor();

    try
    {
        IAlgorithm_sptr alg = AlgorithmManager::Instance().create("PlotAsymmetryByLogValue");
        alg->setChild(true); // Don't want workspaces in the ADS
        alg->setProperty("FirstRun", m_view->firstRun());
        alg->setProperty("LastRun", m_view->lastRun());
        alg->setProperty("LogValue", m_view->log());
        alg->setProperty("Type", m_view->calculationType());

        // If time limiting requested, set min/max times
        if (auto timeRange = m_view->timeRange())
        {
            alg->setProperty("TimeMin", timeRange->first);
            alg->setProperty("TimeMax", timeRange->second);
        }

        alg->setPropertyValue("OutputWorkspace", "__NotUsed");
        alg->execute();

        m_loadedData = alg->getProperty("OutputWorkspace");

        assert(m_loadedData); // If errors are properly caught, shouldn't happen
        assert(m_loadedData->getNumberHistograms() == 1); // PlotAsymmetryByLogValue guarantees that

        m_view->setDataCurve(*(ALCHelper::curveDataFromWs(m_loadedData, 0)));
    }
    catch(std::exception& e)
    {
        m_view->displayError(e.what());
    }

    m_view->restoreCursor();
}
コード例 #2
0
/**
 * Perform analysis on the given workspace using the parameters supplied
 * (using the MuonProcess algorithm)
 * @param inputWS :: [input] Workspace to analyse (previously grouped and
 * dead-time corrected)
 * @param options :: [input] Struct containing parameters for what sort of
 * analysis to do
 * @returns :: Workspace containing analysed data
 */
Workspace_sptr MuonAnalysisDataLoader::createAnalysisWorkspace(
    const Workspace_sptr inputWS, const AnalysisOptions &options) const {
  IAlgorithm_sptr alg =
      AlgorithmManager::Instance().createUnmanaged("MuonProcess");

  alg->initialize();

  // Set input workspace property
  auto inputGroup = boost::make_shared<WorkspaceGroup>();
  // If is a group, will need to handle periods
  if (auto group = boost::dynamic_pointer_cast<WorkspaceGroup>(inputWS)) {
    for (int i = 0; i < group->getNumberOfEntries(); i++) {
      auto ws = boost::dynamic_pointer_cast<MatrixWorkspace>(group->getItem(i));
      inputGroup->addWorkspace(ws);
    }
    alg->setProperty("SummedPeriodSet", options.summedPeriods);
    alg->setProperty("SubtractedPeriodSet", options.subtractedPeriods);
  } else if (auto ws = boost::dynamic_pointer_cast<MatrixWorkspace>(inputWS)) {
    // Put this single WS into a group and set it as the input property
    inputGroup->addWorkspace(ws);
    alg->setProperty("SummedPeriodSet", "1");
  } else {
    throw std::runtime_error(
        "Cannot create analysis workspace: unsupported workspace type");
  }
  alg->setProperty("InputWorkspace", inputGroup);

  // Set the rest of the algorithm properties
  setProcessAlgorithmProperties(alg, options);

  // We don't want workspace in the ADS so far
  alg->setChild(true);
  alg->setPropertyValue("OutputWorkspace", "__NotUsed");
  alg->execute();
  return alg->getProperty("OutputWorkspace");
}
コード例 #3
0
/**
 * Mask edges of a RectangularDetector
 * @param ws :: Input workspace
 * @param left :: number of columns to mask left
 * @param right :: number of columns to mask right
 * @param high :: number of rows to mask top
 * @param low :: number of rows to mask Bottom
 * @param componentName :: Must be a RectangularDetector
 */
void CalculateEfficiency::maskEdges(MatrixWorkspace_sptr ws, int left,
                                    int right, int high, int low,
                                    const std::string &componentName) {

  auto instrument = ws->getInstrument();

  boost::shared_ptr<Mantid::Geometry::RectangularDetector> component;
  try {
    component =
        boost::const_pointer_cast<Mantid::Geometry::RectangularDetector>(
            boost::dynamic_pointer_cast<
                const Mantid::Geometry::RectangularDetector>(
                instrument->getComponentByName(componentName)));
  } catch (std::exception &) {
    g_log.warning("Expecting the component " + componentName +
                  " to be a RectangularDetector. maskEdges not executed.");
    return;
  }
  if (!component) {
    g_log.warning("Component " + componentName +
                  " is not a RectangularDetector. MaskEdges not executed.");
    return;
  }

  std::vector<int> IDs;
  int i = 0;

  while (i < left * component->idstep()) {
    IDs.push_back(component->idstart() + i);
    i += 1;
  }
  // right
  i = component->maxDetectorID() - right * component->idstep();
  while (i < component->maxDetectorID()) {
    IDs.push_back(i);
    i += 1;
  }
  // low: 0,256,512,768,..,1,257,513
  for (int row = 0; row < low; row++) {
    i = row + component->idstart();
    while (i < component->nelements() * component->idstep() -
                   component->idstep() + low + component->idstart()) {
      IDs.push_back(i);
      i += component->idstep();
    }
  }
  // high # 255, 511, 767..
  for (int row = 0; row < high; row++) {
    i = component->idstep() + component->idstart() - row - 1;
    while (i < component->nelements() * component->idstep() +
                   component->idstart()) {
      IDs.push_back(i);
      i += component->idstep();
    }
  }

  g_log.debug() << "CalculateEfficiency::maskEdges Detector Ids to Mask:"
                << std::endl;
  for (auto id : IDs) {
    g_log.debug() << id << " ";
  }
  g_log.debug() << std::endl;

  IAlgorithm_sptr maskAlg = createChildAlgorithm("MaskDetectors");
  maskAlg->setChild(true);
  maskAlg->setProperty("Workspace", ws);
  maskAlg->setProperty("DetectorList", IDs);
  maskAlg->execute();
}
コード例 #4
0
/** Loads the instrument into a workspace.
 */
void VesuvioL1ThetaResolution::loadInstrument() {
  // Get the filename for the VESUVIO IDF
  MatrixWorkspace_sptr tempWS =
      WorkspaceFactory::Instance().create("Workspace2D", 1, 1, 1);
  const std::string vesuvioIPF = tempWS->getInstrumentFilename("VESUVIO");

  // Load an empty VESUVIO instrument workspace
  IAlgorithm_sptr loadInst =
      AlgorithmManager::Instance().create("LoadEmptyInstrument");
  loadInst->initialize();
  loadInst->setChild(true);
  loadInst->setLogging(false);
  loadInst->setProperty("OutputWorkspace", "__evs");
  loadInst->setProperty("Filename", vesuvioIPF);
  loadInst->execute();
  m_instWorkspace = loadInst->getProperty("OutputWorkspace");

  // Load the PAR file if provided
  const std::string parFilename = getPropertyValue("PARFile");
  if (!parFilename.empty()) {
    g_log.information() << "Loading PAR file: " << parFilename << '\n';

    // Get header format
    std::map<size_t, std::string> headerFormats;
    headerFormats[5] = "spectrum,theta,t0,-,R";
    headerFormats[6] = "spectrum,-,theta,t0,-,R";

    std::ifstream parFile(parFilename);
    if (!parFile) {
      throw std::runtime_error("Cannot open PAR file");
    }
    std::string header;
    getline(parFile, header);
    g_log.debug() << "PAR file header: " << header << '\n';
    boost::trim(header);
    std::vector<std::string> headers;
    boost::split(headers, header, boost::is_any_of("\t "),
                 boost::token_compress_on);
    size_t numCols = headers.size();
    g_log.debug() << "PAR file columns: " << numCols << '\n';

    std::string headerFormat = headerFormats[numCols];
    if (headerFormat.empty()) {
      std::stringstream error;
      error << "Unrecognised PAR file header. Number of colums: " << numCols
            << " (expected either 5 or 6.";
      throw std::runtime_error(error.str());
    }
    g_log.debug() << "PAR file header format: " << headerFormat << '\n';

    // Update instrument
    IAlgorithm_sptr updateInst =
        AlgorithmManager::Instance().create("UpdateInstrumentFromFile");
    updateInst->initialize();
    updateInst->setChild(true);
    updateInst->setLogging(false);
    updateInst->setProperty("Workspace", m_instWorkspace);
    updateInst->setProperty("Filename", parFilename);
    updateInst->setProperty("MoveMonitors", false);
    updateInst->setProperty("IgnorePhi", true);
    updateInst->setProperty("AsciiHeader", headerFormat);
    updateInst->execute();
    m_instWorkspace = updateInst->getProperty("Workspace");
  }

  const int specIdxMin = static_cast<int>(
      m_instWorkspace->getIndexFromSpectrumNumber(getProperty("SpectrumMin")));
  const int specIdxMax = static_cast<int>(
      m_instWorkspace->getIndexFromSpectrumNumber(getProperty("SpectrumMax")));

  // Crop the workspace to just the detectors we are interested in
  IAlgorithm_sptr crop = AlgorithmManager::Instance().create("CropWorkspace");
  crop->initialize();
  crop->setChild(true);
  crop->setLogging(false);
  crop->setProperty("InputWorkspace", m_instWorkspace);
  crop->setProperty("OutputWorkspace", "__evs");
  crop->setProperty("StartWorkspaceIndex", specIdxMin);
  crop->setProperty("EndWorkspaceIndex", specIdxMax);
  crop->execute();
  m_instWorkspace = crop->getProperty("OutputWorkspace");

  m_sample = m_instWorkspace->getInstrument()->getSample();
}
コード例 #5
0
/**
 * Load data from the given files into a struct
 * @param files :: [input] List of files to load
 * @returns :: struct with loaded data
 */
LoadResult MuonAnalysisDataLoader::loadFiles(const QStringList &files) const {
  if (files.empty())
    throw std::invalid_argument("Supplied list of files is empty");

  // Convert list of files into a mangled map key
  const auto toString = [](QStringList qsl) {
    std::ostringstream oss;
    qsl.sort();
    for (const QString &qs : qsl) {
      oss << qs.toStdString() << ",";
    }
    return oss.str();
  };

  // Clean cache from stale files etc
  updateCache();
  // Check cache to see if we've loaded this set of files before
  const std::string fileString = toString(files);
  if (m_loadedDataCache.find(fileString) != m_loadedDataCache.end()) {
    g_log.information("Using cached workspace for file(s): " + fileString);
    return m_loadedDataCache[fileString];
  }

  LoadResult result;

  std::vector<Workspace_sptr> loadedWorkspaces;

  std::string instrName; // Instrument name all the run files should belong to

  // Go through all the files and try to load them
  for (const auto &fileName : files) {
    std::string file = fileName.toStdString();

    // Set up load algorithm
    IAlgorithm_sptr load =
        AlgorithmManager::Instance().createUnmanaged("LoadMuonNexus");

    load->initialize();
    load->setChild(true);
    load->setPropertyValue("Filename", file);

    // Just to pass validation
    load->setPropertyValue("OutputWorkspace", "__NotUsed");

    if (fileName == files.first()) {
      // These are only needed for the first file
      if (m_deadTimesType == DeadTimesType::FromFile) {
        load->setPropertyValue("DeadTimeTable", "__NotUsed");
      }
      load->setPropertyValue("DetectorGroupingTable", "__NotUsed");
    }

    load->execute();

    Workspace_sptr loadedWorkspace = load->getProperty("OutputWorkspace");

    if (fileName == files.first()) {
      instrName = getInstrumentName(loadedWorkspace);

      // Check that it is a valid Muon instrument
      if (!m_instruments.contains(QString::fromStdString(instrName),
                                  Qt::CaseInsensitive)) {
        if (0 != instrName.compare("DEVA")) {
          // special case - no IDF but let it load anyway
          throw std::runtime_error("Instrument is not recognized: " +
                                   instrName);
        }
      }

      if (m_deadTimesType == DeadTimesType::FromFile) {
        result.loadedDeadTimes = load->getProperty("DeadTimeTable");
      }
      result.loadedGrouping = load->getProperty("DetectorGroupingTable");
      result.mainFieldDirection =
          static_cast<std::string>(load->getProperty("MainFieldDirection"));
      result.timeZero = load->getProperty("TimeZero");
      result.firstGoodData = load->getProperty("FirstGoodData");
    } else {
      if (getInstrumentName(loadedWorkspace) != instrName)
        throw std::runtime_error(
            "All the files should be produced by the same instrument");
    }

    loadedWorkspaces.push_back(loadedWorkspace);
  }

  // Some of the ARGUS data files contain wrong information about the
  // instrument main field direction. It is always longitudinal.
  if (instrName == "ARGUS") {
    result.mainFieldDirection = "longitudinal";
  }

  if (loadedWorkspaces.size() == 1) {
    // If single workspace loaded - use it
    Workspace_sptr ws = loadedWorkspaces.front();
    result.loadedWorkspace = ws;
    result.label = MuonAnalysisHelper::getRunLabel(ws);
  } else {
    // If multiple workspaces loaded - sum them to get the one to work with
    try {
      result.loadedWorkspace =
          MuonAnalysisHelper::sumWorkspaces(loadedWorkspaces);
    } catch (std::exception &e) {
      std::ostringstream error;
      error << "Unable to sum workspaces together: " << e.what() << "\n";
      error << "Make sure they have equal dimensions and number of periods.";
      throw std::runtime_error(error.str());
    }
    result.label = MuonAnalysisHelper::getRunLabel(loadedWorkspaces);
  }

  // Cache the result if we should so we don't have to load it next time
  if (shouldBeCached(files)) {
    g_log.information("Caching loaded workspace for file(s): " + fileString);
    m_loadedDataCache[fileString] = result;
  }
  return result;
}
コード例 #6
0
    /**
    Stitches the workspaces created by the given rows together.
    @param rows : the list of rows
    */
    void ReflMainViewPresenter::stitchRows(std::vector<size_t> rows)
    {
      //If we can get away with doing nothing, do.
      if(rows.size() < 2)
        return;

      //Ensure the rows are in order.
      std::sort(rows.begin(), rows.end());

      //Properties for Stitch1DMany
      std::vector<std::string> wsNames;
      std::vector<std::string> runs;

      std::vector<double> params;
      std::vector<double> startOverlaps;
      std::vector<double> endOverlaps;

      //Go through each row and prepare the properties
      for(auto rowIt = rows.begin(); rowIt != rows.end(); ++rowIt)
      {
        const std::string  runStr = m_model->String(*rowIt, COL_RUNS);
        const std::string qMinStr = m_model->String(*rowIt, COL_QMIN);
        const std::string qMaxStr = m_model->String(*rowIt, COL_QMAX);

        double qmin, qmax;
        Mantid::Kernel::Strings::convert<double>(qMinStr, qmin);
        Mantid::Kernel::Strings::convert<double>(qMaxStr, qmax);

        runs.push_back(runStr);
        wsNames.push_back(runStr + "_IvsQ");
        startOverlaps.push_back(qmin);
        endOverlaps.push_back(qmax);
      }

      double dqq;
      std::string dqqStr = m_model->String(rows.front(), COL_DQQ);
      Mantid::Kernel::Strings::convert<double>(dqqStr, dqq);

      //params are qmin, -dqq, qmax for the final output
      params.push_back(*std::min_element(startOverlaps.begin(), startOverlaps.end()));
      params.push_back(-dqq);
      params.push_back(*std::max_element(endOverlaps.begin(), endOverlaps.end()));

      //startOverlaps and endOverlaps need to be slightly offset from each other
      //See usage examples of Stitch1DMany to see why we discard first qmin and last qmax
      startOverlaps.erase(startOverlaps.begin());
      endOverlaps.pop_back();

      std::string outputWSName = boost::algorithm::join(runs, "_") + "_IvsQ";

      IAlgorithm_sptr algStitch = AlgorithmManager::Instance().create("Stitch1DMany");
      algStitch->initialize();
      algStitch->setChild(true);
      algStitch->setProperty("InputWorkspaces", boost::algorithm::join(wsNames, ","));
      algStitch->setProperty("OutputWorkspace", outputWSName);
      algStitch->setProperty("Params", params);
      algStitch->setProperty("StartOverlaps", startOverlaps);
      algStitch->setProperty("EndOverlaps", endOverlaps);

      algStitch->execute();

      if(!algStitch->isExecuted())
        throw std::runtime_error("Failed to run Stitch1DMany on IvsQ workspaces.");

      Workspace_sptr stitchedWS = algStitch->getProperty("OutputWorkspace");

      //Insert the final stitched row into the ADS
      AnalysisDataService::Instance().addOrReplace(outputWSName, stitchedWS);
    }
コード例 #7
0
/**
 * Handles creating a diff of two workspaces and plotting it.
 */
void DataComparison::plotDiffWorkspace()
{
  // Detach old curve
  if(m_diffCurve != NULL)
    m_diffCurve->attach(NULL);

  // Do nothing if there are not two workspaces
  if(m_diffWorkspaceNames.first.isEmpty() || m_diffWorkspaceNames.second.isEmpty())
    return;

  // Get pointers to the workspaces to be diffed
  MatrixWorkspace_sptr ws1 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
      m_diffWorkspaceNames.first.toStdString());
  MatrixWorkspace_sptr ws2 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
      m_diffWorkspaceNames.second.toStdString());

  int ws1Spec = 0;
  int ws2Spec = 0;

  // Get the current spectrum for each workspace
  int numRows = m_uiForm.twCurrentData->rowCount();
  for(int row = 0; row < numRows; row++)
  {
    QString workspaceName = m_uiForm.twCurrentData->item(row, WORKSPACE_NAME)->text();
    QString currentSpecName = m_uiForm.twCurrentData->item(row, CURRENT_SPEC)->text();
    bool ok = false;
    bool found = false;

    if(workspaceName == m_diffWorkspaceNames.first)
    {
      ws1Spec = currentSpecName.toInt(&ok);
      found = true;
    }
    if(workspaceName == m_diffWorkspaceNames.second)
    {
      ws2Spec = currentSpecName.toInt(&ok);
      found = true;
    }

    // Check that the spectra are not out of range
    if(!ok && found)
    {
      // Set info message
      QString infoMessage = workspaceName + ": Index out of range.";
      m_uiForm.lbDiffInfo->setText(infoMessage);
      return;
    }
  }

  // Extract the current spectrum for both workspaces
  IAlgorithm_sptr extractWs1Alg = AlgorithmManager::Instance().create("ExtractSingleSpectrum");
  extractWs1Alg->setChild(true);
  extractWs1Alg->initialize();
  extractWs1Alg->setProperty("InputWorkspace", ws1);
  extractWs1Alg->setProperty("OutputWorkspace", "__ws1_spec");
  extractWs1Alg->setProperty("WorkspaceIndex", ws1Spec);
  extractWs1Alg->execute();
  MatrixWorkspace_sptr ws1SpecWs = extractWs1Alg->getProperty("OutputWorkspace");

  IAlgorithm_sptr extractWs2Alg = AlgorithmManager::Instance().create("ExtractSingleSpectrum");
  extractWs2Alg->setChild(true);
  extractWs2Alg->initialize();
  extractWs2Alg->setProperty("InputWorkspace", ws2);
  extractWs2Alg->setProperty("OutputWorkspace", "__ws2_spec");
  extractWs2Alg->setProperty("WorkspaceIndex", ws2Spec);
  extractWs2Alg->execute();
  MatrixWorkspace_sptr ws2SpecWs = extractWs2Alg->getProperty("OutputWorkspace");

  // Rebin the second workspace to the first
  // (needed for identical binning for Minus algorithm)
  IAlgorithm_sptr rebinAlg = AlgorithmManager::Instance().create("RebinToWorkspace");
  rebinAlg->setChild(true);
  rebinAlg->initialize();
  rebinAlg->setProperty("WorkspaceToRebin", ws2SpecWs);
  rebinAlg->setProperty("WorkspaceToMatch", ws1SpecWs);
  rebinAlg->setProperty("OutputWorkspace", "__ws2_spec_rebin");
  rebinAlg->execute();
  MatrixWorkspace_sptr rebinnedWs2SpecWs = rebinAlg->getProperty("OutputWorkspace");

  // Subtract the two extracted spectra
  IAlgorithm_sptr minusAlg = AlgorithmManager::Instance().create("Minus");
  minusAlg->setChild(true);
  minusAlg->initialize();
  minusAlg->setProperty("LHSWorkspace", ws1SpecWs);
  minusAlg->setProperty("RHSWorkspace", rebinnedWs2SpecWs);
  minusAlg->setProperty("OutputWorkspace", "__diff");
  minusAlg->execute();
  MatrixWorkspace_sptr diffWorkspace = minusAlg->getProperty("OutputWorkspace");

  // Create curve and add to plot
  QwtWorkspaceSpectrumData wsData(*diffWorkspace, 0, false, false);
  boost::shared_ptr<QwtPlotCurve> curve(new QwtPlotCurve);
  curve->setData(wsData);
  curve->setPen(QColor(Qt::green));
  curve->attach(m_plot);
  m_diffCurve = curve;

  // Set info message
  QString infoMessage = m_diffWorkspaceNames.first + "(" + QString::number(ws1Spec) + ") - "
                      + m_diffWorkspaceNames.second + "(" + QString::number(ws2Spec) + ")";
  m_uiForm.lbDiffInfo->setText(infoMessage);
}
コード例 #8
0
/**
 * Load new data and update the view accordingly
 * @param lastFile :: [input] Last file in range (user-specified or auto)
 */
void ALCDataLoadingPresenter::load(const std::string &lastFile) {
  m_view->disableAll();
  // Use Path.toString() to ensure both are in same (native) format
  Poco::Path firstRun(m_view->firstRun());
  Poco::Path lastRun(lastFile);

  // Before loading, check custom grouping (if used) is sensible
  const bool groupingOK = checkCustomGrouping();
  if (!groupingOK) {
    m_view->displayError(
        "Custom grouping not valid (bad format or detector numbers)");
    m_view->enableAll();
    return;
  }

  try {
    IAlgorithm_sptr alg =
        AlgorithmManager::Instance().create("PlotAsymmetryByLogValue");
    alg->setChild(true); // Don't want workspaces in the ADS
    alg->setProperty("FirstRun", firstRun.toString());
    alg->setProperty("LastRun", lastRun.toString());
    alg->setProperty("LogValue", m_view->log());
    alg->setProperty("Function", m_view->function());
    alg->setProperty("Type", m_view->calculationType());
    alg->setProperty("DeadTimeCorrType", m_view->deadTimeType());
    alg->setProperty("Red", m_view->redPeriod());

    // If time limiting requested, set min/max times
    if (auto timeRange = m_view->timeRange()) {
      double timeMin = (*timeRange).first;
      double timeMax = (*timeRange).second;
      if (timeMin >= timeMax) {
        throw std::invalid_argument("Invalid time limits");
      }
      alg->setProperty("TimeMin", timeMin);
      alg->setProperty("TimeMax", timeMax);
    }

    // If corrections from custom file requested, set file property
    if (m_view->deadTimeType() == "FromSpecifiedFile") {
      alg->setProperty("DeadTimeCorrFile", m_view->deadTimeFile());
    }

    // If custom grouping requested, set forward/backward groupings
    if (m_view->detectorGroupingType() == "Custom") {
      alg->setProperty("ForwardSpectra", m_view->getForwardGrouping());
      alg->setProperty("BackwardSpectra", m_view->getBackwardGrouping());
    }

    // If Subtract checkbox is selected, set green period
    if (m_view->subtractIsChecked()) {
      alg->setProperty("Green", m_view->greenPeriod());
    }

    alg->setPropertyValue("OutputWorkspace", "__NotUsed");

    // Execute async so we can show progress bar
    Poco::ActiveResult<bool> result(alg->executeAsync());
    while (!result.available()) {
      QCoreApplication::processEvents();
    }
    if (!result.error().empty()) {
      throw std::runtime_error(result.error());
    }

    m_loadedData = alg->getProperty("OutputWorkspace");

    // If errors are properly caught, shouldn't happen
    assert(m_loadedData);
    // If subtract is not checked, only one spectrum,
    // else four spectra
    if (!m_view->subtractIsChecked()) {
      assert(m_loadedData->getNumberHistograms() == 1);
    } else {
      assert(m_loadedData->getNumberHistograms() == 4);
    }

    // Plot spectrum 0. It is either red period (if subtract is unchecked) or
    // red - green (if subtract is checked)
    m_view->setDataCurve(*(ALCHelper::curveDataFromWs(m_loadedData, 0)),
                         ALCHelper::curveErrorsFromWs(m_loadedData, 0));

    emit dataChanged();

  } catch (std::exception &e) {
    m_view->displayError(e.what());
  }

  m_view->enableAll();
}
コード例 #9
0
void HFIRDarkCurrentSubtraction::exec()
{
  std::string output_message = "";
  // Reduction property manager
  const std::string reductionManagerName = getProperty("ReductionProperties");
  boost::shared_ptr<PropertyManager> reductionManager;
  if (PropertyManagerDataService::Instance().doesExist(reductionManagerName))
  {
    reductionManager = PropertyManagerDataService::Instance().retrieve(reductionManagerName);
  }
  else
  {
    reductionManager = boost::make_shared<PropertyManager>();
    PropertyManagerDataService::Instance().addOrReplace(reductionManagerName, reductionManager);
  }

  // If the load algorithm isn't in the reduction properties, add it
  const bool persistent = getProperty("PersistentCorrection");
  if (!reductionManager->existsProperty("DarkCurrentAlgorithm") && persistent)
  {
    AlgorithmProperty *algProp = new AlgorithmProperty("DarkCurrentAlgorithm");
    algProp->setValue(toString());
    reductionManager->declareProperty(algProp);
  }

  Progress progress(this,0.0,1.0,10);

  MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
  const std::string fileName = getPropertyValue("Filename");
  MatrixWorkspace_sptr darkWS;
  std::string darkWSName = getPropertyValue("OutputDarkCurrentWorkspace");

  progress.report("Subtracting dark current");

  // Look for an entry for the dark current in the reduction table
  Poco::Path path(fileName);
  const std::string entryName = "DarkCurrent"+path.getBaseName();

  if (reductionManager->existsProperty(entryName))
  {
    darkWS = reductionManager->getProperty(entryName);
    darkWSName = reductionManager->getPropertyValue(entryName);
    output_message += darkWSName + '\n';
  } else {
    // Load the dark current if we don't have it already
    if (darkWSName.size()==0)
    {
      darkWSName = "__dark_current_"+path.getBaseName();
      setPropertyValue("OutputDarkCurrentWorkspace", darkWSName);
    }

    IAlgorithm_sptr loadAlg;
    if (!reductionManager->existsProperty("LoadAlgorithm"))
    {
      loadAlg = createChildAlgorithm("HFIRLoad", 0.1, 0.3);
      loadAlg->setProperty("Filename", fileName);
      loadAlg->setProperty("ReductionProperties", reductionManagerName);
      loadAlg->executeAsChildAlg();
    } else {
      IAlgorithm_sptr loadAlg0 = reductionManager->getProperty("LoadAlgorithm");
      const std::string loadString = loadAlg0->toString();
      loadAlg = Algorithm::fromString(loadString);
      loadAlg->setChild(true);
      loadAlg->setProperty("Filename", fileName);
      loadAlg->setProperty("ReductionProperties", reductionManagerName);
      loadAlg->setPropertyValue("OutputWorkspace", darkWSName);
      loadAlg->execute();
    }
    darkWS = loadAlg->getProperty("OutputWorkspace");
    output_message += "\n   Loaded " + fileName + "\n";
    if (loadAlg->existsProperty("OutputMessage"))
    {
      std::string msg = loadAlg->getPropertyValue("OutputMessage");
      output_message += "   |" + Poco::replace(msg, "\n", "\n   |") + "\n";
    }

    setProperty("OutputDarkCurrentWorkspace", darkWS);
    reductionManager->declareProperty(new WorkspaceProperty<>(entryName,"",Direction::Output));
    reductionManager->setPropertyValue(entryName, darkWSName);
    reductionManager->setProperty(entryName, darkWS);
  }
  progress.report(3, "Loaded dark current");

  // Perform subtraction
  double darkTimer = getCountingTime(darkWS);
  double dataTimer = getCountingTime(inputWS);
  IAlgorithm_sptr scaleAlg = createChildAlgorithm("Scale", 0.3, 0.5);
  scaleAlg->setProperty("InputWorkspace", darkWS);
  scaleAlg->setProperty("Factor", dataTimer/darkTimer);
  scaleAlg->setProperty("Operation", "Multiply");
  scaleAlg->executeAsChildAlg();
  MatrixWorkspace_sptr scaledDarkWS = scaleAlg->getProperty("OutputWorkspace");

  // Zero out timer and monitor so that we don't subtract them out
  for(size_t i=0; i<scaledDarkWS->dataY(0).size(); i++)
  {
    scaledDarkWS->dataY(DEFAULT_TIMER_ID)[i]=0.0;
    scaledDarkWS->dataE(DEFAULT_TIMER_ID)[i]=0.0;
    scaledDarkWS->dataY(DEFAULT_MONITOR_ID)[i]=0.0;
    scaledDarkWS->dataE(DEFAULT_MONITOR_ID)[i]=0.0;
  }
  IAlgorithm_sptr minusAlg = createChildAlgorithm("Minus", 0.5, 0.7);
  minusAlg->setProperty("LHSWorkspace", inputWS);
  minusAlg->setProperty("RHSWorkspace", scaledDarkWS);
  MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
  minusAlg->setProperty("OutputWorkspace", outputWS);
  minusAlg->executeAsChildAlg();
  MatrixWorkspace_sptr correctedWS = minusAlg->getProperty("OutputWorkspace");
  setProperty("OutputWorkspace", correctedWS);
  setProperty("OutputMessage", "Dark current subtracted: "+output_message);

  progress.report("Subtracted dark current");
}
コード例 #10
0
void SANSSensitivityCorrection::exec() {
  // Output log
  m_output_message = "";

  Progress progress(this, 0.0, 1.0, 10);

  // Reduction property manager
  const std::string reductionManagerName = getProperty("ReductionProperties");
  boost::shared_ptr<PropertyManager> reductionManager;
  if (PropertyManagerDataService::Instance().doesExist(reductionManagerName)) {
    reductionManager =
        PropertyManagerDataService::Instance().retrieve(reductionManagerName);
  } else {
    reductionManager = boost::make_shared<PropertyManager>();
    PropertyManagerDataService::Instance().addOrReplace(reductionManagerName,
                                                        reductionManager);
  }

  if (!reductionManager->existsProperty("SensitivityAlgorithm")) {
    auto algProp = make_unique<AlgorithmProperty>("SensitivityAlgorithm");
    algProp->setValue(toString());
    reductionManager->declareProperty(std::move(algProp));
  }

  progress.report("Loading sensitivity file");
  const std::string fileName = getPropertyValue("Filename");

  // Look for an entry for the dark current in the reduction table
  Poco::Path path(fileName);
  const std::string entryName = "Sensitivity" + path.getBaseName();
  MatrixWorkspace_sptr floodWS;
  std::string floodWSName = "__sensitivity_" + path.getBaseName();

  if (reductionManager->existsProperty(entryName)) {
    std::string wsName = reductionManager->getPropertyValue(entryName);
    floodWS = boost::dynamic_pointer_cast<MatrixWorkspace>(
        AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(wsName));
    m_output_message += "   |Using " + wsName + "\n";
    g_log.debug()
        << "SANSSensitivityCorrection :: Using sensitivity workspace: "
        << wsName << "\n";
  } else {
    // Load the flood field if we don't have it already
    // First, try to determine whether we need to load data or a sensitivity
    // workspace...
    if (!floodWS && fileCheck(fileName)) {
      g_log.debug() << "SANSSensitivityCorrection :: Loading sensitivity file: "
                    << fileName << "\n";
      IAlgorithm_sptr loadAlg = createChildAlgorithm("Load", 0.1, 0.3);
      loadAlg->setProperty("Filename", fileName);
      loadAlg->executeAsChildAlg();
      Workspace_sptr floodWS_ws = loadAlg->getProperty("OutputWorkspace");
      floodWS = boost::dynamic_pointer_cast<MatrixWorkspace>(floodWS_ws);

      // Check that it's really a sensitivity file
      if (!floodWS->run().hasProperty("is_sensitivity")) {
        // Reset pointer
        floodWS.reset();
        g_log.error() << "A processed Mantid workspace was loaded but it "
                         "wasn't a sensitivity file!\n";
      }
    }

    // ... if we don't, just load the data and process it
    if (!floodWS) {
      // Read in default beam center
      double center_x = getProperty("BeamCenterX");
      double center_y = getProperty("BeamCenterY");
      if (isEmpty(center_x) || isEmpty(center_y)) {
        if (reductionManager->existsProperty("LatestBeamCenterX") &&
            reductionManager->existsProperty("LatestBeamCenterY")) {
          center_x = reductionManager->getProperty("LatestBeamCenterX");
          center_y = reductionManager->getProperty("LatestBeamCenterY");
          m_output_message +=
              "   |Setting beam center to [" +
              Poco::NumberFormatter::format(center_x, 1) + ", " +
              Poco::NumberFormatter::format(center_y, 1) + "]\n";
        } else
          m_output_message += "   |No beam center provided: skipping!\n";
      }

      const std::string rawFloodWSName = "__flood_data_" + path.getBaseName();
      MatrixWorkspace_sptr rawFloodWS;
      if (!reductionManager->existsProperty("LoadAlgorithm")) {
        IAlgorithm_sptr loadAlg = createChildAlgorithm("Load", 0.1, 0.3);
        loadAlg->setProperty("Filename", fileName);
        if (!isEmpty(center_x) && loadAlg->existsProperty("BeamCenterX"))
          loadAlg->setProperty("BeamCenterX", center_x);
        if (!isEmpty(center_y) && loadAlg->existsProperty("BeamCenterY"))
          loadAlg->setProperty("BeamCenterY", center_y);
        loadAlg->setPropertyValue("OutputWorkspace", rawFloodWSName);
        loadAlg->executeAsChildAlg();
        Workspace_sptr tmpWS = loadAlg->getProperty("OutputWorkspace");
        rawFloodWS = boost::dynamic_pointer_cast<MatrixWorkspace>(tmpWS);
        m_output_message += "   | Loaded " + fileName + " (Load algorithm)\n";
      } else {
        // Get load algorithm as a string so that we can create a completely
        // new proxy and ensure that we don't overwrite existing properties
        IAlgorithm_sptr loadAlg0 =
            reductionManager->getProperty("LoadAlgorithm");
        const std::string loadString = loadAlg0->toString();
        IAlgorithm_sptr loadAlg = Algorithm::fromString(loadString);
        loadAlg->setChild(true);
        loadAlg->setProperty("Filename", fileName);
        loadAlg->setPropertyValue("OutputWorkspace", rawFloodWSName);
        if (!isEmpty(center_x) && loadAlg->existsProperty("BeamCenterX"))
          loadAlg->setProperty("BeamCenterX", center_x);
        if (!isEmpty(center_y) && loadAlg->existsProperty("BeamCenterY"))
          loadAlg->setProperty("BeamCenterY", center_y);
        loadAlg->execute();
        rawFloodWS = loadAlg->getProperty("OutputWorkspace");
        m_output_message += "   |Loaded " + fileName + "\n";
        if (loadAlg->existsProperty("OutputMessage")) {
          std::string msg = loadAlg->getPropertyValue("OutputMessage");
          m_output_message +=
              "   |" + Poco::replace(msg, "\n", "\n   |") + "\n";
        }
      }

      // Check whether we just loaded a flood field data set, or the actual
      // sensitivity
      if (!rawFloodWS->run().hasProperty("is_sensitivity")) {
        const std::string darkCurrentFile = getPropertyValue("DarkCurrentFile");

        // Look for a dark current subtraction algorithm
        std::string dark_result;
        if (reductionManager->existsProperty("DarkCurrentAlgorithm")) {
          IAlgorithm_sptr darkAlg =
              reductionManager->getProperty("DarkCurrentAlgorithm");
          darkAlg->setChild(true);
          darkAlg->setProperty("InputWorkspace", rawFloodWS);
          darkAlg->setProperty("OutputWorkspace", rawFloodWS);

          // Execute as-is if we use the sample dark current, otherwise check
          // whether a dark current file was provided.
          // Otherwise do nothing
          if (getProperty("UseSampleDC")) {
            darkAlg->execute();
            if (darkAlg->existsProperty("OutputMessage"))
              dark_result = darkAlg->getPropertyValue("OutputMessage");
          } else if (!darkCurrentFile.empty()) {
            darkAlg->setProperty("Filename", darkCurrentFile);
            darkAlg->setProperty("PersistentCorrection", false);
            darkAlg->execute();
            if (darkAlg->existsProperty("OutputMessage"))
              dark_result = darkAlg->getPropertyValue("OutputMessage");
            else
              dark_result = "   Dark current subtracted\n";
          }
        } else if (!darkCurrentFile.empty()) {
          // We need to subtract the dark current for the flood field but no
          // dark
          // current subtraction was set for the sample! Use the default dark
          // current algorithm if we can find it.
          if (reductionManager->existsProperty("DefaultDarkCurrentAlgorithm")) {
            IAlgorithm_sptr darkAlg =
                reductionManager->getProperty("DefaultDarkCurrentAlgorithm");
            darkAlg->setChild(true);
            darkAlg->setProperty("InputWorkspace", rawFloodWS);
            darkAlg->setProperty("OutputWorkspace", rawFloodWS);
            darkAlg->setProperty("Filename", darkCurrentFile);
            darkAlg->setProperty("PersistentCorrection", false);
            darkAlg->execute();
            if (darkAlg->existsProperty("OutputMessage"))
              dark_result = darkAlg->getPropertyValue("OutputMessage");
          } else {
            // We are running out of options
            g_log.error() << "No dark current algorithm provided to load ["
                          << getPropertyValue("DarkCurrentFile")
                          << "]: skipped!\n";
            dark_result = "   No dark current algorithm provided: skipped\n";
          }
        }
        m_output_message +=
            "   |" + Poco::replace(dark_result, "\n", "\n   |") + "\n";

        // Look for solid angle correction algorithm
        if (reductionManager->existsProperty("SANSSolidAngleCorrection")) {
          IAlgorithm_sptr solidAlg =
              reductionManager->getProperty("SANSSolidAngleCorrection");
          solidAlg->setChild(true);
          solidAlg->setProperty("InputWorkspace", rawFloodWS);
          solidAlg->setProperty("OutputWorkspace", rawFloodWS);
          solidAlg->execute();
          std::string msg = "Solid angle correction applied\n";
          if (solidAlg->existsProperty("OutputMessage"))
            msg = solidAlg->getPropertyValue("OutputMessage");
          m_output_message +=
              "   |" + Poco::replace(msg, "\n", "\n   |") + "\n";
        }

        // Apply transmission correction as needed
        double floodTransmissionValue = getProperty("FloodTransmissionValue");
        double floodTransmissionError = getProperty("FloodTransmissionError");

        if (!isEmpty(floodTransmissionValue)) {
          g_log.debug() << "SANSSensitivityCorrection :: Applying transmission "
                           "to flood field\n";
          IAlgorithm_sptr transAlg =
              createChildAlgorithm("ApplyTransmissionCorrection");
          transAlg->setProperty("InputWorkspace", rawFloodWS);
          transAlg->setProperty("OutputWorkspace", rawFloodWS);
          transAlg->setProperty("TransmissionValue", floodTransmissionValue);
          transAlg->setProperty("TransmissionError", floodTransmissionError);
          transAlg->setProperty("ThetaDependent", true);
          transAlg->execute();
          rawFloodWS = transAlg->getProperty("OutputWorkspace");
          m_output_message += "   |Applied transmission to flood field\n";
        }

        // Calculate detector sensitivity
        IAlgorithm_sptr effAlg = createChildAlgorithm("CalculateEfficiency");
        effAlg->setProperty("InputWorkspace", rawFloodWS);

        const double minEff = getProperty("MinEfficiency");
        const double maxEff = getProperty("MaxEfficiency");
        const std::string maskFullComponent =
            getPropertyValue("MaskedFullComponent");
        const std::string maskEdges = getPropertyValue("MaskedEdges");
        const std::string maskComponent = getPropertyValue("MaskedComponent");

        effAlg->setProperty("MinEfficiency", minEff);
        effAlg->setProperty("MaxEfficiency", maxEff);
        effAlg->setProperty("MaskedFullComponent", maskFullComponent);
        effAlg->setProperty("MaskedEdges", maskEdges);
        effAlg->setProperty("MaskedComponent", maskComponent);
        effAlg->execute();
        floodWS = effAlg->getProperty("OutputWorkspace");
      } else {
        floodWS = rawFloodWS;
      }
      // Patch as needed
      if (reductionManager->existsProperty("SensitivityPatchAlgorithm")) {
        IAlgorithm_sptr patchAlg =
            reductionManager->getProperty("SensitivityPatchAlgorithm");
        patchAlg->setChild(true);
        patchAlg->setProperty("Workspace", floodWS);
        patchAlg->execute();
        m_output_message += "   |Sensitivity patch applied\n";
      }

      floodWS->mutableRun().addProperty("is_sensitivity", 1, "", true);
    }
    std::string floodWSOutputName =
        getPropertyValue("OutputSensitivityWorkspace");
    if (floodWSOutputName.empty()) {
      setPropertyValue("OutputSensitivityWorkspace", floodWSName);
      AnalysisDataService::Instance().addOrReplace(floodWSName, floodWS);
      reductionManager->declareProperty(
          Kernel::make_unique<WorkspaceProperty<>>(entryName, floodWSName,
                                                   Direction::InOut));
      reductionManager->setPropertyValue(entryName, floodWSName);
      reductionManager->setProperty(entryName, floodWS);
    }
    setProperty("OutputSensitivityWorkspace", floodWS);
  }

  progress.report(3, "Loaded flood field");

  // Check whether we need to apply the correction to a workspace
  MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
  if (inputWS) {
    // Divide sample data by detector efficiency
    IAlgorithm_sptr divideAlg = createChildAlgorithm("Divide", 0.6, 0.7);
    divideAlg->setProperty("LHSWorkspace", inputWS);
    divideAlg->setProperty("RHSWorkspace", floodWS);
    divideAlg->executeAsChildAlg();
    MatrixWorkspace_sptr outputWS = divideAlg->getProperty("OutputWorkspace");

    // Copy over the efficiency's masked pixels to the reduced workspace
    IAlgorithm_sptr maskAlg = createChildAlgorithm("MaskDetectors", 0.75, 0.85);
    maskAlg->setProperty("Workspace", outputWS);
    maskAlg->setProperty("MaskedWorkspace", floodWS);
    maskAlg->executeAsChildAlg();

    setProperty("OutputWorkspace", outputWS);
  }
  setProperty("OutputMessage",
              "Sensitivity correction computed\n" + m_output_message);

  progress.report("Performed sensitivity correction");
}