JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwCombiner.cc
Go to the documentation of this file.
1/*!
2 * \file QwCombiner.cc
3 * \brief Implementation of data combiner handler for channel operations
4 * \author wdconinc
5 * \date 2010-10-22
6 */
7
8#include "QwCombiner.h"
9#include "MQwPublishable.h"
10#include "VQwSubsystem.h"
11#include <iostream>
12#include <stdexcept>
13
14// Qweak headers
15#include "QwLog.h"
16#include "VQwDataElement.h"
17#include "QwVQWK_Channel.h"
18#include "QwMollerADC_Channel.h"
19#include "QwParameterFile.h"
20#include "QwHelicityPattern.h"
21#include "QwPromptSummary.h"
22
23// Register this handler with the factory
25
26
27/// \brief Constructor with name
28QwCombiner::QwCombiner(const TString& name)
29: VQwDataHandler(name)
30{
31 ParseSeparator = ":";
32 fKeepRunningSum = kTRUE;
35}
36
38: VQwDataHandler(source)
39{
42}
43
44/// Destructor
46{
47 Iterator_HdwChan element;
48 for (element = fOutputVar.begin(); element != fOutputVar.end(); element++) {
49 if (*element != NULL){
50 delete *element;
51 }
52 }
53 fOutputVar.clear();
54}
55
56
57/* Just use the base class version for now....
58 *
59 * void ParseConfigFile(QwParameterFile& file)
60 * {
61 * VQwDataHandler::ParseConfigFile(file);
62 * file.PopValue("slope-path", outPath);
63 * }
64 */
65
66/** Load the channel map
67 *
68 * @param mapfile Filename of map file
69 * @return Zero when success
70 */
71Int_t QwCombiner::LoadChannelMap(const std::string& mapfile)
72{
73 // Open the file
74 QwParameterFile map(mapfile);
75
76 // Read the preamble
77 std::unique_ptr<QwParameterFile> preamble = map.ReadSectionPreamble();
78 TString mask;
79 if (preamble->FileHasVariablePair("=", "mask", mask)) {
81 }
82
83
84 // Read the sections of dependent variables
85 bool keep_header = true;
86 std::string section_name;
87 std::unique_ptr<QwParameterFile> section = nullptr;
88 std::pair<EQwHandleType,std::string> type_name;
89 while ((section = map.ReadNextSection(section_name,keep_header))) {
90 if(section_name=="PUBLISH") continue;
91
92 // Store index to the current position in the dv vector
93 size_t current_dv_start = fDependentName.size();
94
95 // Add dependent variables from the section header
96 section->ReadNextLine();
97 if (section->LineHasSectionHeader()) {
98 section->TrimSectionHeader();
99 section->TrimWhitespace();
100 // Parse section header into tokens separated by a comma
101 std::string current_token;
102 std::string previous_token;
103 do {
104 previous_token = current_token;
105 current_token = section->GetNextToken(",");
106 if (current_token.size() == 0) continue;
107 // Parse current token into dependent variable type and name
108 type_name = ParseHandledVariable(current_token);
109 fDependentType.push_back(type_name.first);
110 fDependentName.push_back(type_name.second);
111 fDependentFull.push_back(current_token);
112 // Resize the vectors of sensitivities and independent variables
113 fSensitivity.resize(fDependentName.size());
114 fIndependentType.resize(fDependentName.size());
115 fIndependentName.resize(fDependentName.size());
116 } while (current_token.size() != 0);
117 } else QwError << "Section does not start with header." << QwLog::endl;
118
119 // Add independent variables and sensitivities
120 while (section->ReadNextLine()) {
121 // Throw away comments, whitespace, empty lines
122 section->TrimComment();
123 section->TrimWhitespace();
124 if (section->LineIsEmpty()) continue;
125 // Get first token: independent variable
126 std::string current_token = section->GetNextToken(",");
127 // Parse current token into independent variable type and name
128 type_name = ParseHandledVariable(current_token);
129 // Loop over dependent variables to set sensitivities
130 for (size_t dv = current_dv_start; dv < fDependentName.size(); dv++) {
131 Double_t sensitivity = atof(section->GetNextToken(",").c_str());
132 fSensitivity.at(dv).push_back(sensitivity);
133 fIndependentType.at(dv).push_back(type_name.first);
134 fIndependentName.at(dv).push_back(type_name.second);
135 }
136 }
137 }
138
139 TString varvalue;
140 // Now load the variables to publish
141 std::vector<std::vector<TString> > fPublishList;
142 map.RewindToFileStart();
143 std::unique_ptr<QwParameterFile> section2;
144 std::vector<TString> publishinfo;
145 while ((section2=map.ReadNextSection(varvalue))) {
146 if (varvalue == "PUBLISH") {
147 fPublishList.clear();
148 while (section2->ReadNextLine()) {
149 section2->TrimComment(); // Remove everything after a comment character
150 section2->TrimWhitespace(); // Get rid of leading and trailing spaces
151 for (int ii = 0; ii < 4; ii++) {
152 varvalue = section2->GetTypedNextToken<TString>();
153 if (varvalue.Length()) {
154 publishinfo.push_back(varvalue);
155 }
156 }
157 if (publishinfo.size() == 4)
158 fPublishList.push_back(publishinfo);
159 publishinfo.clear();
160 }
161 }
162 }
163 // Print list of variables to publish
164 if (fPublishList.size()>0){
165 QwMessage << "Variables to publish:" << QwLog::endl;
166 for (size_t jj = 0; jj < fPublishList.size(); jj++){
167 QwMessage << fPublishList.at(jj).at(0) << " " << fPublishList.at(jj).at(1) << " " << fPublishList.at(jj).at(2) << " " << fPublishList.at(jj).at(3) << QwLog::endl;
168 }
169 }
170 return 0;
171}
172
173/** Connect to the dependent and independent channels */
177{
178 // Return if correction is not enabled
179
180 /// Fill vector of pointers to the relevant data elements
181 fIndependentVar.resize(fDependentName.size());
182 fDependentVar.resize(fDependentName.size());
183 fOutputVar.resize(fDependentName.size());
184
185 for (size_t dv = 0; dv < fDependentName.size(); dv++) {
186 // Add independent variables
187 for (size_t iv = 0; iv < fIndependentName.at(dv).size(); iv++) {
188 // Get the independent variables
189 const VQwHardwareChannel* iv_ptr = 0;
190 iv_ptr = RequestExternalPointer(fIndependentName.at(dv).at(iv));
191 if (iv_ptr == NULL){
192 switch (fIndependentType.at(dv).at(iv)) {
193 case kHandleTypeAsym:
194 iv_ptr = asym.RequestExternalPointer(fIndependentName.at(dv).at(iv));
195 break;
196 case kHandleTypeDiff:
197 iv_ptr = diff.RequestExternalPointer(fIndependentName.at(dv).at(iv));
198 break;
199 default:
200 QwWarning << "Independent variable for combiner has unknown type."
201 << QwLog::endl;
202 break;
203 }
204 }
205 if (iv_ptr) {
206 fIndependentVar[dv].push_back(iv_ptr);
207 } else {
208 QwWarning << "Independent variable " << fIndependentName.at(dv).at(iv) << " for combiner of "
209 << "dependent variable " << fDependentName.at(dv) << " could not be found."
210 << QwLog::endl;
211 }
212 }
213
214 // Get the dependent variables
215 const VQwHardwareChannel* dv_ptr = 0;
216 VQwHardwareChannel* new_chan = NULL;
217 const VQwHardwareChannel* chan = NULL;
218 string name = "";
219 string calc = "calc_";
220
221 if (fDependentType.at(dv)==kHandleTypeMps){
222 // Quietly ignore the MPS type when we're connecting the asym & diff
223 continue;
224 } else if(fDependentName.at(dv).at(0) == '@' ){
225 name = fDependentName.at(dv).substr(1,fDependentName.at(dv).length());
226 }else{
227 dv_ptr = this->RequestExternalPointer(fDependentFull.at(dv));
228 if (dv_ptr==NULL){
229 switch (fDependentType.at(dv)) {
230 case kHandleTypeAsym:
231 dv_ptr = asym.RequestExternalPointer(fDependentName.at(dv));
232 break;
233 case kHandleTypeDiff:
234 dv_ptr = diff.RequestExternalPointer(fDependentName.at(dv));
235 break;
236 default:
237 QwWarning << "QwCombiner::ConnectChannels(QwSubsystemArrayParity& asym, QwSubsystemArrayParity& diff): Dependent variable, "
238 << fDependentName.at(dv)
239 << ", for asym/diff combiner does not have proper type, type=="
240 << fDependentType.at(dv) << "."<< QwLog::endl;
241 break;
242 }
243 }
244
245 name = dv_ptr->GetElementName().Data();
246 name.insert(0, calc);
247
248 new_chan = dv_ptr->Clone(VQwDataElement::kDerived);
249 new_chan->SetElementName(name);
250 new_chan->SetSubsystemName(fName);
251 }
252
253 // alias
254 if(fDependentName.at(dv).at(0) == '@'){
255 //QwMessage << "dv: " << name << QwLog::endl;
256 if (fIndependentVar.at(dv).empty()) {
257 // Throw exception: alias cannot be created without independent variables
258 throw std::runtime_error("Cannot create alias '" + name +
259 "' for dependent variable '" + fDependentName.at(dv) +
260 "': no independent variables found to determine channel type");
261 } else {
262 // Preferred: use Clone() from first independent variable to preserve channel type
263 new_chan = fIndependentVar.at(dv).front()->Clone(VQwDataElement::kDerived);
264 }
265 new_chan->SetElementName(name);
266 new_chan->SetSubsystemName(fName);
267 }
268 // defined type
269 else if(dv_ptr!=NULL){
270 //QwMessage << "dv: " << fDependentName.at(dv) << QwLog::endl;
271 } else {
272 QwWarning << "Dependent variable " << fDependentName.at(dv) << " could not be found, "
273 << "or is not a known channel type." << QwLog::endl;
274 continue;
275 }
276
277 // pair creation
278 if(new_chan != NULL){
279 fDependentVar[dv] = chan;
280 fOutputVar[dv] = new_chan;
281 }
282 }
283
284 // Store error flag pointer
285 QwMessage << "Using asymmetry error flag" << QwLog::endl;
287
288 return 0;
289}
290
291/** Connect to the dependent and independent channels
292 *
293 * Parameters: event Helicity event structure
294 * Returns: Zero on success
295 */
297{
298 // Return if correction is not enabled
299
300 /// Fill vector of pointers to the relevant data elements
301 fIndependentVar.resize(fDependentName.size());
302 fDependentVar.resize(fDependentName.size());
303 fOutputVar.resize(fDependentName.size());
304
305 for (size_t dv = 0; dv < fDependentName.size(); dv++) {
306
307 // Add independent variables
308 for (size_t iv = 0; iv < fIndependentName.at(dv).size(); iv++) {
309 // Get the independent variables
310 const VQwHardwareChannel* iv_ptr = 0;
311 if(fIndependentType.at(dv).at(iv) == kHandleTypeMps){
312 iv_ptr = event.RequestExternalPointer(fIndependentName.at(dv).at(iv));
313 } else {
314 QwWarning << "Independent variable for MPS combiner has unknown type."
315 << QwLog::endl;
316 }
317 if (iv_ptr) {
318 fIndependentVar[dv].push_back(iv_ptr);
319 } else {
320 QwWarning << "Independent variable " << fIndependentName.at(dv).at(iv) << " for combiner of "
321 << "dependent variable " << fDependentName.at(dv) << " could not be found."
322 << QwLog::endl;
323 }
324 }
325
326 // Get the dependent variables
327 const VQwHardwareChannel* dv_ptr = 0;
328 VQwHardwareChannel* new_chan = NULL;
329 const VQwHardwareChannel* chan = NULL;
330 string name = " s";
331 string calc = "calc_";
332
334 // Quietly skip the asymmetry or difference types.
335 continue;
336 } else if(fDependentType.at(dv) != kHandleTypeMps){
337 QwWarning << "QwCombiner::ConnectChannels(QwSubsystemArrayParity& event): Dependent variable, "
338 << fDependentName.at(dv)
339 << ", for MPS combiner does not have MPS type, type=="
340 << fDependentType.at(dv) << "."<< QwLog::endl;
341 continue;
342 } else {
343 if(fDependentName.at(dv).at(0) == '@' ){
344 name = fDependentName.at(dv).substr(1,fDependentName.at(dv).length());
345 new_chan = fIndependentVar.at(dv).front()->Clone(VQwDataElement::kDerived);
346 new_chan->SetElementName(name);
347 new_chan->SetSubsystemName(fName);
348 } else {
349 dv_ptr = event.RequestExternalPointer(fDependentName.at(dv));
350
351 name = dv_ptr->GetElementName().Data();
352 name.insert(0,calc);
353
354 new_chan = dv_ptr->Clone(VQwDataElement::kDerived);
355 new_chan->SetElementName(name);
356 new_chan->SetSubsystemName(fName);
357 }
358 }
359
360 // alias
361 if(new_chan==NULL){
362 QwWarning << "Dependent variable " << fDependentName.at(dv) << " could not be found, "
363 << "or is not a known channel type." << QwLog::endl;
364 continue;
365 } else {
366 // pair creation
367 fDependentVar[dv] = chan;
368 fOutputVar[dv] = new_chan;
369 }
370 }
371
372 // Store error flag pointer
373 QwMessage << "Using event error flag" << QwLog::endl;
374 fErrorFlagPointer = event.GetEventcutErrorFlagPointer();
375
376 return 0;
377}
378
380{
381 if (fErrorFlagMask!=0 && fErrorFlagPointer!=NULL) {
382 if ((*fErrorFlagPointer & fErrorFlagMask)!=0) {
383 //QwMessage << "0x" << std::hex << *fErrorFlagPointer << " passed mask " << "0x" << fErrorFlagMask << std::dec << QwLog::endl;
384 for (size_t i = 0; i < fDependentVar.size(); ++i) {
386 }
387 //} else {
388 //QwMessage << "0x" << std::hex << *fErrorFlagPointer << " failed mask " << "0x" << fErrorFlagMask << std::dec << QwLog::endl;
389 }
390 }
391 else{
392 for (size_t i = 0; i < fDependentVar.size(); ++i) {
394 }
395 }
396}
Definition of the pure virtual base class of all subsystems.
A logfile class, based on an identical class in the Hermes analyzer.
#define QwError
Predefined log drain for errors.
Definition QwLog.h:39
#define QwWarning
Predefined log drain for warnings.
Definition QwLog.h:44
#define QwMessage
Predefined log drain for regular messages.
Definition QwLog.h:49
Parameter file parsing and management.
Decoding and management for Moller ADC channels (6x32-bit datawords)
Definition of the pure virtual base class of all data elements.
Prompt summary data management.
Decoding and management for VQWK ADC channels (6x32-bit datawords)
#define REGISTER_DATA_HANDLER_FACTORY(A)
Definition QwFactory.h:263
Data combiner handler for channel operations.
Helicity pattern analysis and management.
const VQwHardwareChannel * RequestExternalPointer(const TString &name) const
const VQwHardwareChannel * RequestExternalPointer(const TString &name) const
Retrieve a direct pointer to an external variable Searches for the named variable in external subsyst...
static std::ostream & endl(std::ostream &)
End of the line.
Definition QwLog.cc:297
Configuration file parser with flexible tokenization and search capabilities.
static UInt_t GetUInt(const TString &varvalue)
std::unique_ptr< QwParameterFile > ReadSectionPreamble()
Rewinds to the start and read until it finds next section header.
std::unique_ptr< QwParameterFile > ReadNextSection(std::string &secname, const bool keep_header=false)
void SetSubsystemName(TString sysname)
Set the name of the inheriting subsystem name.
virtual const TString & GetElementName() const
Get the name of this element.
void SetElementName(const TString &name)
Set the name of this element.
Abstract base for concrete hardware channels implementing dual-operator pattern.
virtual VQwHardwareChannel * Clone() const
Data handler that forms linear combinations of channels.
Definition QwCombiner.h:24
std::vector< std::vector< std::string > > fIndependentName
Definition QwCombiner.h:65
QwCombiner(const TString &name)
Constructor with name.
Definition QwCombiner.cc:28
std::vector< std::vector< Double_t > > fSensitivity
Definition QwCombiner.h:67
const UInt_t * fErrorFlagPointer
Definition QwCombiner.h:61
void ProcessData() override
Int_t ConnectChannels(QwSubsystemArrayParity &event) override
Connect to Channels (event only)
std::vector< std::vector< const VQwHardwareChannel * > > fIndependentVar
Definition QwCombiner.h:66
std::vector< VQwHardwareChannel * >::iterator Iterator_HdwChan
Definition QwCombiner.h:26
~QwCombiner() override
Virtual destructor.
Definition QwCombiner.cc:45
QwCombiner()
Default constructor (Protected for child class access)
Definition QwCombiner.h:57
UInt_t fErrorFlagMask
Error flag mask.
Definition QwCombiner.h:60
std::vector< std::vector< EQwHandleType > > fIndependentType
List of channels to use in the combiner.
Definition QwCombiner.h:64
Subsystem array container specialized for parity analysis with asymmetry calculations.
const UInt_t * GetEventcutErrorFlagPointer() const
void CalcOneOutput(const VQwHardwareChannel *dv, VQwHardwareChannel *output, std::vector< const VQwHardwareChannel * > &ivs, std::vector< Double_t > &sens)
std::vector< std::string > fDependentFull
std::vector< std::vector< TString > > fPublishList
std::vector< const VQwHardwareChannel * > fDependentVar
VQwDataHandler(const TString &name)
std::string ParseSeparator
std::vector< VQwHardwareChannel * > fOutputVar
std::pair< EQwHandleType, std::string > ParseHandledVariable(const std::string &variable)
std::vector< EQwHandleType > fDependentType
std::vector< std::string > fDependentName