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