/** Process WorkspaceGroup inputs.
 *
 * Overriden from Algorithm base class.
 *
 * This should be called after checkGroups(), which sets up required members.
 * It goes through each member of the group(s), creates and sets an algorithm
 * for each and executes them one by one.
 *
 * If there are several group input workspaces, then the member of each group
 * is executed pair-wise.
 *
 * @param sourceAlg : Source algorithm
 * @param vecMultiPeriodGroups : Vector of pre-identified multiperiod groups.
 * @return true - if all the workspace members are executed.
 */
bool MultiPeriodGroupWorker::processGroups(
    Algorithm *const sourceAlg,
    const VecWSGroupType &vecMultiPeriodGroups) const {
  // If we are not processing multiperiod groups, use the base behaviour.
  if (vecMultiPeriodGroups.empty()) {
    return false; // Indicates that this is not a multiperiod group workspace.
  }
  Property *outputWorkspaceProperty = sourceAlg->getProperty("OutputWorkspace");
  const std::string outName = outputWorkspaceProperty->value();

  const size_t nPeriods = vecMultiPeriodGroups[0]->size();
  WorkspaceGroup_sptr outputWS = boost::make_shared<WorkspaceGroup>();
  AnalysisDataService::Instance().addOrReplace(outName, outputWS);

  double progress_proportion = 1.0 / static_cast<double>(nPeriods);
  // Loop through all the periods. Create spawned algorithms of the same type as
  // this to process pairs from the input groups.
  for (size_t i = 0; i < nPeriods; ++i) {
    const int periodNumber = static_cast<int>(i + 1);
    // use create Child Algorithm that look like this one
    Algorithm_sptr alg = sourceAlg->createChildAlgorithm(
        sourceAlg->name(), progress_proportion * periodNumber,
        progress_proportion * (1 + periodNumber), sourceAlg->isLogging(),
        sourceAlg->version());
    if (!alg) {
      throw std::runtime_error("Algorithm creation failed.");
    }
    // Don't make the new algorithm a child so that it's workspaces are stored
    // correctly
    alg->setChild(false);
    alg->setRethrows(true);
    alg->initialize();
    // Copy properties that aren't workspaces properties.
    sourceAlg->copyNonWorkspaceProperties(alg.get(), periodNumber);

    if (this->useCustomWorkspaceProperty()) {
      const std::string inputWorkspaces =
          createFormattedInputWorkspaceNames(i, vecMultiPeriodGroups);
      // Set the input workspace property.
      alg->setPropertyValue(this->m_workspacePropertyName, inputWorkspaces);
    } else {
      // Configure input properties that are group workspaces.
      copyInputWorkspaceProperties(alg.get(), sourceAlg, periodNumber);
    }
    const std::string outName_i = outName + "_" + Strings::toString(i + 1);
    alg->setPropertyValue("OutputWorkspace", outName_i);
    // Run the spawned algorithm.
    if (!alg->execute()) {
      throw std::runtime_error("Execution of " + sourceAlg->name() +
                               " for group entry " + Strings::toString(i + 1) +
                               " failed.");
    }
    // Add the output workpace from the spawned algorithm to the group.
    outputWS->add(outName_i);
  }

  sourceAlg->setProperty("OutputWorkspace", outputWS);

  return true;
}
Exemple #2
0
/** Execute the algorithm.
 */
void MonitorLiveData::exec() {
  double UpdateEvery = getProperty("UpdateEvery");
  if (UpdateEvery <= 0)
    throw std::runtime_error("UpdateEvery must be > 0");

  // Get the listener (and start listening) as early as possible
  ILiveListener_sptr listener = this->getLiveListener();
  // Grab ownership of the pointer in the LOCAL listener variable.
  // This will make the listener destruct if the algorithm throws,
  // but the Algorithm is still in the list of "Managed" algorithms.
  m_listener.reset();

  // The last time we called LoadLiveData.
  // Since StartLiveData _just_ called it, use the current time.
  DateAndTime lastTime = DateAndTime::getCurrentTime();

  m_chunkNumber = 0;
  int runNumber = 0;
  int prevRunNumber = 0;

  std::string AccumulationWorkspace =
      this->getPropertyValue("AccumulationWorkspace");
  std::string OutputWorkspace = this->getPropertyValue("OutputWorkspace");

  std::string NextAccumulationMethod =
      this->getPropertyValue("AccumulationMethod");

  // Keep going until you get cancelled
  while (true) {
    // Exit if the user presses cancel
    this->interruption_point();

    // Sleep for 50 msec
    Poco::Thread::sleep(50);

    DateAndTime now = DateAndTime::getCurrentTime();
    double seconds = DateAndTime::secondsFromDuration(now - lastTime);
    if (seconds > UpdateEvery) {
      lastTime = now;
      g_log.notice() << "Loading live data chunk " << m_chunkNumber << " at "
                     << now.toFormattedString("%H:%M:%S") << '\n';

      // Time to run LoadLiveData again
      Algorithm_sptr alg = createChildAlgorithm("LoadLiveData");
      LoadLiveData *loadAlg = dynamic_cast<LoadLiveData *>(alg.get());
      if (!loadAlg)
        throw std::runtime_error("Error creating LoadLiveData Child Algorithm");

      loadAlg->setChild(true);
      // So the output gets put into the ADS
      loadAlg->setAlwaysStoreInADS(true);
      // Too much logging
      loadAlg->setLogging(false);
      loadAlg->initialize();
      // Copy settings from THIS to LoadAlg
      loadAlg->copyPropertyValuesFrom(*this);
      // Give the listener directly to LoadLiveData (don't re-create it)
      loadAlg->setLiveListener(listener);
      // Override the AccumulationMethod when a run ends.
      loadAlg->setPropertyValue("AccumulationMethod", NextAccumulationMethod);

      // Run the LoadLiveData
      loadAlg->executeAsChildAlg();

      NextAccumulationMethod = this->getPropertyValue("AccumulationMethod");

      if (runNumber == 0) {
        runNumber = listener->runNumber();
        g_log.debug() << "Run number set to " << runNumber << '\n';
      }

      // Did we just hit a run transition?
      ILiveListener::RunStatus runStatus = listener->runStatus();
      if (runStatus == ILiveListener::EndRun) {
        // Need to keep track of what the run number *was* so we
        // can properly rename workspaces
        prevRunNumber = runNumber;
      }

      if ((runStatus == ILiveListener::BeginRun) ||
          (runStatus == ILiveListener::EndRun)) {
        std::stringstream message;
        message << "Run";
        if (runNumber != 0)
          message << " #" << runNumber;
        message << " ended. ";
        std::string RunTransitionBehavior =
            this->getPropertyValue("RunTransitionBehavior");
        if (RunTransitionBehavior == "Stop") {
          g_log.notice() << message.str() << "Stopping live data monitoring.\n";
          break;
        } else if (RunTransitionBehavior == "Restart") {
          g_log.notice() << message.str() << "Clearing existing workspace.\n";
          NextAccumulationMethod = "Replace";
        } else if (RunTransitionBehavior == "Rename") {
          g_log.notice() << message.str() << "Renaming existing workspace.\n";
          NextAccumulationMethod = "Replace";

          // Now we clone the existing workspaces
          std::string postFix;
          if (runStatus == ILiveListener::EndRun) {
            postFix = "_" + Strings::toString(runNumber);
          } else {
            // indicate that this is data that arrived *after* the run ended
            postFix = "_";
            if (prevRunNumber != 0)
              postFix += Strings::toString(prevRunNumber);

            postFix += "_post";
          }

          doClone(OutputWorkspace, OutputWorkspace + postFix);
        }

        runNumber = 0;
      }

      m_chunkNumber++;
      progress(0.0, "Live Data " + Strings::toString(m_chunkNumber));
    }

    // This is the time to process a single chunk. Is it too long?
    seconds = DateAndTime::secondsFromDuration(now - lastTime);
    if (seconds > UpdateEvery)
      g_log.warning() << "Cannot process live data as quickly as requested: "
                         "requested every " << UpdateEvery
                      << " seconds but it takes " << seconds << " seconds!\n";
  } // loop until aborted

  // Set the outputs (only applicable when RunTransitionBehavior is "Stop")
  Workspace_sptr OutputWS =
      AnalysisDataService::Instance().retrieveWS<Workspace>(OutputWorkspace);
  this->setProperty("OutputWorkspace", OutputWS);
  if (!AccumulationWorkspace.empty()) {
    Workspace_sptr AccumulationWS =
        AnalysisDataService::Instance().retrieveWS<Workspace>(
            AccumulationWorkspace);
    this->setProperty("AccumulationWorkspace", AccumulationWS);
  }

} // exec()