/** 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; }
/** 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()