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
Decoding and management for VQWK ADC channels (6x32-bit datawords)
Definition of the pure virtual base class of all data elements.
Parameter file parsing and management.
Helicity pattern analysis and management.
Alarm handling data handler for monitoring system alerts.
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)