REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestMySQLToAnalysisProcess.cxx
1/*************************************************************************
2 * This file is part of the REST software framework. *
3 * *
4 * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) *
5 * For more information see http://gifna.unizar.es/trex *
6 * *
7 * REST is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * REST is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have a copy of the GNU General Public License along with *
18 * REST in $REST_PATH/LICENSE. *
19 * If not, see http://www.gnu.org/licenses/. *
20 * For the list of contributors see $REST_PATH/CREDITS. *
21 *************************************************************************/
22
79#include "TRestMySQLToAnalysisProcess.h"
80using namespace std;
81
82#if defined USE_SQL
83#include <mysql/mysql.h>
84#endif
85
87
92
108 Initialize();
109 LoadConfig(configFilename);
110}
111
116
121 SetName(this->ClassName());
122 SetTitle("Default config");
123}
124
137void TRestMySQLToAnalysisProcess::LoadConfig(const string& configFilename, const string& name) {
138 if (LoadConfigFromFile(configFilename, name)) LoadDefaultConfig();
139}
140
146 fStartTimestamp = fRunInfo->GetStartTimestamp();
147 fEndTimestamp = fRunInfo->GetEndTimestamp();
148
149 if (fSQLVariables.size() > 0)
150 FillDBArrays();
151 else {
152 RESTWarning
153 << "TRestMySQLToAnalysisProcess::InitProcess. No data base field entries have been specified!"
154 << RESTendl;
155 RESTWarning << "This process will do nothing!" << RESTendl;
156 }
157}
158
164 SetSectionName(this->ClassName());
165
166#ifndef USE_SQL
167 RESTWarning << "TRestMySQLToAnalysisProcess. REST was compiled without mySQL support" << RESTendl;
168 RESTWarning << "This process will not be funcional" << RESTendl;
169#endif
170}
171
176 fEvent = inputEvent;
177
178#if defined USE_SQL
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;
184
186
187 for (int n = 0; n < fAnaTreeVariables.size(); n++)
189#else
190 if (fCheckSQL) {
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."
194 << RESTendl;
195
196 fAnaTreeVariables.clear();
197 fSQLVariables.clear();
198 fDBServerName = "";
199 fDBName = "";
200 fDBUserName = "";
201 fDBUserPass = "";
202 fDBTable = "";
203
204 fCheckSQL = false;
205 }
206#endif
207
208 return fEvent;
209}
210
216 size_t pos = 0;
217
218 fDBServerName = GetParameter("server", "");
219 if (fDBServerName == "")
220 RESTError << "TRestMySQLToAnalysisProcess. Database server name not found!" << RESTendl;
221
222 fDBName = GetParameter("database", "");
223 if (fDBName == "") RESTError << "TRestMySQLToAnalysisProcess. Database not found!" << RESTendl;
224
225 fDBUserName = GetParameter("user", "");
226 if (fDBUserName == "")
227 RESTError << "TRestMySQLToAnalysisProcess. Database user name not found!" << RESTendl;
228
229 fDBUserPass = GetParameter("password", "");
230 if (fDBUserPass == "")
231 RESTError << "TRestMySQLToAnalysisProcess. Database user password not found!" << RESTendl;
232
233 fDBTable = GetParameter("table", "");
234 if (fDBTable == "")
235 RESTError << "TRestMySQLToAnalysisProcess. Database table name not found!" << RESTendl;
236
237 string definition;
238 while ((definition = GetKEYDefinition("dbEntry", pos)) != "") {
239 TString sqlName = GetFieldValue("sqlName", definition);
240 fSQLVariables.push_back((string)sqlName);
241
242 TString anaName = GetFieldValue("anaName", definition);
243 fAnaTreeVariables.push_back((string)anaName);
244 }
245}
246
254
255 RESTMetadata << "SQL data extracted from:" << RESTendl;
256 RESTMetadata << "- database : " << fDBName << RESTendl;
257 RESTMetadata << "- table : " << fDBTable << RESTendl;
258 RESTMetadata << " " << RESTendl;
259
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;
268 }
269 EndPrintProcess();
270}
271
282#if defined USE_SQL
283 MYSQL* conn = mysql_init(nullptr);
284 if (conn == nullptr) {
285 RESTError << "TRestMySQLToAnalysisProcess::InitProcess. mysql_init() failed" << RESTendl;
286 exit(1);
287 }
288
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;
293 exit(1);
294 }
295
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;
302 exit(1);
303 }
304
305 MYSQL_RES* result = mysql_store_result(conn);
306
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;
311 exit(1);
312 }
313
314 int num_fields = mysql_num_fields(result);
315 int num_rows = mysql_num_rows(result);
316
317 // We double the average sampling of data in the given range
318 fSampling = (fEndTimestamp - fStartTimestamp) / num_rows / 2;
319
320 if (num_rows < 3) {
321 this->SetError("No DB entries found for the run period!");
322 fDataBaseExists = false;
323 return;
324 }
325
326 // We register all the data inside a std::vector.
327 MYSQL_ROW row;
328 std::vector<std::vector<Double_t>> data;
329
330 while ((row = mysql_fetch_row(result))) {
331 std::vector<Double_t> dataRow;
332 for (int i = 0; i < num_fields; i++) {
333 string value;
334 if (row[i])
335 value = row[i];
336 else
337 value = "NULL";
338
339 dataRow.push_back(StringToDouble(value));
340 }
341 data.push_back(dataRow);
342 }
343
344 fMinValues.clear();
345 fMaxValues.clear();
346 for (int j = 0; j < data.size(); j++) {
347 if (j == 0)
348 for (int n = 1; n < data.front().size(); n++) {
349 fMinValues.push_back(data.front()[n]);
350 fMaxValues.push_back(data.front()[n]);
351 }
352
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];
356 }
357 }
358
359 RESTDebug << "Raw data size " << data.size() << RESTendl;
360
361 fDBdata.clear();
362 cout.precision(10);
363 // We finally fill the array with a fixed time bin (given by fSampling)
364 Double_t timeNow = fStartTimestamp;
365 Int_t dbEntry = 0;
366 while (timeNow < fEndTimestamp) {
367 while (timeNow > data[dbEntry][0] && dbEntry + 1 < data.size()) dbEntry++;
368
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]);
374 } else {
375 for (int n = 1; n < data[dbEntry].size(); n++) {
376 double y2 = data[dbEntry][n];
377 double y1 = data[dbEntry - 1][n];
378
379 // Normalized field
380 double x2 = data[dbEntry][0];
381 double x1 = data[dbEntry - 1][0];
382
383 double m = (y2 - y1) / (x2 - x1);
384 double l = y1 - m * x1;
385
386 dataBuff.push_back(m * timeNow + l);
387 }
388 }
389
390 timeNow += fSampling;
391 fDBdata.push_back(dataBuff);
392 }
393
394 RESTDebug << "Added entries : " << fDBdata.size() << RESTendl;
397
398 mysql_close(conn);
399#else
400 RESTWarning << "REST was not linked to SQL libraries. Run cmake using -DREST_SQL=ON" << RESTendl;
401#endif
402}
403
408 string sqlQuery = "SELECT timestamp";
409 for (unsigned int n = 0; n < fSQLVariables.size(); n++) {
410 sqlQuery += ",";
411 sqlQuery += fSQLVariables[n];
412 }
413 sqlQuery += " FROM " + fDBTable + " where timestamp between ";
414
415 string startStr = Form("%10.0lf", fStartTimestamp);
416 string endStr = Form("%10.0lf", fEndTimestamp);
417
418 sqlQuery += startStr + " and " + endStr;
419
420 return sqlQuery;
421}
422
428Double_t TRestMySQLToAnalysisProcess::GetDBValueAtTimestamp(Int_t index, Double_t timestamp) {
429 if (!fDataBaseExists) return -1;
430 Int_t bin = (Int_t)((timestamp - fStartTimestamp) / fSampling);
431
432 if (bin < 0) return fDBdata.front()[index];
433 if ((unsigned int)(bin + 1) >= fDBdata.size()) return fDBdata.back()[index];
434
435 double y2 = fDBdata[bin + 1][index];
436 double y1 = fDBdata[bin][index];
437
438 double m = (y2 - y1) / fSampling;
439 double l = y1 - m * (fStartTimestamp + bin * fSampling);
440
441 return m * timestamp + l;
442}
void BeginPrintProcess()
[name, cut range]
TRestRun * fRunInfo
< Pointer to TRestRun object where to find metadata.
void SetObservableValue(const std::string &name, const T &value)
Set observable value for AnalysisTree.
A base class for any REST event.
Definition: TRestEvent.h:38
endl_t RESTendl
Termination flag object for TRestStringOutput.
Int_t LoadConfigFromFile(const std::string &configFilename, const std::string &sectionName="")
Give the file name, find out the corresponding section. Then call the main starter.
TRestStringOutput::REST_Verbose_Level GetVerboseLevel()
returns the verboselevel in type of REST_Verbose_Level enumerator
std::string GetFieldValue(std::string parName, TiXmlElement *e)
Returns the field value of an xml element which has the specified name.
void SetSectionName(std::string sName)
set the section name, clear the section content
void SetError(std::string message="", bool print=true, int maxPrint=5)
A metadata class may use this method to signal that something went wrong.
std::string GetParameter(std::string parName, TiXmlElement *e, TString defaultValue=PARAMETER_NOT_FOUND_STR)
Returns the value for the parameter named parName in the given section.
std::string GetKEYDefinition(std::string keyName)
Gets the first key definition for keyName found inside buffer starting at fromPosition.
This process connects to a SQL database and adds new observables inside the analysis tree.
std::vector< TString > fAnaTreeVariables
The name of the varibles will be renamed to these values in the analysisTree.
void LoadDefaultConfig()
Function to load the default config in absence of RML input.
Double_t fSampling
Defines the internal sampling of the retrieved data for quick access.
std::string fDBServerName
The host indentification name or IP.
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.
Double_t fStartTimestamp
Stores the start timestamp used to extract the SQL data.
TRestEvent * fEvent
A pointer to the event data.
std::string fDBTable
The database table.
std::vector< Double_t > fMinValues
The minimum value of the corresponding extracted field variable.
void InitProcess() override
Function to use in initialization of process members before starting to process the event.
std::string fDBName
The database name.
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.
Double_t fEndTimestamp
Stores the end timestamp used to extract the SQL data.
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.
Bool_t fCheckSQL
A boolean to output a warning message just once inside the process.
std::vector< Double_t > fMaxValues
The maximum value of the corresponding extracted field variable.
Bool_t fDataBaseExists
It will be true in case the database found some entries for the timestamp range.
std::string fDBUserName
The database username.
std::vector< std::vector< Double_t > > fDBdata
A matrix containing extracted SQL data with fixed time bin.
std::string fDBUserPass
The database user password.
std::vector< TString > fSQLVariables
The name of the entries defined by user that will be retrieved at the SQL database.
@ REST_Debug
+show the defined debug messages
static int PrintTable(std::vector< std::vector< T > > data, Int_t start=0, Int_t end=0)
Prints the contents of the vector table given as argument in screen. Allowed types are Int_t,...
Definition: TRestTools.cxx:163
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.