JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwAlarmHandler.cc
Go to the documentation of this file.
1/*!
2 * \file QwAlarmHandler.cc
3 * \brief Implementation of alarm handling data handler for monitoring
4 * \author wdconinc
5 * \date 2010-10-22
6 */
7
8#include "QwAlarmHandler.h"
9
10// Qweak headers
11#include "VQwDataElement.h"
12#include "QwVQWK_Channel.h"
13#include "QwParameterFile.h"
14#include "QwHelicityPattern.h"
15
16
17/// \brief Constructor with name
19{
20 ParseSeparator = "_";
21 //fKeepRunningSum = kTRUE;
22}
23
27
28// Just use the base class version for now....
29
31{
33 //name = MyAlarmHandler
34 //priority = 20
35 //map = prex_alarm_handler.map
36 file.PopValue("alarm-output-file",fAlarmOutputFile);
37 file.PopValue("alarm-loop-N-update",fAlarmNupdate);
38 file.PopValue("alarm-active",fAlarmActive);
39 // Check for and process key-value pairs
40 //file.PopValue("new-key-word",fsomething); // These need = signs in map files
41}
42
43std::pair<std::string,std::string> QwAlarmHandler::ParseAlarmMapVariable(const std::string& variable, char delim) {
44 std::pair<std::string,std::string> type_name;
45 size_t len = variable.length();
46 size_t pos1 = variable.find_first_of(delim);
47 size_t pos2 = variable.find_first_not_of(delim,pos1);
48 if (pos1 == string::npos) {
49 type_name.first = "NULL";
50 type_name.second = "NULL";
51 } else {
52 string type = variable.substr(0,pos1);
53 string name = variable.substr(pos2,len-pos2);
54 type_name.first = type;
55 type_name.second = name;
56 }
57 return type_name;
58}
59
60//******************************************************************************************************************************************************
61
62/** Load the channel map
63 *
64 * @param mapfile Filename of map file
65 * @return Zero when success
66 */
67Int_t QwAlarmHandler::LoadChannelMap(const std::string& mapfile)
68{
69 // Open the file
70 QwParameterFile map(mapfile);
71
72 // Read the sections of dependent variables
73 std::pair<EQwHandleType,std::string> type_name;
74 std::pair<std::string,std::string> tmpPair;
75
76 // Add independent variables and sensitivities
77 while (map.ReadNextLine()) {
78 // Throw away comments, whitespace, empty lines
79 map.TrimComment();
80 map.TrimWhitespace();
81 if (map.LineIsEmpty()) continue;
82 // Get first token: label (dv or iv), second token is the name like "asym_blah"
83// Type, Channel, Ana, tree, channel, highhigh, high, low, lowlow, ringLength, pat-tolerance
84// Kind=Main-Det Chan=usr Tree=mul Channel=asym_usr HighHigh=1000 High=100 Low=-100 LowLow=-1000 Ring-Length=200 Tolerance=2
85 alarmObject tmpAlarmObject;
86 // Do while tmpVal = map.GetNextToken parse
87 // Do map[tmpVal.type] = tmpVal.value
88 std::string tmpToken = map.GetNextToken(" ");
89 while ( tmpToken != "" ) {
90 tmpPair = ParseAlarmMapVariable(tmpToken,'='); // This refers to the object under scrutiny, finds type of object - asym, yield, diff, etc. Check on yields FIXME
91 if (tmpPair.first=="Channel") {
92 type_name = ParseHandledVariable(tmpPair.second);
93 tmpAlarmObject.alarmParameterMapStr["Analysis"] = tmpPair.second;
94 tmpAlarmObject.analysisType = type_name.first;
95 tmpAlarmObject.alarmParameterMapStr["Channel-Name"] = type_name.second;
96 tmpAlarmObject.alarmParameterMapStr["Type-Name"] = tmpPair.second;
97 }
98 else if (tmpPair.first == "Kind") {
99 tmpAlarmObject.alarmParameterMapStr[tmpPair.first] = tmpPair.second;
100 }
101 else if (tmpPair.first == "Chan") {
102 tmpAlarmObject.alarmParameterMapStr[tmpPair.first] = tmpPair.second;
103 }
104 else if (tmpPair.first == "Error-Code") {
105 tmpAlarmObject.alarmParameterMapStr[tmpPair.first] = tmpPair.second;
106 }
107 else {
108 tmpAlarmObject.alarmParameterMap[tmpPair.first] = std::stod(tmpPair.second);
109 }
110 tmpToken = map.GetNextToken(" ");
111 }
112 if (!tmpAlarmObject.alarmParameterMap.count("Ring-Length")) {
113 tmpAlarmObject.alarmParameterMap["Ring-Length"] = 1e9;
114 }
115 if (!tmpAlarmObject.alarmParameterMap.count("Tolerance")) {
116 tmpAlarmObject.alarmParameterMap["Tolerance"] = 0;
117 }
118
119 /* tmpAlarmObject.type = map.GetNextToken(" ");
120 tmpAlarmObject.channel = map.GetNextToken(" ");
121 tmpAlarmObject.ana = map.GetNextToken(" ");
122 tmpAlarmObject.tree = map.GetNextToken(" ");
123 std::string localAna_token = map.GetNextToken(" ");
124 // Parse current token into independent variable type and name
125 type_name = ParseHandledVariable(localAna_token); // This refers to the object under scrutiny, finds type of object - asym, yield, diff, etc. Check on yields FIXME
126 tmpAlarmObject.analysisType = type_name.first;
127 tmpAlarmObject.analysisName = type_name.second;
128 tmpAlarmObject.highHigh = map.GetNextToken(" ");
129 tmpAlarmObject.high = map.GetNextToken(" ");
130 tmpAlarmObject.low = map.GetNextToken(" ");
131 tmpAlarmObject.lowLow = map.GetNextToken(" ");
132 tmpAlarmObject.ringLength = map.GetNextToken(" ");
133 tmpAlarmObject.tolerance = map.GetNextToken(" "); // This is all hardcoded.... how to do with keywords? FIXME
134 */
135 // Default Initializations
136 tmpAlarmObject.alarmStatus = "OK";
137 tmpAlarmObject.Nviolated = 0;
138 tmpAlarmObject.NsinceLastViolation = 1e9;
139 tmpAlarmObject.value = NULL;
140 tmpAlarmObject.eventcutErrorFlag = NULL;
141 fAlarmObjectList.push_back(tmpAlarmObject);
142
143 /*else if (primary_token == "treetype") {
144 QwMessage << "Tree Type read, ignoring." << QwLog::endl;
145 }
146 else {
147 QwError << "Function LoadChannelMap in QwCorrelator.cc read in invalid primary_token." << QwLog::endl;
148 }*/
149 }
150 return 0;
151}
152
153// Connect to the dependent and independent channels (implementation). Parameters are documented in the header.
158{
159 /// Fill vector of pointers to the relevant data elements
160 for (size_t anaInd = 0; anaInd < fAlarmObjectList.size(); anaInd++) {
161 // Get the dependent variables
162 if (fAlarmObjectList.at(anaInd).analysisType==kHandleTypeMps || fAlarmObjectList.at(anaInd).alarmParameterMapStr.count("Channel-Name") == 0){
163 // Quietly ignore the MPS type when we're connecting the asym & diff
164 continue;
165 }
166 const VQwHardwareChannel* ana_ptr = NULL;
167 const UInt_t* eventcut = NULL;
168 switch (fAlarmObjectList.at(anaInd).analysisType) {
169 case kHandleTypeYield:
171 ana_ptr = yield.ReturnInternalValue(fAlarmObjectList.at(anaInd).alarmParameterMapStr.at("Channel-Name"));
172 eventcut = yield.GetEventcutErrorFlagPointer();
173 break;
174 case kHandleTypeAsym:
176 ana_ptr = asym.ReturnInternalValue(fAlarmObjectList.at(anaInd).alarmParameterMapStr.at("Channel-Name"));
177 eventcut = asym.GetEventcutErrorFlagPointer();
178 break;
179 case kHandleTypeDiff:
181 ana_ptr = diff.ReturnInternalValue(fAlarmObjectList.at(anaInd).alarmParameterMapStr.at("Channel-Name"));
182 eventcut = diff.GetEventcutErrorFlagPointer();
183 break;
184 default:
185 QwWarning << "Independent variable for AlarmHandler has unknown type."
186 << QwLog::endl;
187 break;
188 }
189 if (ana_ptr != NULL) {
190 fAlarmObjectList.at(anaInd).value = ana_ptr;
191 //QwError << "ana_ptr = " << ana_ptr <<QwLog::endl;
192 //QwError << "fAlarmObjectList.at(" << anaInd << ").value = " << fAlarmObjectList.at(anaInd).value <<QwLog::endl;
193 fAlarmObjectList.at(anaInd).eventcutErrorFlag = eventcut;
194 } else {
195 fAlarmObjectList.at(anaInd).value = NULL;
196 //QwWarning << "Independent variable " << fAlarmObjectList.at(anaInd).alarmParameterMapStr.at("Channel-Name") << " missing in alarm map "
197 // << QwLog::endl;
198 }
199 }
200 return 0;
201}
202
203// Connect to the dependent and independent channels (overload)
204/*Int_t QwAlarmHandler::ConnectChannels(QwSubsystemArrayParity& event)
205{
206 // Return if correction is not enabled
207
208 /// Fill vector of pointers to the relevant data elements
209 for (size_t dv = 0; dv < fAlarmObjectList.size(); dv++) {
210 // Get the dependent variables
211
212 const VQwHardwareChannel* dv_ptr = 0;
213 QwVQWK_Channel* new_vqwk = NULL;
214 QwVQWK_Channel* vqwk = NULL;
215 string name = " s";
216 string calc = "calc_";
217
218 if (fAnalysisType.at(dv)==kHandleTypeAsym || fAnalysisType.at(dv)==kHandleTypeDiff){
219 // Quietly skip the asymmetry or difference types.
220 continue;
221 } else if(fAnalysisType.at(dv) != kHandleTypeMps){
222 QwWarning << "QwAlarmHandler::ConnectChannels(QwSubsystemArrayParity& event): Dependent variable, "
223 << fAnalysisName.at(dv)
224 << ", for MPS alarm handler does not have MPS type, type=="
225 << fAnalysisType.at(dv) << "."<< QwLog::endl;
226 continue;
227 } else {
228 if(fAnalysisName.at(dv).at(0) == '@' ){
229 name = fAnalysisName.at(dv).substr(1,fAnalysisName.at(dv).length());
230 new_vqwk = new QwVQWK_Channel(name, VQwDataElement::kDerived);
231 } else {
232 dv_ptr = event.RequestExternalPointer(fAnalysisName.at(dv));
233
234 vqwk = dynamic_cast<QwVQWK_Channel*>(dv_ptr);
235 name = vqwk.GetElementName().Data();
236 new_vqwk = new QwVQWK_Channel(*vqwk, VQwDataElement::kDerived);
237 new_vqwk.SetElementName(name);
238 }
239 new_vqwk.SetSubsystemName(fName);
240 }
241
242 // alias
243 if(new_vqwk==NULL){
244 QwWarning << "Dependent variable " << fAnalysisName.at(dv) << " could not be found, "
245 << "or is not a VQWK channel." << QwLog::endl;
246 continue;
247 } else {
248 //QwMessage << "dv: " << new_vqwk.GetElementName() << QwLog::endl;
249 // pair creation
250 fAnalysisType.push_back(fAnalysisType.at(dv));
251 fDependentVar.push_back(vqwk);
252 fOutputVar.push_back(new_vqwk);
253 //fDependentVar.push_back(std::make_pair(vqwk, new_vqwk));
254 }
255 }
256 return 0; // FIXME this won't work, and the pointers are all wrong anyway...
257}*/
258
260 // for (size_t i = 0; i < fDependentVar.size(); ++i) {
261 // *(fOutputVar.at(i)) = *(fDependentVar[i]);
262 // }
263 // for (size_t i = 0; i < fDependentValues.size(); ++i) {
264 // fValue.at(i) = fDependentValues[i];
265 // }
266 fCounter++;
267 if (fAlarmActive) {
268 CheckAlarms();
269 if (fCounter % fAlarmNupdate == 0) {
271 }
272 }
273} // FIXME do I even need a process data method? Probably not
274
275/* Want to define new methods that will evaluate alarm status of config file variables (and combined variables -> correlations)
276 * Per multiplet calculate the asym, diffs, and yields, and compare these results to user set defined high or low values (if defined)
277 * Per multiplet check device_error_code and check eventCuts failed due to device in question and compare with tolerances defined by user
278 * Per failed low/high limit and per failed error_code and eventCut increment fail count++ and check if count > user tolerance
279 * If > tolerance then update alarm status with status (degree of failure, or Not OK status) and print to alarm.csv file the limits and value
280 * for the alarm handler GUI to pick up and parse
281 * Else if status changes to OK then print updated status to file too
282 * Else if no change then don't change the text file
283 *
284 * Probably need to interface with event cuts definitions in order to access their number-coding
285 * Probably need to define either some sort of event ring or counts decay procedure (+1 for bad, -1 for good...) to allow ignoring old failed events
286 * Probably need to define my own map nomenclature to hold stuff like what alarm.csv needs
287 * Parameter List:
288 *
289 * Japan Main Detectors,usr,asym_mean,Alarm Status,OK/saturated/high/low/nsamples/highhigh/lowlow/invalid/trip/eventcuter (I'm the cause)
290 * Japan Main Detectors,usr,asym_mean,Analysis,mean/rms/eventcuts/device_error_code
291 * Japan Main Detectors,usr,asym_mean,High,10000
292 * Japan Main Detectors,usr,asym_mean,Value,500
293 * Japan Main Detectors,usr,asym_mean,Low,50
294 * Japan Main Detectors,usr,asym_mean,Alarm Type,Japan
295 * Japan Main Detectors,usr,asym_mean,Variable Name,yield_usr
296 * Japan Main Detectors,usr,asym_mean,Tree,mul
297 * Japan Main Detectors,usr,asym_mean,Pattern Tolerance,2
298 *
299 * Type, Channel, Ana, tree, channel, highhigh, high, low, lowlow, pat tol
300 * J-m-d, usr, asym_mean, mul, usr, 1000, 100, -100, -1000, 2
301 *
302 *
303 * Make sure I update "canContain" method in /analysis/src/qwdatahandlerarray to include alarmhandler
304 */
305 /* FIXME Available VQwHardwareChannel methods
306 size_t GetNumberOfDataWords() {return fNumberOfDataWords;}
307 size_t GetNumberOfSubelements() {return fNumberOfSubElements;};
308
309 Int_t GetRawValue() const {return this.GetRawValue(0);};
310 Double_t GetValue() const {return this->GetValue(0);};
311 Double_t GetValueM2() const {return this->GetValueM2(0);};
312 Double_t GetValueError() const {return this->GetValueError(0);};
313 Double_t GetValueWidth() const {return this->GetValueWidth(0);};
314 virtual Int_t GetRawValue(size_t element) const = 0;
315 virtual Double_t GetValue(size_t element) const = 0;
316 virtual Double_t GetValueM2(size_t element) const = 0;
317 virtual Double_t GetValueError(size_t element) const = 0;
318 Double_t GetValueWidth(size_t element) const {*/
319
321 // If user-name-of-variable exists then grab it, grab its value from memory, and then compare to the upper and lower limits defined by user (if they were defined)
322 std::string tmpAlarmStat = "OK";
323 for ( size_t numAna = 0; numAna < fAlarmObjectList.size() ; numAna++ ) {
324 if (fAlarmObjectList.at(numAna).value != NULL){
325 //QwWarning << "fAlarmObjectList.at("<<numAna<<").value == " << fAlarmObjectList.at(numAna).value <<QwLog::endl;
326 //QwWarning << "fAlarmObjectList.at("<<numAna<<").value->GetValue() == " << fAlarmObjectList.at(numAna).value->GetValue() <<QwLog::endl;
327 if ( fAlarmObjectList.at(numAna).alarmParameterMapStr.count("Error-Code") != 0
328 && ((TString)fAlarmObjectList.at(numAna).alarmParameterMapStr.at("Error-Code")).IsHex() && ((std::stoul(fAlarmObjectList.at(numAna).alarmParameterMapStr.at("Error-Code"),nullptr,16)) & *fAlarmObjectList.at(numAna).eventcutErrorFlag) != 0 ) {
329 fAlarmObjectList.at(numAna).Nviolated++;
330 fAlarmObjectList.at(numAna).NsinceLastViolation = 0;
331 tmpAlarmStat = "Error-Code";
332 }
333 else if (fAlarmObjectList.at(numAna).alarmParameterMap.count("Exactly") != 0
334 && fAlarmObjectList.at(numAna).value->GetValue() != fAlarmObjectList.at(numAna).alarmParameterMap.at("Exactly")) {
335 fAlarmObjectList.at(numAna).Nviolated++;
336 fAlarmObjectList.at(numAna).NsinceLastViolation = 0;
337 tmpAlarmStat = "Not-Exactly";
338 }
339 else if ( fAlarmObjectList.at(numAna).alarmParameterMap.count("HighHigh") != 0
340 && fAlarmObjectList.at(numAna).value->GetValue() >= fAlarmObjectList.at(numAna).alarmParameterMap.at("HighHigh") ) {
341 fAlarmObjectList.at(numAna).Nviolated++;
342 fAlarmObjectList.at(numAna).NsinceLastViolation = 0;
343 tmpAlarmStat = "HighHigh";
344 }
345 else if ( fAlarmObjectList.at(numAna).alarmParameterMap.count("High") != 0
346 && fAlarmObjectList.at(numAna).value->GetValue() >= fAlarmObjectList.at(numAna).alarmParameterMap.at("High") ) {
347 fAlarmObjectList.at(numAna).Nviolated++;
348 fAlarmObjectList.at(numAna).NsinceLastViolation = 0;
349 tmpAlarmStat = "High";
350 }
351 else if ( fAlarmObjectList.at(numAna).alarmParameterMap.count("LowLow") != 0
352 && fAlarmObjectList.at(numAna).value->GetValue() <= fAlarmObjectList.at(numAna).alarmParameterMap.at("LowLow") ) {
353 fAlarmObjectList.at(numAna).Nviolated++;
354 fAlarmObjectList.at(numAna).NsinceLastViolation = 0;
355 tmpAlarmStat = "LowLow";
356 }
357 else if ( fAlarmObjectList.at(numAna).alarmParameterMap.count("Low") != 0
358 && fAlarmObjectList.at(numAna).value->GetValue() <= fAlarmObjectList.at(numAna).alarmParameterMap.at("Low") ) {
359 fAlarmObjectList.at(numAna).Nviolated++;
360 fAlarmObjectList.at(numAna).NsinceLastViolation = 0;
361 tmpAlarmStat = "Low";
362 }
363 else {
364 fAlarmObjectList.at(numAna).NsinceLastViolation++;
365 }
366 if ( fAlarmObjectList.at(numAna).Nviolated > 0 && fAlarmObjectList.at(numAna).NsinceLastViolation > fAlarmObjectList.at(numAna).alarmParameterMap.at("Ring-Length") ) {
367 fAlarmObjectList.at(numAna).Nviolated--;
368 }
369 if ( fAlarmObjectList.at(numAna).Nviolated > fAlarmObjectList.at(numAna).alarmParameterMap.at("Tolerance") ) {
370 fAlarmObjectList.at(numAna).alarmStatus = tmpAlarmStat;
371 }
372 else {
373 fAlarmObjectList.at(numAna).alarmStatus = "OK";
374 }
375 }
376 else {
377 QwError << "Null: fAlarmObjectList.at("<<numAna<<").value == NULL" <<QwLog::endl;
378 }
379 }
380}
381
383 std::ofstream file_out;
384 // Format of alarmObject struct contents
385 // std::map <std::string,std::string> alarmParameterMap;
386 // VQwDataHandler::EQwHandleType analysisType;
387 // const VQwHardwareChannel* value;
388 // UInt_t eventcutErrorFlag;
389 // std::string alarmStatus;
390 // int Nviolated; // Vector of 0's for history tracking
391 // int NsinceLastViolation; // Vector of 0's for history tracking
392
393 file_out.open(fAlarmOutputFile,std::ofstream::trunc);
394 for (size_t ite = 0 ; ite<fAlarmObjectList.size(); ite++){
395 if (fAlarmObjectList.at(ite).value != NULL && fAlarmObjectList.at(ite).alarmParameterMapStr.count("Kind") && fAlarmObjectList.at(ite).alarmParameterMapStr.count("Chan") && fAlarmObjectList.at(ite).alarmParameterMapStr.count("Analysis")) {
396 if (fAlarmObjectList.at(ite).value != 0) { // Check if non-trivial value object...
397 file_out<<fAlarmObjectList.at(ite).alarmParameterMapStr.at("Kind")<<","<<fAlarmObjectList.at(ite).alarmParameterMapStr.at("Chan")<<","<<fAlarmObjectList.at(ite).alarmParameterMapStr.at("Analysis")<<","<<"Value"<<","<<fAlarmObjectList.at(ite).value->GetValue()<<std::endl;
398 }
399 else continue;
400 if (fAlarmObjectList.at(ite).alarmStatus != "") { // Check if non-trivial value object...
401 file_out<<fAlarmObjectList.at(ite).alarmParameterMapStr.at("Kind")<<","<<fAlarmObjectList.at(ite).alarmParameterMapStr.at("Chan")<<","<<fAlarmObjectList.at(ite).alarmParameterMapStr.at("Analysis")<<","<<"Alarm Status"<<","<<fAlarmObjectList.at(ite).alarmStatus<<std::endl;
402 }
403 else continue;
404 if (fAlarmObjectList.at(ite).alarmParameterMapStr.count("Error-Code")) { // Check if non-trivial value object...
405 file_out<<fAlarmObjectList.at(ite).alarmParameterMapStr.at("Kind")<<","<<fAlarmObjectList.at(ite).alarmParameterMapStr.at("Chan")<<","<<fAlarmObjectList.at(ite).alarmParameterMapStr.at("Analysis")<<","<<"Error-Code"<<","<<fAlarmObjectList.at(ite).alarmParameterMapStr.at("Error-Code")<<std::endl;
406 }
407 }
408 else continue;
409 for (auto jte : fAlarmObjectList.at(ite).alarmParameterMap){ // Loop through parameter list
410 file_out<<fAlarmObjectList.at(ite).alarmParameterMapStr.at("Kind")<<","<<fAlarmObjectList.at(ite).alarmParameterMapStr.at("Chan")<<","<<fAlarmObjectList.at(ite).alarmParameterMapStr.at("Analysis")<<","<<jte.first<<","<<jte.second<<std::endl;
411 }
412 }
413 file_out.close();
414}
#define QwError
Predefined log drain for errors.
Definition QwLog.h:39
#define QwWarning
Predefined log drain for warnings.
Definition QwLog.h:44
Parameter file parsing and management.
Definition of the pure virtual base class of all data elements.
Decoding and management for VQWK ADC channels (6x32-bit datawords)
Alarm handling data handler for monitoring system alerts.
Helicity pattern analysis and management.
virtual const VQwHardwareChannel * ReturnInternalValue(const TString &name) const
Retrieve an internal variable by name (pointer version) Searches for the named variable among publish...
static std::ostream & endl(std::ostream &)
End of the line.
Definition QwLog.cc:297
Configuration file parser with flexible tokenization and search capabilities.
Bool_t PopValue(const std::string keyname, T &retvalue)
void TrimWhitespace(TString::EStripType head_tail=TString::kBoth)
void TrimComment(const char commentchar)
std::string GetNextToken(const std::string &separatorchars)
Get next token as a string.
Abstract base for concrete hardware channels implementing dual-operator pattern.
std::string fAlarmOutputFile
void ParseConfigFile(QwParameterFile &) override
std::vector< alarmObject > fAlarmObjectList
QwAlarmHandler()
Default constructor (Protected for child class access)
QwAlarmHandler(const TString &name)
Constructor with name.
std::pair< std::string, std::string > ParseAlarmMapVariable(const string &, char)
void ProcessData() override
Process a single event: update alarm states and outputs.
Int_t ConnectChannels(QwSubsystemArrayParity &yield, QwSubsystemArrayParity &asym, QwSubsystemArrayParity &diff) override
Connect to Channels (event only)
const VQwHardwareChannel * value
VQwDataHandler::EQwHandleType analysisType
std::map< std::string, double > alarmParameterMap
std::map< std::string, std::string > alarmParameterMapStr
Subsystem array container specialized for parity analysis with asymmetry calculations.
const UInt_t * GetEventcutErrorFlagPointer() const
void SetEventcutErrorFlagPointer(const UInt_t *errorflagptr)
virtual void ParseConfigFile(QwParameterFile &file)
VQwDataHandler(const TString &name)
std::string ParseSeparator
std::pair< EQwHandleType, std::string > ParseHandledVariable(const std::string &variable)