-
Notifications
You must be signed in to change notification settings - Fork 122
/
StartLiveData.cpp
184 lines (145 loc) · 7.11 KB
/
StartLiveData.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#include "MantidLiveData/StartLiveData.h"
#include "MantidKernel/System.h"
#include "MantidLiveData/LoadLiveData.h"
#include "MantidLiveData/MonitorLiveData.h"
#include "MantidAPI/AlgorithmManager.h"
#include "MantidAPI/AlgorithmProxy.h"
#include "MantidAPI/AlgorithmProperty.h"
#include <Poco/ActiveResult.h>
using namespace Mantid::Kernel;
using namespace Mantid::API;
namespace Mantid
{
namespace LiveData
{
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(StartLiveData)
//----------------------------------------------------------------------------------------------
/** Constructor
*/
StartLiveData::StartLiveData()
{
}
//----------------------------------------------------------------------------------------------
/** Destructor
*/
StartLiveData::~StartLiveData()
{
}
//----------------------------------------------------------------------------------------------
/// Algorithm's name for identification. @see Algorithm::name
const std::string StartLiveData::name() const { return "StartLiveData";};
/// Algorithm's version for identification. @see Algorithm::version
int StartLiveData::version() const { return 1;};
//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
*/
void StartLiveData::init()
{
declareProperty(new PropertyWithValue<bool>("FromNow", true, Direction::Input),
"Process live data starting from the current time only.");
declareProperty(new PropertyWithValue<bool>("FromStartOfRun", false, Direction::Input),
"Record live data, but go back to the the start of the run and process all data since then.");
declareProperty(new PropertyWithValue<bool>("FromTime", false, Direction::Input),
"Record live data, but go back to a specific time and process all data since then.\n"
"You must specify the StartTime property if this is checked.");
declareProperty(new PropertyWithValue<double>("UpdateEvery", 60.0, Direction::Input),
"Frequency of updates, in seconds. Default 60.\n"
"If you specify 0, MonitorLiveData will not launch and you will get only one chunk.");
// Initialize the properties common to LiveDataAlgorithm.
initProps();
declareProperty(new AlgorithmProperty("MonitorLiveData", boost::make_shared<NullValidator>(), Direction::Output ),
"A handle to the MonitorLiveData algorithm instance that continues to read live data after this algorithm completes.");
}
//----------------------------------------------------------------------------------------------
/** 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", "1990-01-01T00:00:00");
// Use the epoch value for the start time, as documented in ILiveListener::start.
else if (FromStartOfRun)
// At this point, we don't know when the start of the run was. Set the requested time
// to 1 second past the epoch, which is sure to be before that. We're then relying
// on the concrete live listener to never give data from before the current run.
// So far, any that give historical data behave like this but there's no way to enforce it.
this->setPropertyValue("StartTime", "1990-01-01T00:00:01");
else
{
// Validate the StartTime property. Don't allow times from the future
DateAndTime reqStartTime( this->getPropertyValue( "StartTime"));
// DateAndTime will throw an exception if it can't interpret the string, so
// we don't need to test for that condition.
// check for a requested time in the future
if (reqStartTime > DateAndTime::getCurrentTime())
{
g_log.error("Requested start time in the future. Resetting to current time.");
this->setPropertyValue("StartTime", "1990-01-01T00:00:00");
}
}
// Get the listener (and start listening) as early as possible
ILiveListener_sptr listener = this->getLiveListener();
// Issue a warning if historical data has been requested but the listener does not support it.
// This is only for event data; histogram data is by its nature historical and specifying a time is meaningless.
if ( ! FromNow && ! listener->supportsHistory() && listener->buffersEvents() )
{
g_log.error("Requested start time is in the past, but this instrument does not support historical data. "
"The effective start time is therefore 'now'.");
}
// Set the spectra list to load
std::vector<specid_t> spectra = getProperty("SpectraList");
if ( !spectra.empty() )
{
listener->setSpectra( spectra );
}
auto loadAlg = boost::dynamic_pointer_cast<LoadLiveData>(createChildAlgorithm("LoadLiveData"));
if ( ! loadAlg ) throw std::logic_error("Error creating LoadLiveData - contact the Mantid developer team");
// 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);
// Check for possible cancellation
interruption_point();
// Launch asyncronously
monitorAlg->executeAsync();
// Set the output property that passes back a handle to the ongoing live algorithm
setProperty("MonitorLiveData",algBase);
}
}
} // namespace LiveData
} // namespace Mantid