JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwEnergyCalculator.cc
Go to the documentation of this file.
1/*!
2 * \file QwEnergyCalculator.cc
3 * \brief Implementation of energy calculator for beam energy determination
4 * \author B.Waidyawansa
5 * \date 2010-05-24
6 */
7
9
10// System headers
11#include <stdexcept>
12
13// ROOT headers for RNTuple support
14#ifdef HAS_RNTUPLE_SUPPORT
15#include <ROOT/RNTupleModel.hxx>
16#include <ROOT/RNTupleWriter.hxx>
17#endif // HAS_RNTUPLE_SUPPORT
18
19// Qweak headers
20#ifdef __USE_DATABASE__
21#include "QwDBInterface.h"
22#endif // __USE_DATABASE__
23
24
25// static QwVQWK_Channel targetbeamangle;
26// static QwVQWK_Channel targetbeamx;
27// static QwVQWK_Channel beamx;
28
29/**
30 * \brief Initialize this energy calculator with a name and data-saving mode.
31 * \param name Element name used for histogram and branch prefixes.
32 * \param datatosave Storage mode (e.g., "raw" or "derived").
33 */
34void QwEnergyCalculator::InitializeChannel(TString name,TString datatosave )
35{
36 SetElementName(name);
37 fEnergyChange.InitializeChannel(name,datatosave);
38 // beamx.InitializeChannel("beamx","derived");
39 return;
40}
41
42/**
43 * \brief Initialize this energy calculator with subsystem and name.
44 * \param subsystem Subsystem identifier for tree/hist foldering.
45 * \param name Element name used for histogram and branch prefixes.
46 * \param datatosave Storage mode (e.g., "raw" or "derived").
47 */
48void QwEnergyCalculator::InitializeChannel(TString subsystem, TString name,TString datatosave )
49{
50 SetElementName(name);
51 fEnergyChange.InitializeChannel(subsystem, "QwEnergyCalculator", name,datatosave);
52 // beamx.InitializeChannel("beamx","derived");
53 return;
54}
55
56/**
57 * \brief Register a BPM-based device contributing to the energy calculation.
58 * \param device Pointer to contributing BPM object.
59 * \param type Device type string (e.g., BPM, ComboBPM).
60 * \param property Property descriptor (e.g., targetbeamangle).
61 * \param tmatrix_ratio Transport matrix ratio coefficient for contribution.
62 */
63void QwEnergyCalculator::Set(const VQwBPM* device, TString type, TString property,Double_t tmatrix_ratio)
64{
65 Bool_t ldebug = kFALSE;
66
67 fDevice.push_back(device);
68 fProperty.push_back(property);
69 fType.push_back(type);
70 fTMatrixRatio.push_back(tmatrix_ratio);
71
72 if(ldebug)
73 std::cout<<"QwEnergyCalculator:: Using "<<device->GetElementName()<<" with ratio "<< tmatrix_ratio <<" for "<<property<<std::endl;
74
75 return;
76}
77
78/**
79 * \brief Determine whether to save full ROOT output based on the prefix.
80 * \param prefix Branch/histogram prefix (may toggle full save for asym/diff).
81 */
83{
84 if(prefix.Contains("diff_")||prefix.Contains("yield_")|| prefix.Contains("asym_"))
85 bFullSave=kFALSE;
86
87 return;
88}
89
90/**
91 * \brief Clear event-scoped data of this calculator and underlying channel.
92 */
94 fEnergyChange.ClearEventData();
95 return;
96}
97
98
99
100/**
101 * \brief Compute per-event energy change by summing configured device terms.
102 */
104{
105 //Bool_t ldebug = kFALSE;
106 //Double_t targetbeamangle = 0.0;
107 static QwMollerADC_Channel tmp;
108 tmp.InitializeChannel("tmp","derived");
109 tmp.ClearEventData();
110
111 this->ClearEventData();
112
113 for(UInt_t i = 0; i<fProperty.size(); i++){
114 if(fProperty[i].Contains("targetbeamangle")){
116 } else {
117 tmp.AssignValueFrom(fDevice[i]->GetPosition(VQwBPM::kXAxis));
118 }
119 tmp.Scale(fTMatrixRatio[i]);
120 fEnergyChange += tmp;
121 }
122/*
123 if(fProperty[i].Contains("targetbeamangle")){
124 tmp.ArcTan((((QwCombinedBPM<QwVQWK_Channel>*)fDevice[i])->fSlope[VQwBPM::kXAxis]));
125 tmp.Scale(fTMatrixRatio[i]);
126 // targetbeamangle = atan((((QwCombinedBPM<QwVQWK_Channel>*)fDevice[i])->fSlope[VQwBPM::kXAxis]).GetValue());
127 // targetbeamangle *= fTMatrixRatio[i];
128 //if(ldebug) std::cout<<"QwEnegyCalculator::ProcessEvent() :: Beam angle in X at target = "<<targetbeamangle<<std::endl;
129 // fEnergyChange.AddChannelOffset(targetbeamangle);
130 fEnergyChange += tmp;
131 //if(ldebug) std::cout<<"QwEnegyCalculator::ProcessEvent() :: dp/p += (M12/M16)*X angle = "<<fEnergyChange.GetValue()<<std::endl;
132 } else {
133 tmp.AssignValueFrom(fDevice[i]->GetPosition(VQwBPM::kXAxis));
134 if(ldebug) std::cout<<"QwEnegyCalculator::ProcessEvent() :: X position from "<<fDevice[i]->GetElementName()<<" = "<<tmp.GetValue()<<std::endl;
135 tmp.Scale(fTMatrixRatio[i]);
136 if(ldebug) std::cout<<"QwEnegyCalculator::ProcessEvent() :: (M11/M16)*X position = "<<tmp.GetValue()<<std::endl;
137 fEnergyChange += tmp;
138 }
139*/
140 //if(ldebug) std::cout<<"QwEnegyCalculator::ProcessEvent() :: dp/p = "<<fEnergyChange.GetValue()<<std::endl;
141 return;
142}
143
144//------------------------------------------------------------------------------------------------------------------------------------
145
146/**
147 * \brief Generate mock event data for testing.
148 * \param helicity Helicity state indicator.
149 * \param time Event time or timestamp proxy.
150 */
151void QwEnergyCalculator::RandomizeEventData(int helicity, double time)
152{
153 fEnergyChange.RandomizeEventData(helicity, time);
154 return;
155}
156
157
158/**
159 * \brief Configure Gaussian mock data parameters for the underlying channel.
160 * \param mean Mean value for the distribution.
161 * \param sigma Standard deviation for the distribution.
162 */
163void QwEnergyCalculator::SetRandomEventParameters(Double_t mean, Double_t sigma)
164{
165 fEnergyChange.SetRandomEventParameters(mean, sigma);
166 return;
167}
168
169
170/**
171 * \brief Back-project a BPM position from the current dp/p estimate.
172 * \param device BPM device whose X position is solved from energy and other terms.
173 */
175{
176 UInt_t idevice = fProperty.size()+1; /** fProperty.size()=3, idevice=4 **/
177
178 for(UInt_t i=0; i<fProperty.size(); i++) {
179 if (fDevice[i]->GetElementName()==device->GetElementName()) { /** fDevice[i] = qwk_1c12 = device **/
180 idevice = i; /** i=0=idevice **/
181 break;
182 }
183 } /** idevice=0, fProperty.size()=3 **/
184
185 if (idevice>fProperty.size()) return; // Return without trying to find a new position if "device" doesn't contribute to the energy calculator
186
187 static QwMollerADC_Channel tmp;
188 tmp.InitializeChannel("tmp","derived");
189 tmp.ClearEventData();
190 // Set the device position value to be equal to the energy change
191 (device->GetPosition(VQwBPM::kXAxis))->AssignValueFrom(&fEnergyChange);
192 /** qwk_1c12X changes only **/
193
194 /** idevice=0 **/
195 for(UInt_t i = 0; i<fProperty.size(); i++) {
196 if (i==idevice) {
197 // Do nothing for this device!
198 continue;
199 } else {
200 // Calculate contribution to fEnergyChange from the other devices
201 if(fProperty[i].Contains("targetbeamangle")) {
203 } else {
204 tmp.AssignValueFrom(fDevice[i]->GetPosition(VQwBPM::kXAxis));
205 }
206 tmp.Scale(fTMatrixRatio[i]);
207 // And subtract it from the device we are trying to get the position of.
208 (device->GetPosition(VQwBPM::kXAxis))->operator-=(tmp);
209 }
210 } // end of for(UInt_t i = 0; i<fProperty.size(); i++)
211
212 // At this point, device position is (Energy - ( M_x*x + M_xp*arctan(xp) ) )
213 // Now divide by matrixratio for 1c12 to get: (Energy - ( M_x*x + M_xp*arctan(xp) ) )/M_1c12 === x_1c12
214
215 (device->GetPosition(VQwBPM::kXAxis))->Scale(1.0/fTMatrixRatio[idevice]);
217 device->FillRawEventData();
218
219/*
220/// Reclaculate energy and see what we get
221 static QwVQWK_Channel tmp_e;
222 tmp_e.InitializeChannel("tmp_e","derived");
223 tmp_e.ClearEventData();
224
225 for(UInt_t i = 0; i<fProperty.size(); i++){
226 if(fProperty[i].Contains("targetbeamangle")){
227 tmp.ArcTan((((QwCombinedBPM<QwVQWK_Channel>*)fDevice[i])->fSlope[VQwBPM::kXAxis]));
228 } else {
229 tmp.AssignValueFrom(fDevice[i]->GetPosition(VQwBPM::kXAxis));
230 }
231 tmp.Scale(fTMatrixRatio[i]);
232 tmp_e += tmp;
233 }
234 // std::cout << "GetProjectedPosition()::fEnergyChange = " << fEnergyChange.GetValue(0) << "\t ProcessEvent()::fEnergyChange = " << tmp_e.GetValue(0) << std::endl;
235*/
236
237 return;
238}
239
240
241/**
242 * \brief Load mock-data configuration for the underlying channel from a file.
243 * \param paramfile Parameter file reader positioned at channel section.
244 */
246
247 //std::cout << "In QwEnergyCalculator: ChannelName = " << GetElementName() << std::endl;
248 fEnergyChange.SetMockDataAsDiff(); // Sets this channel to use the difference mode in the RandomizeMockData
249 fEnergyChange.LoadMockDataParameters(paramfile);
250
251/* Bool_t ldebug=kFALSE;
252 Double_t mean=0.0, sigma=0.0;
253
254 mean = paramfile.GetTypedNextToken<Double_t>();
255 sigma = paramfile.GetTypedNextToken<Double_t>();
256
257 if (ldebug==1) {
258 std::cout << "#################### \n";
259 std::cout << "! mean, sigma \n" << std::endl;
260 std::cout << mean << " / "
261 << sigma << " / "
262 << std::endl;
263 }
264 this->SetRandomEventParameters(mean, sigma);
265*/
266}
267//------------------------------------------------------------------------------------------------------------------------------------
268
269/**
270 * \brief Apply single-event cuts to the energy channel and contributing devices.
271 * \return kTRUE if the event passes cuts; otherwise kFALSE.
272 */
274 Bool_t status=kTRUE;
275
276 UInt_t error_code = 0;
277 for(UInt_t i = 0; i<fProperty.size(); i++){
278 if(fProperty[i].Contains("targetbeamangle")){
279 error_code |= ((QwCombinedBPM<QwMollerADC_Channel>*)fDevice[i])->fSlope[0].GetErrorCode();
280 } else {
281 error_code |= fDevice[i]->GetPosition(VQwBPM::kXAxis)->GetErrorCode();
282 }
283 }
284 //fEnergyChange.UpdateErrorFlag(error_code);//No need to do this. error codes are ORed when energy is calculated
285
286 if (fEnergyChange.ApplySingleEventCuts()){
287 status=kTRUE;
288 }
289 else{
290 status&=kFALSE;
291 }
292 return status;
293}
294
295/**
296 * \brief Increment error counters in the underlying energy channel.
297 */
299{
300 fEnergyChange.IncrementErrorCounters();
301}
302
303
304/**
305 * \brief Print accumulated error counters for diagnostic purposes.
306 */
308 // report number of events failed due to HW and event cut failure
309 fEnergyChange.PrintErrorCounters();
310}
311/*
312void QwEnergyCalculator::PrintRandomEventParameters(){
313
314}
315*/
316/**
317 * \brief Update and return the composite event-cut error flag.
318 * \return The updated event-cut error flag for this calculator.
319 */
321{
322 UInt_t error_code = 0;
323 for(UInt_t i = 0; i<fProperty.size(); i++){
324 if(fProperty[i].Contains("targetbeamangle")){
325 error_code |= ((QwCombinedBPM<QwMollerADC_Channel>*)fDevice[i])->fSlope[0].GetErrorCode();
326 } else {
327 error_code |= fDevice[i]->GetPosition(VQwBPM::kXAxis)->GetErrorCode();
328 }
329 }
330 fEnergyChange.UpdateErrorFlag(error_code);
331 return fEnergyChange.GetEventcutErrorFlag();
332}
333
334
335/**
336 * \brief Propagate error flags from a reference calculator into this one.
337 * \param ev_error Reference energy calculator containing error flags to merge.
338 */
340 fEnergyChange.UpdateErrorFlag(ev_error->fEnergyChange);
341};
342
343
344/**
345 * \brief Update running averages for the underlying energy channel.
346 */
348 fEnergyChange.CalculateRunningAverage();
349}
350
351
352
353/**
354 * \brief Accumulate running sums from another calculator into this one.
355 * \param value Source calculator to accumulate from.
356 * \param count Weight/count for accumulation; 0 implies use source count.
357 * \param ErrorMask Mask to control error propagation behavior.
358 */
359void QwEnergyCalculator::AccumulateRunningSum(const QwEnergyCalculator& value, Int_t count, Int_t ErrorMask){
360 fEnergyChange.AccumulateRunningSum(value.fEnergyChange, count, ErrorMask);
361}
362
363/**
364 * \brief Remove a single entry from the running sums using a source value.
365 * \param value Source calculator to subtract.
366 * \param ErrorMask Mask to control error propagation behavior.
367 */
369 fEnergyChange.DeaccumulateRunningSum(value.fEnergyChange, ErrorMask);
370}
371
372
373
374/**
375 * \brief Process a configuration/event buffer (no-op for this calculator).
376 * \return The updated buffer word position (unchanged here).
377 */
378Int_t QwEnergyCalculator::ProcessEvBuffer(UInt_t* buffer, UInt_t word_position_in_buffer,UInt_t subelement){
379 return 0;
380}
381
382
383/** \brief Copy-assign from another calculator (event-scoped data). */
385 if (this != &value) {
386 if (GetElementName()!="")
387 this->fEnergyChange=value.fEnergyChange;
388 }
389 return *this;
390}
391
392/** \brief Add-assign from another calculator (sum energy change). */
394
395 if (GetElementName()!="")
396 this->fEnergyChange+=value.fEnergyChange;
397
398 return *this;
399}
400
401/** \brief Subtract-assign from another calculator (difference energy change). */
403 if (GetElementName()!="")
404 this->fEnergyChange-=value.fEnergyChange;
405
406 return *this;
407}
408
410 *this = value1;
411 *this += value2;
412}
413
415 *this = value1;
416 *this -= value2;
417}
418
419
420/**
421 * \brief Define the ratio for asymmetry formation (here acts as pass-through).
422 * \param numer Numerator calculator.
423 * \param denom Denominator calculator.
424 */
426 // this function is called when forming asymmetries. In this case what we actually want for the
427 // qwk_energy/(dp/p) is the difference only not the asymmetries
428
429 *this=numer;
430 return;
431}
432
433
434/**
435 * \brief Scale the underlying energy channel by a constant factor.
436 * \param factor Multiplicative scale factor.
437 */
438void QwEnergyCalculator::Scale(Double_t factor){
439 fEnergyChange.Scale(factor);
440 return;
441}
442
443
444/** \brief Print detailed information for this calculator. */
446 fEnergyChange.PrintInfo();
447 return;
448}
449
450
451/** \brief Print a compact value summary for this calculator. */
453 fEnergyChange.PrintValue();
454 return;
455}
456
457/**
458 * \brief Apply hardware checks (delegated to contributing channels if any).
459 * \return Always kTRUE; no direct hardware channels in this calculator.
460 */
462 // For the energy calculator there are no physical channels that we can relate to because it is being
463 // derived from combinations of physical channels. Therefore, this is not exactly a "HW Check"
464 // but just a check of the HW checks of the used channels.
465
466 Bool_t eventokay=kTRUE;
467 return eventokay;
468}
469
470
471/**
472 * \brief Set single-event cut limits on the underlying energy channel.
473 * \param minX Lower limit.
474 * \param maxX Upper limit.
475 * \return 1 on success.
476 */
477Int_t QwEnergyCalculator::SetSingleEventCuts(Double_t minX, Double_t maxX){
478 fEnergyChange.SetSingleEventCuts(minX,maxX);
479 return 1;
480}
481
482/**
483 * \brief Configure detailed single-event cuts for the underlying channel.
484 * \param errorflag Device-specific error flag mask to set.
485 * \param LL Lower limit.
486 * \param UL Upper limit.
487 * \param stability Stability threshold.
488 * \param burplevel Burp detection threshold.
489 */
490void QwEnergyCalculator::SetSingleEventCuts(UInt_t errorflag, Double_t LL=0, Double_t UL=0, Double_t stability=0, Double_t burplevel=0){
491 //set the unique tag to identify device type (bcm,bpm & etc)
492 errorflag|=kBCMErrorFlag;//currently I use the same flag for bcm
493 QwMessage<<"QwEnergyCalculator Error Code passing to QwMollerADC_Ch "<<errorflag<<QwLog::endl;
494 fEnergyChange.SetSingleEventCuts(errorflag,LL,UL,stability,burplevel);
495}
496
497/**
498 * \brief Check for burp failures by delegating to the energy channel.
499 * \param ev_error Reference energy calculator to compare against.
500 * \return kTRUE if a burp failure was detected; otherwise kFALSE.
501 */
503 Bool_t burpstatus = kFALSE;
504 try {
505 if(typeid(*ev_error)==typeid(*this)) {
506 //std::cout<<" Here in QwEnergyCalculator::CheckForBurpFail \n";
507 if (this->GetElementName()!="") {
508 const QwEnergyCalculator* value_halo = dynamic_cast<const QwEnergyCalculator* >(ev_error);
509 burpstatus |= fEnergyChange.CheckForBurpFail(&(value_halo->fEnergyChange));
510 }
511 } else {
512 TString loc="Standard exception from QwEnergyCalculator::CheckForBurpFail :"+
513 ev_error->GetElementName()+" "+this->GetElementName()+" are not of the "
514 +"same type";
515 throw std::invalid_argument(loc.Data());
516 }
517 } catch (std::exception& e) {
518 std::cerr<< e.what()<<std::endl;
519 }
520 return burpstatus;
521}
522
523/**
524 * \brief Define histograms for this calculator (delegated to energy channel).
525 * \param folder ROOT folder to contain histograms.
526 * \param prefix Histogram name prefix.
527 */
528void QwEnergyCalculator::ConstructHistograms(TDirectory *folder, TString &prefix){
529 if (GetElementName()==""){
530 // This channel is not used, so skip filling the histograms.
531 }
532 else{
533 TString thisprefix=prefix;
534 if(prefix.Contains("asym_"))
535 thisprefix.ReplaceAll("asym_","diff_");
536 SetRootSaveStatus(thisprefix);
537 fEnergyChange.ConstructHistograms(folder, thisprefix);
538 }
539 return;
540}
541
542/** \brief Fill histograms for this calculator if enabled. */
544 if (GetElementName()==""){
545 // This channel is not used, so skip filling the histograms.
546 }
547 else
548 fEnergyChange.FillHistograms();
549
550 return;
551}
552
553/**
554 * \brief Construct ROOT branches and value vector entries.
555 * \param tree Output tree.
556 * \param prefix Branch name prefix.
557 * \param values Output value vector to be appended.
558 */
559void QwEnergyCalculator::ConstructBranchAndVector(TTree *tree, TString &prefix,
560 QwRootTreeBranchVector &values){
561 if (GetElementName()==""){
562 // This channel is not used, so skip filling the histograms.
563 }
564 else{
565 TString thisprefix=prefix;
566 if(prefix.Contains("asym_"))
567 thisprefix.ReplaceAll("asym_","diff_");
568
569 SetRootSaveStatus(thisprefix);
570
571 fEnergyChange.ConstructBranchAndVector(tree,thisprefix,values);
572 }
573 return;
574}
575
576
577
578/**
579 * \brief Construct ROOT branches for this calculator (if enabled).
580 * \param tree Output tree.
581 * \param prefix Branch name prefix.
582 */
583void QwEnergyCalculator::ConstructBranch(TTree *tree, TString &prefix){
584 if (GetElementName()==""){
585 // This channel is not used, so skip filling the histograms.
586 }
587 else{
588 TString thisprefix=prefix;
589 if(prefix.Contains("asym_"))
590 thisprefix.ReplaceAll("asym_","diff_");
591
592 SetRootSaveStatus(thisprefix);
593 fEnergyChange.ConstructBranch(tree,thisprefix);
594 }
595 return;
596}
597
598void QwEnergyCalculator::ConstructBranch(TTree *tree, TString &prefix, QwParameterFile& modulelist){
599
600 TString devicename;
601 devicename=GetElementName();
602 devicename.ToLower();
603 if (GetElementName()==""){
604 // This channel is not used, so skip filling the histograms.
605 }
606 else
607 if (modulelist.HasValue(devicename)){
608 TString thisprefix=prefix;
609 if(prefix.Contains("asym_"))
610 thisprefix.ReplaceAll("asym_","diff_");
611 SetRootSaveStatus(thisprefix);
612 fEnergyChange.ConstructBranch(tree,thisprefix);
613 QwMessage <<" Tree leave added to "<<devicename<<QwLog::endl;
614 }
615 return;
616}
617
619{
620 if (GetElementName()==""){
621 // This channel is not used, so skip filling the histograms.
622 }
623 else
624 fEnergyChange.FillTreeVector(values);
625 return;
626}
627
628#ifdef HAS_RNTUPLE_SUPPORT
629void QwEnergyCalculator::ConstructNTupleAndVector(std::unique_ptr<ROOT::RNTupleModel>& model, TString& prefix, std::vector<Double_t>& values, std::vector<std::shared_ptr<Double_t>>& fieldPtrs)
630{
631 if (GetElementName()==""){
632 // This channel is not used, so skip construction.
633 }
634 else{
635 TString thisprefix=prefix;
636 if(prefix.Contains("asym_"))
637 thisprefix.ReplaceAll("asym_","diff_");
638
639 fEnergyChange.ConstructNTupleAndVector(model, thisprefix, values, fieldPtrs);
640 }
641 return;
642}
643
644void QwEnergyCalculator::FillNTupleVector(std::vector<Double_t>& values) const
645{
646 if (GetElementName()==""){
647 // This channel is not used, so skip filling.
648 }
649 else
650 fEnergyChange.FillNTupleVector(values);
651 return;
652}
653#endif // HAS_RNTUPLE_SUPPORT
654
655#ifdef __USE_DATABASE__
656std::vector<QwDBInterface> QwEnergyCalculator::GetDBEntry()
657{
658 std::vector <QwDBInterface> row_list;
659 row_list.clear();
660 fEnergyChange.AddEntriesToList(row_list);
661 return row_list;
662
663}
664
665std::vector<QwErrDBInterface> QwEnergyCalculator::GetErrDBEntry()
666{
667 std::vector <QwErrDBInterface> row_list;
668 row_list.clear();
669 fEnergyChange.AddErrEntriesToList(row_list);
670 return row_list;
671}
672#endif // __USE_DATABASE__
#define QwMessage
Predefined log drain for regular messages.
Definition QwLog.h:49
static const UInt_t kBCMErrorFlag
Definition QwTypes.h:168
Database interface for QwIntegrationPMT and subsystems.
Beam energy calculation from BPM position measurements.
const TString QwBPMStripline< T >::subelement[4]
static std::ostream & endl(std::ostream &)
End of the line.
Definition QwLog.cc:297
Concrete hardware channel for Moller ADC modules (6x32-bit words)
void AssignValueFrom(const VQwDataElement *valueptr) override
void InitializeChannel(TString name, TString datatosave) override
Initialize the fields in this object.
void ArcTan(const QwMollerADC_Channel &value)
void Scale(Double_t Offset) override
void ClearEventData() override
Clear the event data in this element.
Configuration file parser with flexible tokenization and search capabilities.
Bool_t HasValue(TString &vname)
A helper class to manage a vector of branch entries for ROOT trees.
Definition QwRootFile.h:53
VQwDataElement()
Default constructor.
virtual const TString & GetElementName() const
Get the name of this element.
void SetElementName(const TString &name)
Set the name of this element.
Template for combined beam position monitor using multiple BPMs.
void ClearEventData() override
Clear event-scoped data of this calculator and underlying channel.
void RandomizeEventData(int helicity=0, double time=0.0)
Generate mock event data for testing.
std::vector< const VQwBPM * > fDevice
void PrintInfo() const override
Print detailed information for this calculator.
void Difference(const QwEnergyCalculator &value1, const QwEnergyCalculator &value2)
QwEnergyCalculator & operator-=(const QwEnergyCalculator &value)
Subtract-assign from another calculator (difference energy change).
void ConstructBranch(TTree *tree, TString &prefix)
Construct ROOT branches for this calculator (if enabled).
void CalculateRunningAverage()
Update running averages for the underlying energy channel.
std::vector< TString > fType
void PrintValue() const override
Print a compact value summary for this calculator.
void FillHistograms() override
Fill histograms for this calculator if enabled.
void Scale(Double_t factor)
Scale the underlying energy channel by a constant factor.
void SetRootSaveStatus(TString &prefix)
Determine whether to save full ROOT output based on the prefix.
QwEnergyCalculator & operator+=(const QwEnergyCalculator &value)
Add-assign from another calculator (sum energy change).
void FillTreeVector(QwRootTreeBranchVector &values) const
Int_t SetSingleEventCuts(Double_t mean, Double_t sigma)
Set single-event cut limits on the underlying energy channel.
std::vector< Double_t > fTMatrixRatio
void ConstructBranchAndVector(TTree *tree, TString &prefix, QwRootTreeBranchVector &values)
Construct ROOT branches and value vector entries.
void LoadMockDataParameters(QwParameterFile &paramfile) override
Load mock-data configuration for the underlying channel from a file.
void PrintErrorCounters() const override
Print accumulated error counters for diagnostic purposes.
void Set(const VQwBPM *device, TString type, TString property, Double_t tmatrix_ratio)
Register a BPM-based device contributing to the energy calculation.
UInt_t UpdateErrorFlag() override
Update and return the composite event-cut error flag.
void GetProjectedPosition(VQwBPM *device)
Back-project a BPM position from the current dp/p estimate.
void ProcessEvent()
Compute per-event energy change by summing configured device terms.
Bool_t ApplySingleEventCuts()
Apply single-event cuts to the energy channel and contributing devices.
void AccumulateRunningSum(const QwEnergyCalculator &value, Int_t count=0, Int_t ErrorMask=0xFFFFFFF)
Accumulate running sums from another calculator into this one.
QwMollerADC_Channel fEnergyChange
Int_t ProcessEvBuffer(UInt_t *buffer, UInt_t word_position_in_buffer, UInt_t indexnumber) override
Process a configuration/event buffer (no-op for this calculator).
void SetRandomEventParameters(Double_t mean, Double_t sigma)
Configure Gaussian mock data parameters for the underlying channel.
std::vector< TString > fProperty
void DeaccumulateRunningSum(QwEnergyCalculator &value, Int_t ErrorMask=0xFFFFFFF)
Remove a single entry from the running sums using a source value.
void Ratio(QwEnergyCalculator &numer, QwEnergyCalculator &denom)
Define the ratio for asymmetry formation (here acts as pass-through).
Bool_t CheckForBurpFail(const VQwDataElement *ev_error)
Check for burp failures by delegating to the energy channel.
void InitializeChannel(TString name, TString datatosave)
Initialize this energy calculator with a name and data-saving mode.
void Sum(const QwEnergyCalculator &value1, const QwEnergyCalculator &value2)
QwEnergyCalculator & operator=(const QwEnergyCalculator &value)
Copy-assign from another calculator (event-scoped data).
Bool_t ApplyHWChecks()
Apply hardware checks (delegated to contributing channels if any).
void IncrementErrorCounters()
Increment error counters in the underlying energy channel.
void ConstructHistograms(TDirectory *folder, TString &prefix) override
Define histograms for this calculator (delegated to energy channel).
Abstract base for beam position monitors (BPMs)
Definition VQwBPM.h:52
virtual void ApplyResolutionSmearing()
Definition VQwBPM.h:273
@ kXAxis
Definition VQwBPM.h:72
virtual void FillRawEventData()
Definition VQwBPM.h:98
virtual const VQwHardwareChannel * GetPosition(EBeamPositionMonitorAxis axis) const
Definition VQwBPM.h:140