79 #include "TRestMySQLToAnalysisProcess.h"
83 #include <mysql/mysql.h>
109 LoadConfig(configFilename);
121 SetName(this->ClassName());
122 SetTitle(
"Default config");
138 if (LoadConfigFromFile(configFilename, name)) LoadDefaultConfig();
146 fStartTimestamp = fRunInfo->GetStartTimestamp();
147 fEndTimestamp = fRunInfo->GetEndTimestamp();
149 if (fSQLVariables.size() > 0)
153 <<
"TRestMySQLToAnalysisProcess::InitProcess. No data base field entries have been specified!"
155 RESTWarning <<
"This process will do nothing!" << RESTendl;
164 SetSectionName(this->ClassName());
167 RESTWarning <<
"TRestMySQLToAnalysisProcess. REST was compiled without mySQL support" << RESTendl;
168 RESTWarning <<
"This process will not be funcional" << RESTendl;
179 RESTDebug <<
"TRestMySQLToAnalysisProcess. Ev ID : " << fEvent->GetID() << RESTendl;
180 RESTDebug <<
"TRestMySQLToAnalysisProcess. Get timestamp : " << fEvent->GetTime() << RESTendl;
181 for (
int n = 0; n < fAnaTreeVariables.size(); n++)
182 RESTDebug <<
"TRestMySQLToAnalysisProcess. Variable : " << fAnaTreeVariables[n]
183 <<
" value : " << GetDBValueAtTimestamp(n, fEvent->GetTime()) << RESTendl;
187 for (
int n = 0; n < fAnaTreeVariables.size(); n++)
188 SetObservableValue((
string)fAnaTreeVariables[n], GetDBValueAtTimestamp(n, fEvent->GetTime()));
191 RESTWarning <<
"REST was not linked to SQL libraries. Run cmake using -DREST_SQL=ON" << RESTendl;
192 RESTWarning <<
"Clearing process metadata info." << RESTendl;
193 RESTWarning <<
"Please, remove this process from the data chain or enable support for MySQL."
196 fAnaTreeVariables.clear();
197 fSQLVariables.clear();
218 fDBServerName = GetParameter(
"server",
"");
219 if (fDBServerName ==
"")
220 RESTError <<
"TRestMySQLToAnalysisProcess. Database server name not found!" << RESTendl;
222 fDBName = GetParameter(
"database",
"");
223 if (fDBName ==
"") RESTError <<
"TRestMySQLToAnalysisProcess. Database not found!" << RESTendl;
225 fDBUserName = GetParameter(
"user",
"");
226 if (fDBUserName ==
"")
227 RESTError <<
"TRestMySQLToAnalysisProcess. Database user name not found!" << RESTendl;
229 fDBUserPass = GetParameter(
"password",
"");
230 if (fDBUserPass ==
"")
231 RESTError <<
"TRestMySQLToAnalysisProcess. Database user password not found!" << RESTendl;
233 fDBTable = GetParameter(
"table",
"");
235 RESTError <<
"TRestMySQLToAnalysisProcess. Database table name not found!" << RESTendl;
238 while ((definition = GetKEYDefinition(
"dbEntry", pos)) !=
"") {
239 TString sqlName = GetFieldValue(
"sqlName", definition);
240 fSQLVariables.push_back((
string)sqlName);
242 TString anaName = GetFieldValue(
"anaName", definition);
243 fAnaTreeVariables.push_back((
string)anaName);
255 RESTMetadata <<
"SQL data extracted from:" << RESTendl;
256 RESTMetadata <<
"- database : " << fDBName << RESTendl;
257 RESTMetadata <<
"- table : " << fDBTable << RESTendl;
258 RESTMetadata <<
" " << RESTendl;
260 RESTMetadata <<
"List of variables added to the analysis tree" << RESTendl;
261 RESTMetadata <<
" ------------------------------------------ " << RESTendl;
262 for (
unsigned int n = 0; n < fAnaTreeVariables.size(); n++) {
263 RESTMetadata <<
" + SQL field : " << fSQLVariables[n] << RESTendl;
264 RESTMetadata <<
" - Tree name : " << fAnaTreeVariables[n] << RESTendl;
265 RESTMetadata <<
" - Min value : " << fMinValues[n] << RESTendl;
266 RESTMetadata <<
" - Max value : " << fMaxValues[n] << RESTendl;
267 RESTMetadata <<
" " << RESTendl;
283 MYSQL* conn = mysql_init(
nullptr);
284 if (conn ==
nullptr) {
285 RESTError <<
"TRestMySQLToAnalysisProcess::InitProcess. mysql_init() failed" << RESTendl;
289 if (!mysql_real_connect(conn, fDBServerName.c_str(), fDBUserName.c_str(), fDBUserPass.c_str(),
290 fDBName.c_str(), 0,
nullptr, 0)) {
291 RESTError <<
"TRestMySQLToAnalysisProcess::InitProcess. Connection to DB failed!" << RESTendl;
292 RESTError << mysql_error(conn) << RESTendl;
296 string sqlQuery = BuildQueryString();
297 RESTDebug << sqlQuery << RESTendl;
298 if (mysql_query(conn, sqlQuery.c_str())) {
299 RESTError <<
"Error making query to SQL database" << RESTendl;
300 RESTError << mysql_error(conn) << RESTendl;
301 RESTError <<
"Query string : " << sqlQuery << RESTendl;
305 MYSQL_RES* result = mysql_store_result(conn);
307 if (result ==
nullptr) {
308 RESTError <<
"Error getting result from SQL query" << RESTendl;
309 RESTError << mysql_error(conn) << RESTendl;
310 RESTError <<
"Query string : " << sqlQuery << RESTendl;
314 int num_fields = mysql_num_fields(result);
315 int num_rows = mysql_num_rows(result);
318 fSampling = (fEndTimestamp - fStartTimestamp) / num_rows / 2;
321 this->SetError(
"No DB entries found for the run period!");
322 fDataBaseExists =
false;
328 std::vector<std::vector<Double_t>> data;
330 while ((row = mysql_fetch_row(result))) {
331 std::vector<Double_t> dataRow;
332 for (
int i = 0; i < num_fields; i++) {
341 data.push_back(dataRow);
346 for (
int j = 0; j < data.size(); j++) {
348 for (
int n = 1; n < data.front().size(); n++) {
349 fMinValues.push_back(data.front()[n]);
350 fMaxValues.push_back(data.front()[n]);
353 for (
int n = 1; n < data[j].size(); n++) {
354 if (fMinValues[n - 1] > data[j][n]) fMinValues[n - 1] = data[j][n];
355 if (fMaxValues[n - 1] < data[j][n]) fMaxValues[n - 1] = data[j][n];
359 RESTDebug <<
"Raw data size " << data.size() << RESTendl;
364 Double_t timeNow = fStartTimestamp;
366 while (timeNow < fEndTimestamp) {
367 while (timeNow > data[dbEntry][0] && dbEntry + 1 < data.size()) dbEntry++;
369 std::vector<Double_t> dataBuff;
370 if (timeNow < data.front()[0]) {
371 for (
int n = 1; n < data.front().size(); n++) dataBuff.push_back(data.front()[n]);
372 }
else if (timeNow > data.back()[0]) {
373 for (
int n = 1; n < data.back().size(); n++) dataBuff.push_back(data.back()[n]);
375 for (
int n = 1; n < data[dbEntry].size(); n++) {
376 double y2 = data[dbEntry][n];
377 double y1 = data[dbEntry - 1][n];
380 double x2 = data[dbEntry][0];
381 double x1 = data[dbEntry - 1][0];
383 double m = (y2 - y1) / (x2 - x1);
384 double l = y1 - m * x1;
386 dataBuff.push_back(m * timeNow + l);
390 timeNow += fSampling;
391 fDBdata.push_back(dataBuff);
394 RESTDebug <<
"Added entries : " << fDBdata.size() << RESTendl;
400 RESTWarning <<
"REST was not linked to SQL libraries. Run cmake using -DREST_SQL=ON" << RESTendl;
408 string sqlQuery =
"SELECT timestamp";
409 for (
unsigned int n = 0; n < fSQLVariables.size(); n++) {
411 sqlQuery += fSQLVariables[n];
413 sqlQuery +=
" FROM " + fDBTable +
" where timestamp between ";
415 string startStr = Form(
"%10.0lf", fStartTimestamp);
416 string endStr = Form(
"%10.0lf", fEndTimestamp);
418 sqlQuery += startStr +
" and " + endStr;
429 if (!fDataBaseExists)
return -1;
430 Int_t bin = (Int_t)((timestamp - fStartTimestamp) / fSampling);
432 if (bin < 0)
return fDBdata.front()[index];
433 if ((
unsigned int)(bin + 1) >= fDBdata.size())
return fDBdata.back()[index];
435 double y2 = fDBdata[bin + 1][index];
436 double y1 = fDBdata[bin][index];
438 double m = (y2 - y1) / fSampling;
439 double l = y1 - m * (fStartTimestamp + bin * fSampling);
441 return m * timestamp + l;
A base class for any REST event.
This process connects to a SQL database and adds new observables inside the analysis tree.
void LoadDefaultConfig()
Function to load the default config in absence of RML input.
void InitFromConfigFile() override
Function reading input parameters from the RML TRestMySQLToAnalysisProcess section.
Double_t GetDBValueAtTimestamp(Int_t index, Double_t timestamp)
This method will retrieve the given data field component, specified by the argument index at the give...
std::string BuildQueryString()
Dedicated method to help building the SQL query string.
void InitProcess() override
Function to use in initialization of process members before starting to process the event.
void FillDBArrays()
This method is the one accessing the SQL database and filling the internal arrays with data that will...
void PrintMetadata() override
It prints out basic information of the SQL database used to generate the analysis tree observables....
void Initialize() override
Function to initialize input/output event members and define the section name and library version.
TRestMySQLToAnalysisProcess()
Default constructor.
~TRestMySQLToAnalysisProcess()
Default destructor.
TRestEvent * ProcessEvent(TRestEvent *inputEvent) override
The main processing event function.
void LoadConfig(const std::string &configFilename, const std::string &name="")
Function to load the configuration from an external configuration file.
@ REST_Extreme
show everything
@ REST_Debug
+show the defined debug messages
Int_t GetChar(std::string hint="Press a KEY to continue ...")
Helps to pause the program, printing a message before pausing.
Double_t StringToDouble(std::string in)
Gets a double from a string.