JAPAn
Just Another Parity Analyzer
Loading...
Searching...
No Matches
QwCombinedBCM.cc
Go to the documentation of this file.
1/*!
2 * \file QwCombinedBCM.cc
3 * \brief Combined beam current monitor implementation using weighted averages
4 *
5 * Combined beam current monitor implementation: weighted average of multiple
6 * BCMs with optional beam trip simulation, resolution smearing, and random
7 * event generation. Template class supporting various channel types.
8 * Documentation-only edits; runtime behavior unchanged.
9 */
10
11#include "QwCombinedBCM.h"
12
13// System headersF
14#include <stdexcept>
15
16// Qweak headers
17#ifdef __USE_DATABASE__
18#include "QwDBInterface.h"
19#endif // __USE_DATABASE__
20
21// Qweak types that we want to use in this template
22#include "QwVQWK_Channel.h"
23#include "QwADC18_Channel.h"
24#include "QwScaler_Channel.h"
25#include "QwMollerADC_Channel.h"
26
27
28// Randomness generator: Mersenne twister with period 2^19937 - 1
29//
30// This is defined as static to avoid getting stuck with 100% correlated
31// ADC channels when each channel goes through the same list of pseudo-
32// random numbers...
33
34template<typename T> std::mt19937 QwCombinedBCM<T>::fRandomnessGenerator;
35template<typename T> std::uniform_real_distribution<double> QwCombinedBCM<T>::fDistribution;
36template<typename T> std::function<double()> QwCombinedBCM<T>::fRandomVariable = []() -> double { return QwCombinedBCM<T>::fDistribution(QwCombinedBCM<T>::fRandomnessGenerator); };
37
38/** Set random number generator seed for beam trip simulation. */
39template<typename T>
41{
42 fRandomnessGenerator.seed(seedval);
43}
44
45/********************************************************/
46
47//this is a combined BCM made out of BCMs that are already calibrated and have pedstals removed.
48//This will be used for projection of charge at the target
49
50/**
51 * Add a constituent BCM to the combination with specified weight.
52 *
53 * @param bcm Pointer to the BCM to include.
54 * @param weight Charge weight for this BCM.
55 * @param sumqw Total sum of absolute weights.
56 */
57template<typename T>
58void QwCombinedBCM<T>::SetBCMForCombo(VQwBCM* bcm, Double_t weight, Double_t sumqw )
59{
60 // Convert back to QWBCM<T>* from generic VQwBCM*
61 fElement.push_back(dynamic_cast<QwBCM<T>* >(bcm));
62 fWeights.push_back(weight);
63 fSumQweights = sumqw;
64}
65
66/********************************************************/
67
68/** Initialize combined BCM with simple name and default settings. */
69template<typename T>
70void QwCombinedBCM<T>::InitializeChannel(TString name, TString datatosave)
71{
72 SetPedestal(0.);
74 fLastTripTime = -99999.9;
75 this->SetElementName(name);
76 this->fBeamCurrent.InitializeChannel(name,"derived");
77}
78
79/** Initialize combined BCM with subsystem scoping. */
80template<typename T>
81void QwCombinedBCM<T>::InitializeChannel(TString subsystem, TString name, TString datatosave)
82{
83 SetPedestal(0.);
85 fLastTripTime = -99999.9;
86 this->SetElementName(name);
87 this->fBeamCurrent.InitializeChannel(subsystem, "QwCombinedBCM", name,"derived");
88}
89
90template<typename T>
91void QwCombinedBCM<T>::InitializeChannel(TString subsystem, TString name,
92 TString type, TString datatosave)
93{
94 SetPedestal(0.);
96 fLastTripTime = -99999.9;
97 this->SetElementName(name);
98 this->SetModuleType(type);
99 this->fBeamCurrent.InitializeChannel(subsystem, "QwCombinedBCM", name,"derived");
100}
101
102
103/********************************************************/
104/**
105 * Compute weighted average of constituent BCM currents and normalize by
106 * total weight sum.
107 */
108template<typename T>
110{
111 static T tmpADC;
112 tmpADC.InitializeChannel("tmp","derived");
113
114 this->ClearEventData();
115
116 for (size_t i = 0; i < fElement.size(); i++) {
117 tmpADC = fElement[i]->fBeamCurrent;
118 tmpADC.Scale(fWeights[i]);
119 this->fBeamCurrent += tmpADC;
120 }
121 this->fBeamCurrent.Scale(1.0/fSumQweights);
122
123 Bool_t ldebug = kFALSE;
124 if (ldebug) {
125 QwMessage << "*****************" << QwLog::endl;
126 QwMessage << "QwCombinedBCM: " << this->GetElementName() << QwLog::endl
127 << "weighted average of hardware sums = " << this->fBeamCurrent.GetValue() << QwLog::endl;
128 if (this->fBeamCurrent.GetNumberOfSubelements() > 1) {
129 for (size_t i = 0; i < 4; i++) {
130 QwMessage << "weighted average of block[" << i << "] = " << this->fBeamCurrent.GetValue(i) << QwLog::endl;
131 }
132 }
133 QwMessage << "*****************" << QwLog::endl;
134 }
135}
136
137//---------------------------------------------------------------------------------------------------------
138
139
140/**
141 * Project the combined current to a device channel, applying resolution
142 * smearing and filling raw event data.
143 */
144template<typename T>
146{
147 (device->GetCharge())->AssignScaledValue(this->fBeamCurrent,1.0);
148 //device->PrintInfo();
149 device->ApplyResolutionSmearing();
150 //device->PrintInfo();
151 device->FillRawEventData();
152}
153
154
155/**
156 * Generate random event data and optionally simulate beam trips with
157 * configurable trip period, length, and ramp duration.
158 */
159template<typename T>
160void QwCombinedBCM<T>::RandomizeEventData(int helicity, double time)
161{
162 this->fBeamCurrent.RandomizeEventData(helicity, time);
163 // do the beam cut routine from MockDataGenerator, but just scale fBeamCurrent instead of re-randomizing
164 // Three time intervals: fmod(time,period) > (period-tripramp): Do the ramp scaling
165 // (period-tripramp) > fmod(time,period) > (period-triplength- tripramp): scale by 0.0
166 // (period-triplength- tripramp) > fmod(time,period) : leave the variable alone
167
168
169 // Determine the probability of having a beam trip
170 if (fLastTripTime<=-99999.9) {
172 }
173// if ( ((time-fLastTripTime) > (fTripPeriod)) ){ // Make some comparison to a probablilty instead of the time
174// Probability of a trip happening in one event: # of trips per hour/3600 * eventtime_in_seconds (which is 0.001s)
175 Double_t tmp = fRandomVariable();
176// std::cout << "random value=="<<tmp << "; fProbabilityOfTrip=="<<fProbabilityOfTrip<<std::endl;
177 if (tmp < fProbabilityOfTrip) {
178 fLastTripTime = time;
179 std::cout << "random value=="<<tmp << "; fProbabilityOfTrip=="<<fProbabilityOfTrip<<"; time=="<<time<<std::endl;
180 }
181
182 Double_t time_since_trip = time - fLastTripTime;
183 if (time_since_trip <= fTripLength) {
184 this->fBeamCurrent.Scale(0.0);
185 //std::cout << "fBeamCurrent.Scale(0.0)" << std::endl;
186 } else if (time_since_trip < (fTripLength + fTripRamp)) {
187 Double_t factor = (time_since_trip-fTripLength)/fTripRamp;
188 //std::cout << "(fTripPeriod - fmod(time, fTripPeriod))=="<<(fTripPeriod - fmod(time, fTripPeriod))<<"; fTripLength=="<<fTripLength
189 // << "; ((fTripPeriod - fmod(time, fTripPeriod)) / fTripLength)=="<<((fTripPeriod - fmod(time, fTripPeriod)) / fTripLength)
190 // << std::endl;
191 this->fBeamCurrent.Scale(factor);
192 //std::cout << "fBeamCurrent.Scale(factor) = " << factor << std::endl;
193 }
194}
195
196
197/**
198 * Load mock data parameters including beam trip settings and resolution.
199 * Recognizes 'beamtrip' and 'resolution' keywords.
200 */
201template<typename T>
203
204 Double_t res=0.0;
205
206 // Test for the word "beamtrip", and get the tripperiod and tripduration if it is found, otherwise, just pass
207 // the line to the fBeamCurrent object.
208 if (paramfile.GetLine().find("beamtrip")!=std::string::npos){
209 // "beamtrip" appears somewhere in the line. Assume it is the next token and move on...
210 paramfile.GetNextToken(); //Throw away this token. Now the next three should be the beamtrip parameters.
211
212 fTripPeriod = paramfile.GetTypedNextToken<Double_t>() * Qw::sec;
213 fTripLength = paramfile.GetTypedNextToken<Double_t>() * Qw::sec;
214 fTripRamp = paramfile.GetTypedNextToken<Double_t>() * Qw::sec;
215
217 } else if (paramfile.GetLine().find("resolution")!=std::string::npos){
218 paramfile.GetNextToken();
219 res = paramfile.GetTypedNextToken<Double_t>();
220 this->SetResolution(res);
221 } else {
222 //std::cout << "In QwCombinedBCM: ChannelName = " << this->GetElementName() << std::endl;
223 this->fBeamCurrent.LoadMockDataParameters(paramfile);
224 }
225}
226
227//---------------------------------------------------------------------------------------------------------
228
229
230/********************************************************/
231/**
232 * Apply single-event cuts: first propagate error codes from constituent
233 * BCMs, then apply cuts using the inherited BCM logic.
234 */
235template<typename T>
237{
238
239 //This is required to update single event cut failures in individual channels
240 // First update the error code based on the codes
241 // of the elements. This requires that the BCMs
242 // have had ApplySingleEventCuts run on them already.
243
244 for (size_t i=0;i<fElement.size();i++){
245 this->fBeamCurrent.UpdateErrorFlag(fElement.at(i)->fBeamCurrent.GetErrorCode());
246 }
247
248
249 // Everything is identical as for a regular BCM
251}
252
253/**
254 * Update error flags by propagating error codes from constituent BCMs.
255 */
256template<typename T>
258 for (size_t i=0;i<fElement.size();i++){
259 this->fBeamCurrent.UpdateErrorFlag(fElement.at(i)->fBeamCurrent.GetErrorCode());
260 }
261 return this->fBeamCurrent.GetEventcutErrorFlag();
262}
263
264
265/********************************************************/
266/*
267template<typename T>
268void QwCombinedBCM<T>::UpdateErrorFlag(const VQwBCM *ev_error){
269
270 try {
271 if(typeid(*ev_error)==typeid(*this)) {
272 // std::cout<<" Here in QwCombinedBCM::UpdateErrorFlag \n";
273 if (this->GetElementName()!="") {
274 QwCombinedBCM<T>* value_bcm = dynamic_cast<QwCombinedBCM<T>* >(ev_error);
275 VQwDataElement *value_data = dynamic_cast<VQwDataElement *>(&(value_bcm->fBeamCurrent));
276 fBeamCurrent.UpdateErrorFlag(value_data->GetErrorCode());//the routine GetErrorCode() return the error flag + configuration flag unconditionally
277 }
278 } else {
279 TString loc="Standard exception from QwCombinedBCM::UpdateErrorFlag :"+
280 ev_error->GetElementName()+" "+this->GetElementName()+" are not of the "
281 +"same type";
282 throw std::invalid_argument(loc.Data());
283 }
284 } catch (std::exception& e) {
285 std::cerr<< e.what()<<std::endl;
286 }
287
288 QwBCM<T>::UpdateErrorFlag(const ev_error);
289};
290*/
291
292/********************************************************/
293/*
294template<typename T>
295void QwCombinedBCM<T>::CalculateRunningAverage(){
296 fBeamCurrent.CalculateRunningAverage();
297=======
298 return eventokay;
299>>>>>>> .merge-right.r3406
300}
301*/
302/********************************************************/
303/*
304template<typename T>
305<<<<<<< .working
306void QwCombinedBCM<T>::AccumulateRunningSum(const VQwBCM &value){
307 fBeamCurrent.AccumulateRunningSum(dynamic_cast<const QwCombinedBCM<T>* >(&value)->fBeamCurrent);
308}
309*/
310/********************************************************/
311/*
312template<typename T>
313void QwCombinedBCM<T>::DeaccumulateRunningSum(VQwBCM &value){
314 fBeamCurrent.DeaccumulateRunningSum(dynamic_cast<QwCombinedBCM<T>* >(&value)->fBeamCurrent);
315}
316*/
317
318
319/********************************************************/
320/** Assignment operator: copy the beam current value. */
321template<typename T>
323{
324 if (this->GetElementName()!="")
325 this->fBeamCurrent=value.fBeamCurrent;
326
327 return *this;
328}
329
330/** Polymorphic assignment operator. */
331template<typename T>
333{
334 if (this->GetElementName()!="")
335 dynamic_cast<QwCombinedBCM<T>* >(this)->fBeamCurrent=
336 dynamic_cast<const QwCombinedBCM<T>* >(&value)->fBeamCurrent;
337
338 return *this;
339}
340
341
342/********************************************************/
343/*
344template<typename T>
345Bool_t QwCombinedBCM<T>::ApplyHWChecks()
346{
347 // For the combined devices there are no physical channels that we can relate to because they are being
348 // derived from combinations of physical channels. Therefore, this is not exactly a "HW Check"
349 // but just a check of the HW checks of the combined channels.
350
351 Bool_t eventokay=kTRUE;
352
353 return eventokay;
354}
355*/
356
357/*
358template<typename T>
359Int_t QwCombinedBCM<T>::SetSingleEventCuts(Double_t LL=0, Double_t UL=0){
360 fBeamCurrent.SetSingleEventCuts(LL,UL);
361 return 1;
362}
363
364
365template<typename T>
366void QwCombinedBCM<T>::SetSingleEventCuts(UInt_t errorflag, Double_t LL=0, Double_t UL=0, Double_t stability=0){
367 //set the unique tag to identify device type (bcm,bpm & etc)
368 errorflag|=kBCMErrorFlag;//currently I use the same flag for bcm & combinedbcm
369 QwMessage<<"QwCombinedBCM Error Code passing to QwVQWK_Ch "<<errorflag<<" "<<stability<<QwLog::endl;
370 fBeamCurrent.SetSingleEventCuts(errorflag,LL,UL,stability);
371
372}
373
374
375template<typename T>
376void QwCombinedBCM<T>::ConstructHistograms(TDirectory *folder, TString &prefix)
377{
378 if (this->GetElementName()=="")
379 {
380 // This channel is not used, so skip filling the histograms.
381 }
382 else
383 {
384 fBeamCurrent.ConstructHistograms(folder, prefix);
385 }
386 return;
387
388}
389
390template<typename T>
391void QwCombinedBCM<T>::FillHistograms()
392{
393 if (this->GetElementName()=="")
394 {
395 // This channel is not used, so skip filling the histograms.
396 }
397 else
398 {
399 fBeamCurrent.FillHistograms();
400 }
401
402
403 return;
404}
405
406template<typename T>
407void QwCombinedBCM<T>::ConstructBranchAndVector(TTree *tree, TString &prefix, QwRootTreeBranchVector &values)
408{
409 if (this->GetElementName()==""){
410 // This channel is not used, so skip filling the histograms.
411 } else
412 {
413 fBeamCurrent.ConstructBranchAndVector(tree,prefix,values);
414 }
415 return;
416}
417
418template<typename T>
419void QwCombinedBCM<T>::ConstructBranch(TTree *tree, TString &prefix)
420{
421 if (this->GetElementName()==""){
422 // This channel is not used, so skip filling the histograms.
423 } else
424 {
425 fBeamCurrent.ConstructBranch(tree,prefix);
426 }
427 return;
428}
429
430template<typename T>
431void QwCombinedBCM<T>::ConstructBranch(TTree *tree, TString &prefix, QwParameterFile& modulelist)
432{
433 TString devicename;
434 devicename=this->GetElementName();
435 devicename.ToLower();
436
437 if (this->GetElementName()==""){
438 // This channel is not used, so skip filling the histograms.
439 } else
440 {
441 if (modulelist.HasValue(devicename)){
442 fBeamCurrent.ConstructBranch(tree,prefix);
443 QwMessage <<" Tree leave added to "<<devicename<<QwLog::endl;
444 }
445 }
446 return;
447}
448
449
450template<typename T>
451void QwCombinedBCM<T>::FillTreeVector(QwRootTreeBranchVector &values) const
452{
453 if (this->GetElementName()==""){
454 // This channel is not used, so skip filling the histograms.
455 } else
456 {
457 fBeamCurrent.FillTreeVector(values);
458 }
459 return;
460}
461
462*/
463
464/********************************************************/
465template class QwCombinedBCM<QwVQWK_Channel>;
466template class QwCombinedBCM<QwADC18_Channel>;
Base and derived classes for scaler channel data handling.
#define QwMessage
Predefined log drain for regular messages.
Definition QwLog.h:49
Decoding and management for Moller ADC channels (6x32-bit datawords)
Decoding and management for VQWK ADC channels (6x32-bit datawords)
Database interface for QwIntegrationPMT and subsystems.
Combined beam current monitor using weighted average of multiple BCMs.
std::function< double()> QwCombinedBCM< T >::fRandomVariable
static const double sec
Definition QwUnits.h:80
static std::ostream & endl(std::ostream &)
End of the line.
Definition QwLog.cc:297
Configuration file parser with flexible tokenization and search capabilities.
T GetTypedNextToken()
Get next token into specific type.
std::string GetLine()
std::string GetNextToken(const std::string &separatorchars)
Get next token as a string.
virtual const TString & GetElementName() const
Get the name of this element.
void SetElementName(const TString &name)
Set the name of this element.
void SetModuleType(TString ModuleType)
set the type of the beam instrument
Template for a combined beam current monitor using weighted inputs.
Double_t fTripLength
void SetPedestal(Double_t ped) override
Set the pedestal value for the beam current monitor.
Double_t fLastTripTime
void InitializeChannel(TString name, TString datatosave) override
void SetCalibrationFactor(Double_t calib) override
Set the calibration factor for the beam current monitor.
Double_t fTripRamp
static std::uniform_real_distribution< double > fDistribution
Internal uniform probability distribution.
static void SetTripSeed(uint seedval)
Double_t fProbabilityOfTrip
void ProcessEvent() override
Double_t fTripPeriod
std::vector< Double_t > fWeights
std::vector< QwBCM< T > * > fElement
void GetProjectedCharge(VQwBCM *device) override
static std::function< double()> fRandomVariable
Internal normal random variable.
void LoadMockDataParameters(QwParameterFile &paramfile) override
UInt_t UpdateErrorFlag() override
Bool_t ApplySingleEventCuts() override
VQwBCM & operator=(const VQwBCM &value) override
Double_t fSumQweights
void SetBCMForCombo(VQwBCM *bcm, Double_t weight, Double_t sumqw) override
void RandomizeEventData(int helicity=0, double time=0.0) override
static std::mt19937 fRandomnessGenerator
Internal randomness generator.
void SetResolution(Double_t resolution)
Definition QwBCM.h:79
T fBeamCurrent
Definition QwBCM.h:189
Bool_t ApplySingleEventCuts() override
Apply single-event cuts for this BCM and return pass/fail.
Definition QwBCM.cc:279
void ClearEventData() override
Clear event-scoped data in the underlying channel.
Definition QwBCM.cc:136
QwBCM()
Definition QwBCM.h:40
virtual void FillRawEventData()
Definition VQwBCM.h:119
VQwBCM(VQwDataElement &beamcurrent)
Definition VQwBCM.h:64
virtual const VQwHardwareChannel * GetCharge() const
Definition VQwBCM.h:143
virtual void ApplyResolutionSmearing()
Definition VQwBCM.h:117