/** 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()
/** Execute the algorithm. */ void StartLiveData::exec() { // Validate the inputs bool FromNow = getProperty("FromNow"); bool FromStartOfRun = getProperty("FromStartOfRun"); bool FromTime = getProperty("FromTime"); int numChecked = 0; if (FromNow) numChecked++; if (FromStartOfRun) numChecked++; if (FromTime) numChecked++; if (numChecked != 1) throw std::runtime_error("Please check exactly one of FromNow, FromStartOfRun, FromTime."); // Adjust the StartTime if you are starting from run/now. if (FromNow) this->setPropertyValue("StartTime", DateAndTime::getCurrentTime().toISO8601String()); else if (FromStartOfRun) // TODO: implement throw Kernel::Exception::NotImplementedError("Cannot start from the run start yet."); // Get the listener (and start listening) as early as possible ILiveListener_sptr listener = this->getLiveListener(); // TODO: Wait a bit to make sure something gets accumulated? LoadLiveData loadAlg; loadAlg.initialize(); loadAlg.setChild(true); // Copy settings from THIS to LoadAlg loadAlg.copyPropertyValuesFrom(*this); // Force replacing the output workspace on the first run, to clear out old junk. loadAlg.setPropertyValue("AccumulationMethod", "Replace"); // Give the listener directly to LoadLiveData (don't re-create it) loadAlg.setLiveListener(listener); // Run the LoadLiveData for the first time. loadAlg.executeAsChildAlg(); // Copy the output workspace properties from LoadLiveData Workspace_sptr outWS = loadAlg.getProperty("OutputWorkspace"); this->setProperty("OutputWorkspace", outWS); Workspace_sptr accumWS = loadAlg.getProperty("AccumulationWorkspace"); this->setProperty("AccumulationWorkspace", accumWS); double UpdateEvery = this->getProperty("UpdateEvery"); if (UpdateEvery > 0) { // Create the MonitorLiveData but DO NOT make a AlgorithmProxy to it IAlgorithm_sptr algBase = AlgorithmManager::Instance().create("MonitorLiveData", -1, false); MonitorLiveData * monitorAlg = dynamic_cast<MonitorLiveData*>(algBase.get()); if (!monitorAlg) throw std::runtime_error("Error creating the MonitorLiveData algorithm"); // Copy settings from THIS to monitorAlg monitorAlg->initialize(); monitorAlg->copyPropertyValuesFrom(*this); monitorAlg->setProperty("UpdateEvery", UpdateEvery); // Give the listener directly to LoadLiveData (don't re-create it) monitorAlg->setLiveListener(listener); // Launch asyncronously monitorAlg->executeAsync(); } }