/**
 * @brief Handle setting fit workspace.
 *
 * Creates a list of Q values from each spectrum to be used with WorkspaceIndex
 * attribute.
 *
 * @param ws Pointer to workspace
 */
void InelasticDiffSphere::setWorkspace(
    boost::shared_ptr<const API::Workspace> ws) {
  m_qValueCache.clear();

  auto workspace = boost::dynamic_pointer_cast<const API::MatrixWorkspace>(ws);
  if (!workspace)
    return;

  size_t numHist = workspace->getNumberHistograms();
  for (size_t idx = 0; idx < numHist; idx++) {
    Mantid::Geometry::IDetector_const_sptr det;
    try {
      det = workspace->getDetector(idx);
    } catch (Kernel::Exception::NotFoundError &) {
      m_qValueCache.clear();
      g_log.information("Cannot populate Q values from workspace");
      break;
    }

    try {
      double efixed = workspace->getEFixed(det);
      double usignTheta = 0.5 * workspace->detectorTwoTheta(*det);

      double q = Mantid::Kernel::UnitConversion::run(usignTheta, efixed);

      m_qValueCache.push_back(q);
    } catch (std::runtime_error &) {
      m_qValueCache.clear();
      g_log.information("Cannot populate Q values from workspace");
      return;
    }
  }
}
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");
}
void ConvFitModel::addExtendedResolution(std::size_t index) {
  const std::string name = "__ConvFitResolution" + std::to_string(index);

  extendResolutionWorkspace(m_resolution[index].lock(),
                            getNumberHistograms(index), name);

  if (m_extendedResolution.size() > index)
    m_extendedResolution[index] = name;
  else
    m_extendedResolution.emplace_back(name);
}
/// Constructor.
/// @param wsName :: Name of a MatrixWorkspace with the data for fitting.
/// @param wsIndex :: Workspace index of a spectrum in wsName to plot.
/// @param outputWSName :: Name of the Fit's output workspace containing at
/// least 3 spectra:
///    #0 - original data (the same as in wsName[wsIndex]), #1 - calculated
///    data, #3 - difference.
///    If empty - ignore this workspace.
DatasetPlotData::DatasetPlotData(const QString &wsName, int wsIndex,
                                 const QString &outputWSName)
    : m_dataCurve(new QwtPlotCurve(wsName + QString(" (%1)").arg(wsIndex))),
      m_dataErrorCurve(NULL), m_calcCurve(NULL), m_diffCurve(NULL),
      m_showDataErrorBars(false) {
  // get the data workspace
  auto ws = Mantid::API::AnalysisDataService::Instance()
                .retrieveWS<Mantid::API::MatrixWorkspace>(wsName.toStdString());
  if (!ws) {
    QString mess =
        QString("Workspace %1 either doesn't exist or isn't a MatrixWorkspace")
            .arg(wsName);
    throw std::runtime_error(mess.toStdString());
  }
  // check that the index is in range
  if (static_cast<size_t>(wsIndex) >= ws->getNumberHistograms()) {
    QString mess = QString("Spectrum %1 doesn't exist in workspace %2")
                       .arg(wsIndex)
                       .arg(wsName);
    throw std::runtime_error(mess.toStdString());
  }

  // get the data workspace
  Mantid::API::MatrixWorkspace_sptr outputWS;
  if (!outputWSName.isEmpty()) {
    std::string stdOutputWSName = outputWSName.toStdString();
    if (Mantid::API::AnalysisDataService::Instance().doesExist(
            stdOutputWSName)) {
      try {
        outputWS =
            Mantid::API::AnalysisDataService::Instance()
                .retrieveWS<Mantid::API::MatrixWorkspace>(stdOutputWSName);
      } catch (Mantid::Kernel::Exception::NotFoundError &) {
        QString mess =
            QString(
                "Workspace %1 either doesn't exist or isn't a MatrixWorkspace")
                .arg(outputWSName);
        throw std::runtime_error(mess.toStdString());
      }
    }
  }

  // create the curves
  setData(ws.get(), wsIndex, outputWS.get());
}
Exemple #5
0
/// Check that the data sets in the table are valid and remove invalid ones.
void DataController::checkSpectra() {
  QList<int> rows;
  int nrows = getNumberOfSpectra();
  auto &ADS = Mantid::API::AnalysisDataService::Instance();
  for (int row = 0; row < nrows; ++row) {
    auto wsName = getWorkspaceName(row).toStdString();
    auto i = getWorkspaceIndex(row);
    if (!ADS.doesExist(wsName)) {
      rows.push_back(row);
      continue;
    }
    auto ws = ADS.retrieveWS<Mantid::API::MatrixWorkspace>(wsName);
    if (!ws || i >= static_cast<int>(ws->getNumberHistograms())) {
      rows.push_back(row);
      continue;
    }
  }

  removeSpectra(rows);
}
/** Execute the algorithm.
 */
void ConjoinXRuns::exec() {

  const std::vector<std::string> inputs_given =
      getProperty(INPUT_WORKSPACE_PROPERTY);
  m_logEntry = getPropertyValue(SAMPLE_LOG_X_AXIS_PROPERTY);

  const std::string sampleLogsSum = getProperty(SampleLogsBehaviour::SUM_PROP);
  const std::string sampleLogsTimeSeries =
      getProperty(SampleLogsBehaviour::TIME_SERIES_PROP);
  const std::string sampleLogsList =
      getProperty(SampleLogsBehaviour::LIST_PROP);
  const std::string sampleLogsWarn =
      getProperty(SampleLogsBehaviour::WARN_PROP);
  const std::string sampleLogsWarnTolerances =
      getProperty(SampleLogsBehaviour::WARN_TOL_PROP);
  const std::string sampleLogsFail =
      getProperty(SampleLogsBehaviour::FAIL_PROP);
  const std::string sampleLogsFailTolerances =
      getProperty(SampleLogsBehaviour::FAIL_TOL_PROP);
  const std::string sampleLogsFailBehaviour = getProperty("FailBehaviour");

  m_inputWS.clear();

  for (const auto &input : RunCombinationHelper::unWrapGroups(inputs_given)) {
    MatrixWorkspace_sptr ws =
        AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(input);
    m_inputWS.push_back(ws);
  }

  auto first = m_inputWS.front();
  SampleLogsBehaviour sampleLogsBehaviour = SampleLogsBehaviour(
      *first, g_log, sampleLogsSum, sampleLogsTimeSeries, sampleLogsList,
      sampleLogsWarn, sampleLogsWarnTolerances, sampleLogsFail,
      sampleLogsFailTolerances);

  auto it = m_inputWS.begin();

  // Temporary workspace to carry the merged sample logs
  // This is cloned from the first workspace and does not have
  // the correct size to be the output, since the size is unknown
  // at this point. We can check only later which ones are going
  // to be skipped, to compute the size of the output respectively.
  MatrixWorkspace_uptr temp = first->clone();

  size_t outBlockSize = (*it)->blocksize();
  // First sequentially merge the sample logs
  for (++it; it != m_inputWS.end(); ++it) {
    // attempt to merge the sample logs
    try {
      sampleLogsBehaviour.mergeSampleLogs(**it, *temp);
      sampleLogsBehaviour.setUpdatedSampleLogs(*temp);
      outBlockSize += (*it)->blocksize();
    } catch (std::invalid_argument &e) {
      if (sampleLogsFailBehaviour == SKIP_BEHAVIOUR) {
        g_log.error() << "Could not join workspace: " << (*it)->getName()
                      << ". Reason: \"" << e.what() << "\". Skipping.\n";
        sampleLogsBehaviour.resetSampleLogs(*temp);
        // remove the skipped one from the list
        m_inputWS.erase(it);
        --it;
      } else {
        throw std::invalid_argument(e);
      }
    }
  }

  if (m_inputWS.size() == 1) {
    g_log.warning() << "Nothing left to join [after skipping the workspaces "
                       "that failed to merge the sample logs].";
    // note, we need to continue still, since
    // the x-axis might need to be changed
  }

  if (!m_logEntry.empty()) {
    for (const auto &ws : m_inputWS) {
      m_axisCache[ws->getName()] = getXAxis(ws);
    }
  }

  // now get the size of the output
  size_t numSpec = first->getNumberHistograms();

  m_outWS = WorkspaceFactory::Instance().create(first, numSpec, outBlockSize,
                                                outBlockSize);

  // copy over the merged sample logs from the temp
  m_outWS->mutableRun() = temp->run();

  m_progress = make_unique<Progress>(this, 0.0, 1.0, numSpec);

  // Now loop in parallel over all the spectra and join the data
  PARALLEL_FOR_IF(threadSafe(*m_outWS))
  for (int64_t index = 0; index < static_cast<int64_t>(numSpec); ++index) {
    PARALLEL_START_INTERUPT_REGION
    joinSpectrum(index);
    m_progress->report();
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION

  if (!m_logEntry.empty()) {
    std::string unit = first->run().getLogData(m_logEntry)->units();
    try {
      m_outWS->getAxis(0)->unit() = UnitFactory::Instance().create(unit);
    } catch (Exception::NotFoundError &) {
      m_outWS->getAxis(0)->unit() = UnitFactory::Instance().create("Empty");
    }
  }

  setProperty("OutputWorkspace", m_outWS);
  m_inputWS.clear();
  m_axisCache.clear();
}
Exemple #7
0
void CorrectKiKf::execEvent() {
  g_log.information("Processing event workspace");

  const MatrixWorkspace_const_sptr matrixInputWS =
      getProperty("InputWorkspace");
  auto inputWS =
      boost::dynamic_pointer_cast<const EventWorkspace>(matrixInputWS);

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

  const std::string emodeStr = getProperty("EMode");
  double efixedProp = getProperty("EFixed"), efixed;

  if (efixedProp == EMPTY_DBL()) {
    if (emodeStr == "Direct") {
      // Check if it has been store on the run object for this workspace
      if (inputWS->run().hasProperty("Ei")) {
        Kernel::Property *eiprop = inputWS->run().getProperty("Ei");
        efixedProp = boost::lexical_cast<double>(eiprop->value());
        g_log.debug() << "Using stored Ei value " << efixedProp << "\n";
      } else {
        throw std::invalid_argument(
            "No Ei value has been set or stored within the run information.");
      }
    } else {
      // If not specified, will try to get Ef from the parameter file for
      // indirect geometry,
      // but it will be done for each spectrum separately, in case of different
      // analyzer crystals
    }
  }

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

  int64_t numHistograms = static_cast<int64_t>(inputWS->getNumberHistograms());
  API::Progress prog = API::Progress(this, 0.0, 1.0, numHistograms);
  PARALLEL_FOR_IF(Kernel::threadSafe(*outputWS))
  for (int64_t i = 0; i < numHistograms; ++i) {
    PARALLEL_START_INTERUPT_REGION

    double Efi = 0;
    // Now get the detector object for this histogram to check if monitor
    // or to get Ef for indirect geometry
    if (emodeStr == "Indirect") {
      if (efixedProp != EMPTY_DBL())
        Efi = efixedProp;
      else
        try {
          IDetector_const_sptr det = inputWS->getDetector(i);
          if (!det->isMonitor()) {
            try {
              Parameter_sptr par = pmap.getRecursive(det.get(), "Efixed");
              if (par) {
                Efi = par->value<double>();
                g_log.debug() << "Detector: " << det->getID()
                              << " EFixed: " << Efi << "\n";
              }
            } catch (std::runtime_error &) { /* Throws if a DetectorGroup, use
                                                single provided value */
            }
          }

        } catch (std::runtime_error &) {
          g_log.information() << "Workspace Index " << i
                              << ": cannot find detector"
                              << "\n";
        }
    }

    if (emodeStr == "Indirect")
      efixed = Efi;
    else
      efixed = efixedProp;

    // Do the correction
    auto &evlist = outputWS->getSpectrum(i);
    switch (evlist.getEventType()) {
    case TOF:
      // Switch to weights if needed.
      evlist.switchTo(WEIGHTED);
    /* no break */
    // Fall through

    case WEIGHTED:
      correctKiKfEventHelper(evlist.getWeightedEvents(), efixed, emodeStr);
      break;

    case WEIGHTED_NOTIME:
      correctKiKfEventHelper(evlist.getWeightedEventsNoTime(), efixed,
                             emodeStr);
      break;
    }

    prog.report();
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION

  outputWS->clearMRU();
  if (inputWS->getNumberEvents() != outputWS->getNumberEvents()) {
    g_log.information() << "Ef <= 0 or Ei <= 0 for "
                        << inputWS->getNumberEvents() -
                               outputWS->getNumberEvents() << " events, out of "
                        << inputWS->getNumberEvents() << '\n';
    if (efixedProp == EMPTY_DBL())
      g_log.information() << "Try to set fixed energy\n";
  }
}
Mantid::API::MatrixWorkspace_sptr
provide2DWorkspace(NXcanSASTestParameters &parameters) {
  auto ws = provide1DWorkspace(parameters);

  std::string axisBinning =
      std::to_string(parameters.xmin) + ",1," + std::to_string(parameters.xmax);
  std::string axis2Binning =
      std::to_string(parameters.ymin) + ",1," + std::to_string(parameters.ymax);

  // Convert to Histogram data
  auto toHistAlg = Mantid::API::AlgorithmManager::Instance().createUnmanaged(
      "ConvertToHistogram");
  std::string toHistoOutputName("toHistOutput");
  toHistAlg->initialize();
  toHistAlg->setChild(true);
  toHistAlg->setProperty("InputWorkspace", ws);
  toHistAlg->setProperty("OutputWorkspace", toHistoOutputName);
  toHistAlg->execute();
  ws = toHistAlg->getProperty("OutputWorkspace");

  // Convert Spectrum Axis
  auto axisAlg = Mantid::API::AlgorithmManager::Instance().createUnmanaged(
      "ConvertSpectrumAxis");
  std::string toAxisOutputName("toAxisOutput");
  axisAlg->initialize();
  axisAlg->setChild(true);
  axisAlg->setProperty("InputWorkspace", ws);
  axisAlg->setProperty("OutputWorkspace", toAxisOutputName);
  axisAlg->setProperty("Target", "ElasticQ");
  axisAlg->execute();
  ws = axisAlg->getProperty("OutputWorkspace");

  // Rebin 2D
  auto rebin2DAlg =
      Mantid::API::AlgorithmManager::Instance().createUnmanaged("Rebin2D");
  std::string rebinOutputName("rebinOutput");
  rebin2DAlg->initialize();
  rebin2DAlg->setChild(true);
  rebin2DAlg->setProperty("InputWorkspace", ws);
  rebin2DAlg->setProperty("OutputWorkspace", rebinOutputName);
  rebin2DAlg->setProperty("Axis1Binning", axisBinning);
  rebin2DAlg->setProperty("Axis2Binning", axis2Binning);
  rebin2DAlg->execute();
  ws = rebin2DAlg->getProperty("OutputWorkspace");

  if (!parameters.isHistogram) {
    // Convert to Point data
    auto toPointAlg = Mantid::API::AlgorithmManager::Instance().createUnmanaged(
        "ConvertToPointData");
    std::string toPointOutputName("toPointOutput");
    toPointAlg->initialize();
    toPointAlg->setChild(true);
    toPointAlg->setProperty("InputWorkspace", ws);
    toPointAlg->setProperty("OutputWorkspace", toPointOutputName);
    toPointAlg->execute();
    ws = toPointAlg->getProperty("OutputWorkspace");
  }

  // At this point we have a mismatch between the Axis1 elements and the
  // number of histograms.
  if (ws->getAxis(1)->length() != ws->getNumberHistograms()) {
    auto oldAxis = ws->getAxis(1);
    auto const newAxis =
        new Mantid::API::NumericAxis(ws->getNumberHistograms());
    for (size_t index = 0; index < ws->getNumberHistograms(); ++index) {
      newAxis->setValue(index, oldAxis->getValue(index));
    }
    ws->replaceAxis(1, newAxis);
  }

  ws->getAxis(1)->unit() =
      Mantid::Kernel::UnitFactory::Instance().create("MomentumTransfer");
  return ws;
}
void ModeratorTzero::execEvent(const std::string &emode) {
  g_log.information("Processing event workspace");

  const MatrixWorkspace_const_sptr matrixInputWS =
      getProperty("InputWorkspace");

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

  // calculate tof shift once for all neutrons if emode==Direct
  double t0_direct(-1);
  if (emode == "Direct") {
    Kernel::Property *eiprop = outputWS->run().getProperty("Ei");
    double Ei = boost::lexical_cast<double>(eiprop->value());
    mu::Parser parser;
    parser.DefineVar("incidentEnergy", &Ei); // associate E1 to this parser
    parser.SetExpr(m_formula);
    t0_direct = parser.Eval();
  }

  const auto &spectrumInfo = outputWS->spectrumInfo();
  const double Lss = spectrumInfo.l1();

  // Loop over the spectra
  const size_t numHists = static_cast<size_t>(outputWS->getNumberHistograms());
  Progress prog(this, 0.0, 1.0, numHists); // report progress of algorithm
  PARALLEL_FOR_IF(Kernel::threadSafe(*outputWS))
  for (int i = 0; i < static_cast<int>(numHists); ++i) {
    PARALLEL_START_INTERUPT_REGION
    size_t wsIndex = static_cast<size_t>(i);
    EventList &evlist = outputWS->getSpectrum(wsIndex);
    if (evlist.getNumberEvents() > 0) // don't bother with empty lists
    {
      double L1(Lss); // distance from source to sample
      double L2(-1);  // distance from sample to detector

      if (spectrumInfo.hasDetectors(i)) {
        if (spectrumInfo.isMonitor(i)) {
          // redefine the sample as the monitor
          L1 = Lss + spectrumInfo.l2(i); // L2 in SpectrumInfo defined negative
          L2 = 0;
        } else {
          L2 = spectrumInfo.l2(i);
        }
      } else {
        g_log.error() << "Unable to calculate distances to/from detector" << i
                      << '\n';
      }

      if (L2 >= 0) {
        // One parser for each parallel processor needed (except Edirect mode)
        double E1;
        mu::Parser parser;
        parser.DefineVar("incidentEnergy", &E1); // associate E1 to this parser
        parser.SetExpr(m_formula);

        // fast neutrons are shifted by min_t0_next, irrespective of tof
        double v1_max = L1 / m_t1min;
        E1 = m_convfactor * v1_max * v1_max;
        double min_t0_next = parser.Eval();

        if (emode == "Indirect") {
          double t2(-1.0); // time from sample to detector. (-1) signals error
          if (spectrumInfo.isMonitor(i)) {
            t2 = 0.0;
          } else {
            static const double convFact =
                1.0e-6 * sqrt(2 * PhysicalConstants::meV /
                              PhysicalConstants::NeutronMass);
            std::vector<double> wsProp =
                spectrumInfo.detector(i).getNumberParameter("Efixed");
            if (!wsProp.empty()) {
              double E2 = wsProp.at(0);        //[E2]=meV
              double v2 = convFact * sqrt(E2); //[v2]=meter/microsec
              t2 = L2 / v2;
            } else {
              // t2 is kept to -1 if no Efixed is found
              g_log.debug() << "Efixed not found for detector " << i << '\n';
            }
          }
          if (t2 >= 0) // t2 < 0 when no detector info is available
          {
            // fix the histogram bins
            auto &x = evlist.mutableX();
            for (double &tof : x) {
              if (tof < m_t1min + t2)
                tof -= min_t0_next;
              else
                tof -= CalculateT0indirect(tof, L1, t2, E1, parser);
            }

            MantidVec tofs = evlist.getTofs();
            for (double &tof : tofs) {
              if (tof < m_t1min + t2)
                tof -= min_t0_next;
              else
                tof -= CalculateT0indirect(tof, L1, t2, E1, parser);
            }
            evlist.setTofs(tofs);
            evlist.setSortOrder(Mantid::DataObjects::EventSortType::UNSORTED);
          } // end of if( t2>= 0)
        }   // end of if(emode=="Indirect")
        else if (emode == "Elastic") {
          // Apply t0 correction to histogram bins
          auto &x = evlist.mutableX();
          for (double &tof : x) {
            if (tof < m_t1min * (L1 + L2) / L1)
              tof -= min_t0_next;
            else
              tof -= CalculateT0elastic(tof, L1 + L2, E1, parser);
          }

          MantidVec tofs = evlist.getTofs();
          for (double &tof : tofs) {
            // add a [-0.1,0.1] microsecond noise to avoid artifacts
            // resulting from original tof data
            if (tof < m_t1min * (L1 + L2) / L1)
              tof -= min_t0_next;
            else
              tof -= CalculateT0elastic(tof, L1 + L2, E1, parser);
          }
          evlist.setTofs(tofs);
          evlist.setSortOrder(Mantid::DataObjects::EventSortType::UNSORTED);
        } // end of else if(emode=="Elastic")
        else if (emode == "Direct") {
          // fix the histogram bins
          evlist.mutableX() -= t0_direct;

          MantidVec tofs = evlist.getTofs();
          for (double &tof : tofs) {
            tof -= t0_direct;
          }
          evlist.setTofs(tofs);
          evlist.setSortOrder(Mantid::DataObjects::EventSortType::UNSORTED);
        } // end of else if(emode=="Direct")
      }   // end of if(L2 >= 0)
    }     // end of if (evlist.getNumberEvents() > 0)
    prog.report();
    PARALLEL_END_INTERUPT_REGION
  } // end of for (int i = 0; i < static_cast<int>(numHists); ++i)
  PARALLEL_CHECK_INTERUPT_REGION
  outputWS->clearMRU(); // Clears the Most Recent Used lists */
} // end of void ModeratorTzero::execEvent()
/** Execute the algorithm.
 */
void CreateGroupingWorkspace::exec() {
  MatrixWorkspace_sptr inWS = getProperty("InputWorkspace");
  std::string InstrumentName = getPropertyValue("InstrumentName");
  std::string InstrumentFilename = getPropertyValue("InstrumentFilename");
  std::string OldCalFilename = getPropertyValue("OldCalFilename");
  std::string GroupNames = getPropertyValue("GroupNames");
  std::string grouping = getPropertyValue("GroupDetectorsBy");
  int numGroups = getProperty("FixedGroupCount");
  std::string componentName = getPropertyValue("ComponentName");

  // Some validation
  int numParams = 0;
  if (inWS)
    numParams++;
  if (!InstrumentName.empty())
    numParams++;
  if (!InstrumentFilename.empty())
    numParams++;

  if (numParams > 1)
    throw std::invalid_argument("You must specify exactly ONE way to get an "
                                "instrument (workspace, instrument name, or "
                                "IDF file). You specified more than one.");
  if (numParams == 0)
    throw std::invalid_argument("You must specify exactly ONE way to get an "
                                "instrument (workspace, instrument name, or "
                                "IDF file). You specified none.");

  if (!OldCalFilename.empty() && !GroupNames.empty())
    throw std::invalid_argument("You must specify either to use the "
                                "OldCalFilename parameter OR GroupNames but "
                                "not both!");

  bool sortnames = false;

  // ---------- Get the instrument one of 3 ways ---------------------------
  Instrument_const_sptr inst;
  if (inWS) {
    inst = inWS->getInstrument();
  } else {
    Algorithm_sptr childAlg = createChildAlgorithm("LoadInstrument", 0.0, 0.2);
    MatrixWorkspace_sptr tempWS = boost::make_shared<Workspace2D>();
    childAlg->setProperty<MatrixWorkspace_sptr>("Workspace", tempWS);
    childAlg->setPropertyValue("Filename", InstrumentFilename);
    childAlg->setProperty("RewriteSpectraMap",
                          Mantid::Kernel::OptionalBool(true));
    childAlg->setPropertyValue("InstrumentName", InstrumentName);
    childAlg->executeAsChildAlg();
    inst = tempWS->getInstrument();
  }

  if (GroupNames.empty() && OldCalFilename.empty()) {
    if (grouping.compare("All") == 0) {
      GroupNames = inst->getName();
    } else if (inst->getName().compare("SNAP") == 0 &&
               grouping.compare("Group") == 0) {
      GroupNames = "East,West";
    } else {
      sortnames = true;
      GroupNames = "";
      int maxRecurseDepth = this->getProperty("MaxRecursionDepth");

      // cppcheck-suppress syntaxError
          PRAGMA_OMP(parallel for schedule(dynamic, 1) )
          for (int num = 0; num < 300; ++num) {
            PARALLEL_START_INTERUPT_REGION
            std::ostringstream mess;
            mess << grouping << num;
            IComponent_const_sptr comp =
                inst->getComponentByName(mess.str(), maxRecurseDepth);
            PARALLEL_CRITICAL(GroupNames)
            if (comp)
              GroupNames += mess.str() + ",";
            PARALLEL_END_INTERUPT_REGION
          }
          PARALLEL_CHECK_INTERUPT_REGION
    }
  }

  // --------------------------- Create the output --------------------------
  auto outWS = boost::make_shared<GroupingWorkspace>(inst);
  this->setProperty("OutputWorkspace", outWS);

  // This will get the grouping
  std::map<detid_t, int> detIDtoGroup;

  Progress prog(this, 0.2, 1.0, outWS->getNumberHistograms());
  // Make the grouping one of three ways:
  if (!GroupNames.empty())
    detIDtoGroup = makeGroupingByNames(GroupNames, inst, prog, sortnames);
  else if (!OldCalFilename.empty())
    detIDtoGroup = readGroupingFile(OldCalFilename, prog);
  else if ((numGroups > 0) && !componentName.empty())
    detIDtoGroup =
        makeGroupingByNumGroups(componentName, numGroups, inst, prog);

  g_log.information() << detIDtoGroup.size()
                      << " entries in the detectorID-to-group map.\n";
  setProperty("NumberGroupedSpectraResult",
              static_cast<int>(detIDtoGroup.size()));

  if (detIDtoGroup.empty()) {
    g_log.warning() << "Creating empty group workspace\n";
    setProperty("NumberGroupsResult", static_cast<int>(0));
  } else {
    size_t numNotFound = 0;

    // Make the groups, if any
    std::map<detid_t, int>::const_iterator it_end = detIDtoGroup.end();
    std::map<detid_t, int>::const_iterator it;
    std::unordered_set<int> groupCount;
    for (it = detIDtoGroup.begin(); it != it_end; ++it) {
      int detID = it->first;
      int group = it->second;
      groupCount.insert(group);
      try {
        outWS->setValue(detID, double(group));
      } catch (std::invalid_argument &) {
        numNotFound++;
      }
    }
    setProperty("NumberGroupsResult", static_cast<int>(groupCount.size()));

    if (numNotFound > 0)
      g_log.warning() << numNotFound << " detector IDs (out of "
                      << detIDtoGroup.size()
                      << ") were not found in the instrument\n.";
  }
}