QwAnalysis
QwCombinedBPM.cc
Go to the documentation of this file.
1 /**********************************************************\
2  * File: QwCombinedBPM.cc *
3  * *
4  * Author: B. Waidyawansa *
5  * Time-stamp: *
6 \**********************************************************/
7 
8 #include "QwCombinedBPM.h"
9 
10 // System headers
11 #include <stdexcept>
12 
13 // Qweak headers
14 #include "QwDBInterface.h"
15 #include "QwVQWK_Channel.h"
16 #include "QwScaler_Channel.h"
17 #include "QwParameterFile.h"
18 
19 
20 template<typename T>
22 {
23 
25 
26  fEffectiveCharge.InitializeChannel(name+"_EffectiveCharge","derived");
27 
28  for( Short_t axis=kXAxis;axis<kNumAxes;axis++){
29  fAbsPos[axis].InitializeChannel(name+kAxisLabel[axis],"derived");
30  fSlope[axis].InitializeChannel(name+kAxisLabel[axis]+"Slope","derived");
31  fIntercept[axis].InitializeChannel(name+kAxisLabel[axis]+"Intercept","derived");
32  fMinimumChiSquare[axis].InitializeChannel(name+kAxisLabel[axis]+"MinChiSquare","derived");
33  }
34 
35  fixedParamCalculated = false;
36 
37  fElement.clear();
38  fQWeights.clear();
39  fXWeights.clear();
40  fYWeights.clear();
41 
42  fSumQweights = 0.0;
43 
44  for(Short_t axis=kXAxis;axis<kNumAxes;axis++){
45  erra[axis] = 0.0;
46  errb[axis] = 0.0;
47  covab[axis] = 0.0;
48  A[axis] = 0.0;
49  B[axis] = 0.0;
50  D[axis] = 0.0;
51  m[axis] = 0.0;
52  }
53 
54  return;
55 }
56 
57 template<typename T>
58 void QwCombinedBPM<T>::InitializeChannel(TString subsystem, TString name)
59 {
60 
62 
63  fEffectiveCharge.InitializeChannel(subsystem, "QwCombinedBPM", name+"_EffectiveCharge","derived");
64 
65  for( Short_t axis=kXAxis;axis<kNumAxes;axis++){
66  fAbsPos[axis].InitializeChannel(subsystem, "QwCombinedBPM", name+kAxisLabel[axis],"derived");
67  fSlope[axis].InitializeChannel(subsystem, "QwCombinedBPM", name+kAxisLabel[axis]+"Slope","derived");
68  fIntercept[axis].InitializeChannel(subsystem, "QwCombinedBPM", name+kAxisLabel[axis]+"Intercept","derived");
69  fMinimumChiSquare[axis].InitializeChannel(subsystem, "QwCombinedBPM",name+kAxisLabel[axis]+"MinChiSquare","derived");
70  }
71 
72  fixedParamCalculated = false;
73 
74  fElement.clear();
75  fQWeights.clear();
76  fXWeights.clear();
77  fYWeights.clear();
78 
79  fSumQweights = 0.0;
80 
81  for(Short_t axis=kXAxis;axis<kNumAxes;axis++){
82  erra[axis] = 0.0;
83  errb[axis] = 0.0;
84  covab[axis] = 0.0;
85  A[axis] = 0.0;
86  B[axis] = 0.0;
87  D[axis] = 0.0;
88  m[axis] = 0.0;
89  }
90 
91  return;
92 }
93 
94 
95 template<typename T>
97 {
98  fEffectiveCharge.ClearEventData();
99 
100  for(Short_t axis=kXAxis;axis<kNumAxes;axis++){
101  fAbsPos[axis].ClearEventData();
102  fSlope[axis].ClearEventData();
103  fIntercept[axis].ClearEventData();
104  }
105 
106  return;
107 }
108 
109 
110 template<typename T>
111 void QwCombinedBPM<T>::SetBPMForCombo(const VQwBPM* bpm, Double_t charge_weight, Double_t x_weight, Double_t y_weight,
112  Double_t sumqw)
113 {
114  fElement.push_back(bpm);
115  fQWeights.push_back(charge_weight);
116  fXWeights.push_back(x_weight);
117  fYWeights.push_back(y_weight);
118  fSumQweights=sumqw;
119 
120  size_t i = fElement.size();
121  if (i>=1){
122  i--;
123  // std::cout << "+++++++++++++++++++++++++++\n+++++++++++++++++++++++++++\n" << std::endl;
124  // std::cout << "fElement.size()==" << fElement.size() << " " << i << " "
125  // << fElement.at(i)->GetElementName() << " "
126  // << fQWeights.at(i) << " "
127  // << fXWeights.at(i) << " "
128  // << fYWeights.at(i) << " "
129  // << "fElement.at(i)->GetEffectiveCharge()==" << fElement.at(i)->GetEffectiveCharge() << " "
130  // << std::endl;
131  // fElement.at(i)->GetEffectiveCharge()->PrintInfo();
132  // fElement.at(i)->PrintInfo();
133  }
134  return;
135 
136 }
137 
138 
139 template<typename T>
141 {
142  Bool_t eventokay=kTRUE;
143 
144  return eventokay;
145 }
146 
147 
148 template<typename T>
150 {
151  for(Short_t axis=kXAxis;axis<kNumAxes;axis++){
152  fAbsPos[axis].IncrementErrorCounters();
153  fSlope[axis].IncrementErrorCounters();
154  fIntercept[axis].IncrementErrorCounters();
155  fMinimumChiSquare[axis].IncrementErrorCounters();
156  }
157 
158  fEffectiveCharge.IncrementErrorCounters();
159 }
160 
161 template<typename T>
163 {
164  for(Short_t axis=kXAxis;axis<kNumAxes;axis++){
165  fAbsPos[axis].PrintErrorCounters();
166  fSlope[axis].PrintErrorCounters();
167  fIntercept[axis].PrintErrorCounters();
168  fMinimumChiSquare[axis].PrintErrorCounters();
169  }
170 
171  fEffectiveCharge.PrintErrorCounters();
172 }
173 
174 template<typename T>
176 {
177  UInt_t error=0;
178  for(Short_t axis=kXAxis;axis<kNumAxes;axis++){
179  error|=fAbsPos[axis].GetEventcutErrorFlag();
180  error|=fSlope[axis].GetEventcutErrorFlag();
181  error|=fIntercept[axis].GetEventcutErrorFlag();
182  error|=fMinimumChiSquare[axis].GetEventcutErrorFlag();
183  }
184 
185  error|=fEffectiveCharge.GetEventcutErrorFlag();
186  return error;
187 }
188 
189 
190 
191 template<typename T>
193 {
194  Bool_t status=kTRUE;
195  Int_t axis=0;
196  UInt_t charge_error;
197  UInt_t pos_error[2];
198  charge_error = 0;
199  pos_error[kXAxis]=0;
200  pos_error[kYAxis]=0;
201 
202  for(size_t i=0;i<fElement.size();i++){
203  /// TODO: The returned base class should be changed so
204  /// these casts aren't needed, but "GetErrorCode"
205  /// is not meaningful for every VQwDataElement.
206  /// Maybe the return should be a VQwHardwareChannel?
207 
208  //To update the event cut faliures in individual BPM devices
209  charge_error |= fElement[i]->GetEffectiveCharge()->GetErrorCode();
210  pos_error[kXAxis] |= fElement[i]->GetPosition(kXAxis)->GetErrorCode();
211  pos_error[kYAxis] |= fElement[i]->GetPosition(kYAxis)->GetErrorCode();
212  }
213 
214  //Event cuts for X & Y slopes
215  for(axis=kXAxis;axis<kNumAxes;axis++){
216  fSlope[axis].UpdateErrorFlag(pos_error[axis]);
217  if (fSlope[axis].ApplySingleEventCuts()){ //for X slope
218  status&=kTRUE;
219  }
220  else{
221  status&=kFALSE;
222  if (bDEBUG) std::cout<<" X Slope event cut failed ";
223  }
224  }
225 
226  //Event cuts for X & Y intercepts
227  for(axis=kXAxis;axis<kNumAxes;axis++){
228  fIntercept[axis].UpdateErrorFlag(pos_error[axis]);
229  if (fIntercept[axis].ApplySingleEventCuts()){ //for X slope
230  status&=kTRUE;
231  }
232  else{
233  status&=kFALSE;
234  if (bDEBUG) std::cout<<" X Intercept event cut failed ";
235  }
236  }
237 
238 
239  //Event cuts for X & Y minimum chi square
240  for(axis=kXAxis;axis<kNumAxes;axis++){
241  fMinimumChiSquare[axis].UpdateErrorFlag(pos_error[axis]);
242  if (fMinimumChiSquare[axis].ApplySingleEventCuts()){ //for X slope
243  status&=kTRUE;
244  }
245  else{
246  status&=kFALSE;
247  if (bDEBUG) std::cout<<" X Intercept event cut failed ";
248  }
249  }
250 
251 
252  //Event cuts for X & Y positions
253  for(axis=kXAxis;axis<kNumAxes;axis++){
254  fAbsPos[axis].UpdateErrorFlag(pos_error[axis]);
255  if (fAbsPos[axis].ApplySingleEventCuts()){
256  status&=kTRUE;
257  }
258  else{
259  status&=kFALSE;
260  if (bDEBUG) std::cout<<" Abs X event cut failed ";
261  }
262  }
263 
264  //Event cuts for four wire sum (EffectiveCharge)
265  fEffectiveCharge.UpdateErrorFlag(charge_error);
266  if (fEffectiveCharge.ApplySingleEventCuts()){
267  status&=kTRUE;
268  }
269  else{
270  status&=kFALSE;
271  if (bDEBUG) std::cout<<"EffectiveCharge event cut failed ";
272  }
273 
274  return status;
275 }
276 
277 template<typename T>
279 {
280  Int_t axis=0;
281  UInt_t charge_error;
282  UInt_t pos_error[2];
283  charge_error = 0;
284  pos_error[kXAxis]=0;
285  pos_error[kYAxis]=0;
286 
287  UInt_t error = 0;
288 
289  for(size_t i=0;i<fElement.size();i++){
290  //To update the event cut faliures in individual BPM devices
291  charge_error |= fElement[i]->GetEffectiveCharge()->GetErrorCode();
292  pos_error[kXAxis] |= fElement[i]->GetPosition(kXAxis)->GetErrorCode();
293  pos_error[kYAxis] |= fElement[i]->GetPosition(kYAxis)->GetErrorCode();
294  }
295 
296  //Event cuts for X & Y slopes
297  for(axis=kXAxis;axis<kNumAxes;axis++){
298  fIntercept[axis].UpdateErrorFlag(pos_error[axis]);
299  fSlope[axis].UpdateErrorFlag(pos_error[axis]);
300  fMinimumChiSquare[axis].UpdateErrorFlag(pos_error[axis]);
301  fAbsPos[axis].UpdateErrorFlag(pos_error[axis]);
302 
303  //Get the Event cut error flag for SlopeX/Y
304  error|=fSlope[axis].GetEventcutErrorFlag();
305  error|=fIntercept[axis].GetEventcutErrorFlag();
306  error|=fMinimumChiSquare[axis].GetEventcutErrorFlag();
307  error|=fAbsPos[axis].GetEventcutErrorFlag();
308 
309  }
310 
311  //Event cuts for four wire sum (EffectiveCharge)
312  fEffectiveCharge.UpdateErrorFlag(charge_error);
313  //Get the Event cut error flag for EffectiveCharge
314  error|=fEffectiveCharge.GetEventcutErrorFlag();
315 
316  return error;
317 }
318 
319 
320 template<typename T>
322 {
323  VQwHardwareChannel* tmpptr = NULL;
324  ch_name.ToLower();
325  if (ch_name=="xslope"){
326  tmpptr = &fSlope[kXAxis];
327  }else if (ch_name=="yslope"){
328  tmpptr = &fSlope[kYAxis];
329  }else if (ch_name=="xintercept"){
330  tmpptr = &fIntercept[kXAxis];
331  }else if (ch_name=="yintercept"){
332  tmpptr = &fIntercept[kYAxis];
333  }else if (ch_name=="xminchisquare"){
334  tmpptr = &fMinimumChiSquare[kXAxis];
335  }else if (ch_name=="yminchisquare"){
336  tmpptr = &fMinimumChiSquare[kYAxis];
337  }else if (ch_name=="absx" || ch_name=="x" ){
338  tmpptr = &fAbsPos[kXAxis];
339  }else if (ch_name=="absy" || ch_name=="y"){
340  tmpptr = &fAbsPos[kYAxis];
341  }else if (ch_name=="effectivecharge" || ch_name=="charge"){
342  tmpptr = &fEffectiveCharge;
343  } else {
344  TString loc="QwCombinedBPM::GetSubelementByName for"
345  + this->GetElementName() + " was passed "
346  + ch_name + ", which is an unrecognized subelement name.";
347  throw std::invalid_argument(loc.Data());
348  }
349  return tmpptr;
350 }
351 
352 /*
353 template<typename T>
354 void QwCombinedBPM<T>::SetSingleEventCuts(TString ch_name, Double_t minX, Double_t maxX)
355 {
356 
357  if (ch_name=="xslope"){//cuts for the x slope
358  QwMessage<<"XSlope LL " << minX <<" UL " << maxX <<QwLog::endl;
359  fSlope[kXAxis].SetSingleEventCuts(minX,maxX);
360 
361  }else if (ch_name=="yslope"){//cuts for the y slope
362  QwMessage<<"YSlope LL " << minX <<" UL " << maxX <<QwLog::endl;
363  fSlope[kYAxis].SetSingleEventCuts(minX,maxX);
364 
365  }else if (ch_name=="xintercept"){//cuts for the x intercept
366  QwMessage<<"XIntercept LL " << minX <<" UL " << maxX <<QwLog::endl;
367  fIntercept[kXAxis].SetSingleEventCuts(minX,maxX);
368 
369  }else if (ch_name=="yintercept"){//cuts for the y intercept
370  QwMessage<<"YIntercept LL " << minX <<" UL " << maxX <<QwLog::endl;
371  fIntercept[kYAxis].SetSingleEventCuts(minX,maxX);
372 
373  } else if (ch_name=="absx"){
374  //cuts for the absolute x and y
375  QwMessage<<"AbsX LL " << minX <<" UL " << maxX <<QwLog::endl;
376  fAbsPos[kXAxis].SetSingleEventCuts(minX,maxX);
377 
378  }else if (ch_name=="absy"){
379  QwMessage<<"AbsY LL " << minX <<" UL " << maxX <<QwLog::endl;
380  fAbsPos[kYAxis].SetSingleEventCuts(minX,maxX);
381 
382  }else if (ch_name=="effectivecharge"){ //cuts for the effective charge
383  QwMessage<<"EffectveQ LL " << minX <<" UL " << maxX <<QwLog::endl;
384  fEffectiveCharge.SetSingleEventCuts(minX,maxX);
385  }
386 }
387 
388 template<typename T>
389 void QwCombinedBPM<T>::SetSingleEventCuts(TString ch_name, UInt_t errorflag,Double_t minX, Double_t maxX, Double_t stability){
390  errorflag|=kBPMErrorFlag;//update the device flag
391  if (ch_name=="xslope"){//cuts for the x slope
392  QwMessage<<"XSlope LL " << minX <<" UL " << maxX << " kGlobalCut "<< (errorflag&kGlobalCut)<< QwLog::endl;
393  fSlope[kXAxis].SetSingleEventCuts(errorflag, minX,maxX, stability);
394 
395  }else if (ch_name=="yslope"){//cuts for the y slope
396  QwMessage<<"YSlope LL " << minX <<" UL " << maxX <<" kGlobalCut "<< (errorflag&kGlobalCut)<< QwLog::endl;
397  fSlope[kYAxis].SetSingleEventCuts(errorflag, minX,maxX, stability);
398 
399  }else if (ch_name=="xintercept"){//cuts for the x intercept
400  QwMessage<<"XIntercept LL " << minX <<" UL " << maxX <<" kGlobalCut "<< (errorflag&kGlobalCut)<< QwLog::endl;
401  fIntercept[kXAxis].SetSingleEventCuts(errorflag, minX,maxX, stability);
402 
403  }else if (ch_name=="yintercept"){//cuts for the y intercept
404  QwMessage<<"YIntercept LL " << minX <<" UL " << maxX <<" kGlobalCut "<< (errorflag&kGlobalCut)<< QwLog::endl;
405  fIntercept[kYAxis].SetSingleEventCuts(errorflag, minX,maxX, stability);
406 
407  } else if (ch_name=="absx"){
408  //cuts for the absolute x and y
409  QwMessage<<"AbsX LL " << minX <<" UL " << maxX <<" kGlobalCut "<< (errorflag&kGlobalCut)<< QwLog::endl;
410  fIntercept[kXAxis].SetSingleEventCuts(errorflag, 0,0,0);
411  fAbsPos[kXAxis].SetSingleEventCuts(errorflag, minX,maxX, stability);
412 
413  }else if (ch_name=="absy"){
414  QwMessage<<"AbsY LL " << minX <<" UL " << maxX <<" kGlobalCut "<< (errorflag&kGlobalCut)<< QwLog::endl;
415  fIntercept[kYAxis].SetSingleEventCuts(errorflag, 0,0,0);
416  fAbsPos[kYAxis].SetSingleEventCuts(errorflag, minX,maxX, stability);
417 
418  }else if (ch_name=="effectivecharge"){ //cuts for the effective charge
419  QwMessage<<"EffectveQ LL " << minX <<" UL " << maxX <<" kGlobalCut "<< (errorflag&kGlobalCut)<< QwLog::endl;
420  fEffectiveCharge.SetSingleEventCuts(errorflag, minX,maxX, stability);
421  }
422 }
423 
424 */
425 
426 template<typename T>
428  Short_t i=0;
429  try {
430  if(typeid(*ev_error)==typeid(*this)) {
431  // std::cout<<" Here in QwBPMStripline::UpdateErrorFlag \n";
432  if (this->GetElementName()!="") {
433  const QwCombinedBPM<T>* value_bpm = dynamic_cast<const QwCombinedBPM<T>* >(ev_error);
434  for(i=kXAxis;i<kNumAxes;i++) {
435  fAbsPos[i].UpdateErrorFlag(value_bpm->fAbsPos[i]);
436  fSlope[i].UpdateErrorFlag(value_bpm->fSlope[i]);
437  fIntercept[i].UpdateErrorFlag(value_bpm->fIntercept[i]);
438  fMinimumChiSquare[i].UpdateErrorFlag(value_bpm->fMinimumChiSquare[i]);
439  }
440  fEffectiveCharge.UpdateErrorFlag(value_bpm->fEffectiveCharge);
441  }
442  } else {
443  TString loc="Standard exception from QwCombinedBPM::UpdateErrorFlag :"+
444  ev_error->GetElementName()+" "+this->GetElementName()+" are not of the "
445  +"same type";
446  throw std::invalid_argument(loc.Data());
447  }
448  } catch (std::exception& e) {
449  std::cerr<< e.what()<<std::endl;
450  }
451 };
452 
453 
454 
455 template<typename T>
457 {
458  Bool_t ldebug = kFALSE;
459 
460  static T tmpQADC("tmpQADC"), tmpADC("tmpADC");
461 
462  //check to see if the fixed parameters are calculated
463  if(!fixedParamCalculated){
464  if(ldebug) std::cout<<"QwCombinedBPM:Calculating fixed parameters..\n";
465  CalculateFixedParameter(fXWeights,kXAxis); //for X
466  CalculateFixedParameter(fYWeights,kYAxis); //for Y
467  fixedParamCalculated = kTRUE;
468  }
469 
470  for(size_t i=0;i<fElement.size();i++){
471  if(ldebug){
472  std::cout<<"*******************************\n";
473  std::cout<<" QwCombinedBPM: Reading "<<fElement[i]->GetElementName()<<" with charge weight ="<<fQWeights[i]
474  <<" and x weight ="<<fXWeights[i]
475  <<" and y weight ="<<fYWeights[i]<<"\n"<<std::flush;
476 
477  }
478  tmpQADC.AssignValueFrom(fElement[i]->GetEffectiveCharge());
479  tmpQADC.Scale(fQWeights[i]);
480  fEffectiveCharge+=tmpQADC;
481 
482 
483  if(ldebug) {
484  std::cout<<"fElement[" << i << "]->GetEffectiveCharge()=="
485  << fElement[i]->GetEffectiveCharge()
486  << std::endl << std::flush;
487  fElement[i]->GetEffectiveCharge()->PrintInfo();
488  std::cout<<"fElement[" << i << "]->GetPosition(kXAxis)=="
489  << fElement[i]->GetPosition(kXAxis)
490  << std::endl << std::flush;
491  std::cout<<"fElement[" << i << "]->GetPosition(kYAxis)=="
492  << fElement[i]->GetPosition(kYAxis)
493  << std::endl << std::flush;
494 
495  if (fElement[i]->GetEffectiveCharge()==NULL){
496  std::cout<<"fElement[" << i << "]->GetEffectiveCharge returns NULL"
497  << std::endl;
498  } else
499  std::cout<<"got 4-wire.hw_sum = "<<fEffectiveCharge.GetValue()
500  <<" vs actual "
501  << fElement[i]->GetEffectiveCharge()->GetValue()
502  << std::endl << std::flush;
503 
504 
505  std::cout<<"copied absolute X position hw_sum from device "
506  << fElement[i]->GetPosition(kXAxis)->GetValue() <<std::endl;
507  std::cout<<"copied absolute Y position hw_sum from device "
508  << fElement[i]->GetPosition(kYAxis)->GetValue() <<std::endl;
509 
510  }
511  }
512 
513  fEffectiveCharge.Scale(1.0/fSumQweights);
514  //fAbsPos[0].ResetErrorFlag(0x4000000);
515  //Least squares fit for X
516  LeastSquareFit(kXAxis, fXWeights );
517 
518  //Least squares fit for Y
519  LeastSquareFit(kYAxis, fYWeights );
520 
521 
522  if(ldebug){
523  std::cout<<" QwCombinedBPM:: Projected target X position = "<<fAbsPos[kXAxis].GetValue()
524  <<" and target X slope = "<<fSlope[kXAxis].GetValue()
525  <<" and target X intercept = "<<fIntercept[kXAxis].GetValue()
526  <<" with mimimum chi square = "<< fMinimumChiSquare[kXAxis].GetValue()
527  <<" \nProjected target Y position = "<<fAbsPos[kYAxis].GetValue()
528  <<" and target Y slope = "<<fSlope[kYAxis].GetValue()
529  <<" and target Y intercept = "<<fIntercept[kYAxis].GetValue()
530  <<" with mimimum chi square = "<< fMinimumChiSquare[kYAxis].GetValue()<<std::endl;
531 
532  }
533 
534 
535  if (ldebug) {
536  fEffectiveCharge.PrintInfo();
537  for(Short_t axis=kXAxis;axis<kNumAxes;axis++) {
538  fAbsPos[axis].PrintInfo();
539  fSlope[axis].PrintInfo();
540  fIntercept[axis].PrintInfo();
541  fMinimumChiSquare[axis].PrintInfo();
542  }
543  }
544 
545  return;
546 
547  }
548 
549 
550 
551 template<typename T>
552  void QwCombinedBPM<T>::CalculateFixedParameter(std::vector<Double_t> fWeights, Int_t pos)
553  {
554 
555  Bool_t ldebug = kFALSE;
556  static Double_t zpos = 0.0;
557 
558  for(size_t i=0;i<fElement.size();i++){
559  zpos = fElement[i]->GetPositionInZ();
560  A[pos] += zpos*fWeights[i]; //zw
561  B[pos] += fWeights[i]; //w
562  D[pos] += zpos*zpos*fWeights[i]; //z^2w
563  }
564 
565  m[pos] = D[pos]*B[pos]-A[pos]*A[pos];
566  erra[pos] = B[pos]/m[pos];
567  errb[pos] = D[pos]/m[pos];
568  covab[pos] = -A[pos]/m[pos];
569 
570  // Divvy
571  if (m[pos] == 0)
572  QwWarning << "Angry Divvy: Division by zero in " << this->GetElementName() << QwLog::endl;
573 
574  if(ldebug){
575  std::cout<<" A = "<<A[pos]<<", B = "<<B[pos]<<", D = "<<D[pos]<<", m = "<<m[pos]<<std::endl;
576  std::cout<<"For least square fit, errors are "<<erra[pos]
577  <<"\ncovariance = "<<covab[pos]<<"\n\n";
578  }
579 
580  return;
581  }
582 
583 
584 template<typename T>
585  Double_t QwCombinedBPM<T>::SumOver(std::vector<Double_t> weight,std::vector <T> val)
586  {
587  Double_t sum = 0.0;
588  if(weight.size()!=fElement.size()){
589  std::cout
590  <<"QwCombinedBPM:: Number of devices doesnt match the number of weights."
591  <<" Exiting calculating parameters for the least squares fit"
592  <<std::endl;
593  }
594  else{
595  for(size_t i=0;i<weight.size();i++){
596  val[i].Scale(weight[i]);
597  sum+=val[i].GetValue();
598  }
599  }
600  return sum;
601  }
602 
603 template<typename T>
604  void QwCombinedBPM<T>::LeastSquareFit(VQwBPM::EBeamPositionMonitorAxis axis, std::vector<Double_t> fWeights)
605  {
606 
607  /**
608  REF : W.R Leo
609 
610  For Y = aX +b
611 
612  A = sigma(X * Wy) B = sigma(Wy) C = sigma(Y*Wy) D = sigma(X *X * Wy) E = sigma(X*Y*Wy) F = sigma(Y * Y *Wy)
613 
614  then
615  a = (EB-CA)/(DB-AA) b =(DC-EA)/(DB-AA)
616  **/
617 
618  Bool_t ldebug = kFALSE;
619  static Double_t zpos = 0;
620  static T tmp1("tmp1","derived");
621  static T tmp2("tmp2","derived");
622  static T tmp3("tmp3","derived");
623  static T C[kNumAxes];
624  static T E[kNumAxes];
625 
626  // initialize the VQWK_Channel arrays
627  C[kXAxis].InitializeChannel("cx","derived");
628  C[kYAxis].InitializeChannel("cy","derived");
629  E[kXAxis].InitializeChannel("ex","derived");
630  E[kYAxis].InitializeChannel("ey","derived");
631 
632  C[axis].ClearEventData();
633  E[axis].ClearEventData();
634  for(size_t i=0;i<fElement.size();i++){
635  zpos = fElement[i]->GetPositionInZ();
636  tmp1.ClearEventData();
637  tmp1.AssignValueFrom(fElement[i]->GetPosition(axis));
638  tmp1.Scale(fWeights[i]);
639  C[axis] += tmp1; //xw or yw
640  tmp1.Scale(zpos);//xzw or yzw
641  E[axis] += tmp1;
642  }
643 
644  if(ldebug) std::cout<<"\n A ="<<A[axis]
645  <<" -- B ="<<B[axis]
646  <<" --C ="<<C[axis].GetValue()
647  <<" --D ="<<D[axis]
648  <<" --E ="<<E[axis].GetValue()<<"\n";
649 
650  // calculate the slope a = E*erra + C*covab
651  fSlope[axis].AssignScaledValue(E[axis], erra[axis]);
652  tmp2.AssignScaledValue(C[axis], covab[axis]);
653  fSlope[axis] += tmp2;
654 
655  // calculate the intercept b = C*errb + E*covab
656  fIntercept[axis].AssignScaledValue(C[axis], errb[axis]);
657  tmp2.AssignScaledValue(E[axis], covab[axis]);
658  fIntercept[axis] += tmp2;
659 
660  if(ldebug) std::cout<<" Least Squares Fit Parameters for "<< axis
661  <<" are: \n slope = "<< fSlope[axis].GetValue()
662  <<" \n intercept = " << fIntercept[axis].GetValue()<<"\n\n";
663 
664 
665  // absolute positions at target using X = Za + b
666  tmp1.ClearEventData();
667  // Absolute position of the combined bpm is not a physical position but a derived one.
668 
669 
670  zpos = this->GetPositionInZ();
671  //UInt_t err_flag=fAbsPos[axis].GetEventcutErrorFlag();
672  fAbsPos[axis] = fIntercept[axis]; // X = b
673  //fAbsPos[axis].ResetErrorFlag(err_flag);
674  tmp1.AssignScaledValue(fSlope[axis],zpos); //az
675  fAbsPos[axis] += tmp1; //X = az+b
676 
677 
678  // to perform the minimul chi-square test
679  // We want to calculte (X-az-b)^2 for each bpm in the combination and sum over the values
680  tmp3.ClearEventData();
681  fMinimumChiSquare[axis].ClearEventData();
682 
683  for(size_t i=0;i<fElement.size();i++){
684  tmp1.ClearEventData();
685  tmp2.ClearEventData();
686  //std::cout<<"\nName -------- ="<<(fElement[i]->GetElementName())<<std::endl;
687  //std::cout<<"\nRead value ="<<(fElement[i]->GetPosition(axis))->GetValue()<<std::endl;
688 
689  tmp1.AssignValueFrom(fElement[i]->GetPosition(axis)); // = X
690  //std::cout<<"Read value ="<<tmp1.GetValue()<<std::endl;
691 
692  tmp2.AssignScaledValue(fSlope[axis],fElement[i]->GetPositionInZ());
693  tmp2+=fIntercept[axis];
694  //std::cout<<"Calculated abs value ="<<tmp2.GetValue()<<std::endl;
695 
696  tmp1 -= tmp2; // = X-Za-b
697  //std::cout<<"Read-calculated ="<<tmp1.GetValue()<<std::endl;
698  tmp1.Product(tmp1,tmp1); // = (X-Za-b)^2
699  //std::cout<<"(Read-calculated)^2 ="<<tmp1.GetValue()<<std::endl;
700  tmp1.Scale(fWeights[i]*fWeights[i]); // = [(X-Za-b)^2]W
701  //std::cout<<"(Read-calculated)^2/weight ="<<tmp1.GetValue()<<std::endl;
702  tmp3+=tmp1; //sum over
703  //std::cout<<"Sum (Read-calculated)^2/weight +="<<tmp3.GetValue()<<std::endl;
704  }
705 
706  fMinimumChiSquare[axis].AssignScaledValue(tmp3,1.0/(fElement.size()-2)); //minimul chi-square
707 
708  return;
709  }
710 
711 template<typename T>
712  Int_t QwCombinedBPM<T>::ProcessEvBuffer(UInt_t* buffer, UInt_t word_position_in_buffer,UInt_t index)
713  {
714  return word_position_in_buffer;
715  }
716 
717 
718 
719 template<typename T>
721 {
722  Short_t axis;
723 
724  for(axis = kXAxis; axis < kNumAxes; axis++){
725  fAbsPos[axis].PrintValue();
726  }
727  /// TODO: To print the Z position, we need to use GetPositionInZ()
728  for(axis = kXAxis; axis < kNumAxes; axis++) {
729  fSlope[axis].PrintValue();
730  fIntercept[axis].PrintValue();
731  fMinimumChiSquare[axis].PrintValue();
732  }
733  fEffectiveCharge.PrintValue();
734 
735  return;
736  }
737 
738 
739 template<typename T>
741 {
742 
743  Short_t axis;
744 
745  for(axis = kXAxis; axis < kNumAxes; axis++){
746  fAbsPos[axis].PrintInfo();
747  }
748  /// TODO: To print the Z position, we need to use GetPositionInZ()
749  for(axis = kXAxis; axis < kNumAxes; axis++) {
750  fSlope[axis].PrintInfo();
751  fIntercept[axis].PrintInfo();
752  fMinimumChiSquare[axis].PrintInfo();
753  }
754  fEffectiveCharge.PrintInfo();
755 
756  return;
757 }
758 
759 
760 template<typename T>
762 {
763  *(dynamic_cast<QwCombinedBPM<T>*>(this))=
764  *(dynamic_cast<const QwCombinedBPM<T>*>(&value));
765  return *this;
766 }
767 
768 template<typename T>
770 {
771  VQwBPM::operator= (value);
772  if (this->GetElementName()!=""){
773  this->fEffectiveCharge=value.fEffectiveCharge;
774  for(Short_t axis=kXAxis;axis<kNumAxes;axis++){
775  this->fSlope[axis]=value.fSlope[axis];
776  this->fIntercept[axis] = value.fIntercept[axis];
777  this->fAbsPos[axis]=value.fAbsPos[axis];
778  this->fMinimumChiSquare[axis]=value.fMinimumChiSquare[axis];
779  }
780  }
781  return *this;
782 }
783 
784 
785 template<typename T>
787 {
788  *(dynamic_cast<QwCombinedBPM<T>*>(this))+=
789  *(dynamic_cast<const QwCombinedBPM<T>*>(&value));
790  return *this;
791 }
792 
793 template<typename T>
795 {
796 
797  if (this->GetElementName()!=""){
798  this->fEffectiveCharge+=value.fEffectiveCharge;
799  for(Short_t axis=kXAxis;axis<kNumAxes;axis++) {
800  this->fSlope[axis]+=value.fSlope[axis];
801  this->fIntercept[axis]+=value.fIntercept[axis];
802  this->fAbsPos[axis]+=value.fAbsPos[axis];
803  this->fMinimumChiSquare[axis]+=value.fMinimumChiSquare[axis];
804  }
805  }
806  return *this;
807 }
808 
809 template<typename T>
811 {
812  *(dynamic_cast<QwCombinedBPM<T>*>(this))-=
813  *(dynamic_cast<const QwCombinedBPM<T>*>(&value));
814  return *this;
815 }
816 
817 
818 template<typename T>
820 {
821 
822  if (this->GetElementName()!=""){
823  this->fEffectiveCharge-=value.fEffectiveCharge;
824  for(Short_t axis=kXAxis;axis<kNumAxes;axis++){
825  this->fSlope[axis]-=value.fSlope[axis];
826  this->fIntercept[axis]-=value.fIntercept[axis];
827  this->fAbsPos[axis]-=value.fAbsPos[axis];
828  this->fMinimumChiSquare[axis]-=value.fMinimumChiSquare[axis];
829  }
830  }
831  return *this;
832 }
833 
834 
835 template<typename T>
837 {
838  Ratio(*dynamic_cast<QwCombinedBPM<T>*>(&numer),
839  *dynamic_cast<QwCombinedBPM<T>*>(&denom));
840 }
841 
842 template<typename T>
844  QwCombinedBPM<T> &denom)
845 {
846  // this function is called when forming asymmetries. In this case waht we actually want for the
847  // combined bpm is the difference only not the asymmetries
848 
849  *this=numer;
850  this->fEffectiveCharge.Ratio(numer.fEffectiveCharge,denom.fEffectiveCharge);
851  if (this->GetElementName()!=""){
852  // The slope, intercept and absolute positions should all be differences, not asymmetries.
853  for(Short_t axis=kXAxis;axis<kNumAxes;axis++) {
854  this->fSlope[axis] = numer.fSlope[axis];
855  this->fIntercept[axis] = numer.fIntercept[axis];
856  this->fAbsPos[axis] = numer.fAbsPos[axis];
857  this->fMinimumChiSquare[axis] = numer.fMinimumChiSquare[axis];
858  }
859  }
860 
861  return;
862 }
863 
864 
865 template<typename T>
866 void QwCombinedBPM<T>::Scale(Double_t factor)
867 {
868  fEffectiveCharge.Scale(factor);
869  for(Short_t axis=kXAxis;axis<kNumAxes;axis++){
870  fSlope[axis].Scale(factor);
871  fIntercept[axis].Scale(factor);
872  fAbsPos[axis].Scale(factor);
873  fMinimumChiSquare[axis].Scale(factor);
874  }
875  return;
876 }
877 
878 template<typename T>
880 {
881  fEffectiveCharge.CalculateRunningAverage();
882 
883  for (Short_t axis = kXAxis; axis < kNumAxes; axis++) {
884  fSlope[axis].CalculateRunningAverage();
885  fIntercept[axis].CalculateRunningAverage();
886  fAbsPos[axis].CalculateRunningAverage();
887  fMinimumChiSquare[axis].CalculateRunningAverage();
888  }
889 }
890 
891 
892 template<typename T>
894 {
895  AccumulateRunningSum(*dynamic_cast<const QwCombinedBPM<T>* >(&value));
896 }
897 
898 template<typename T>
900 {
901  for (Short_t axis = kXAxis; axis < kNumAxes; axis++){
902  fSlope[axis].AccumulateRunningSum(value.fSlope[axis]);
903  fIntercept[axis].AccumulateRunningSum(value.fIntercept[axis]);
904  fAbsPos[axis].AccumulateRunningSum(value.fAbsPos[axis]);
905  fMinimumChiSquare[axis].AccumulateRunningSum(value.fMinimumChiSquare[axis]);
906  }
907  fEffectiveCharge.AccumulateRunningSum(value.fEffectiveCharge);
908 }
909 
910 template<typename T>
912 {
913  DeaccumulateRunningSum(*dynamic_cast<QwCombinedBPM<T>* >(&value));
914 }
915 
916 template<typename T>
918 {
919 
920  for (Short_t axis = kXAxis; axis < kNumAxes; axis++){
921  fSlope[axis].DeaccumulateRunningSum(value.fSlope[axis]);
922  fIntercept[axis].DeaccumulateRunningSum(value.fIntercept[axis]);
923  fAbsPos[axis].DeaccumulateRunningSum(value.fAbsPos[axis]);
924  fMinimumChiSquare[axis].DeaccumulateRunningSum(value.fMinimumChiSquare[axis]);
925  }
926  fEffectiveCharge.DeaccumulateRunningSum(value.fEffectiveCharge);
927 
928 }
929 
930 
931 
932 
933 
934 template<typename T>
935 void QwCombinedBPM<T>::ConstructHistograms(TDirectory *folder, TString &prefix)
936 {
937 
938  if (this->GetElementName()==""){
939  // This channel is not used, so skip filling the histograms.
940  }
941  else{
942  //we calculate the asym_ for the fEffectiveCharge becasue its an asymmetry and not a difference.
943  fEffectiveCharge.ConstructHistograms(folder, prefix);
944  TString thisprefix=prefix;
945  if(prefix=="asym_")
946  thisprefix="diff_";
947  this->SetRootSaveStatus(prefix);
948 
949  for(Short_t axis=kXAxis;axis<kNumAxes;axis++) {
950  fSlope[axis].ConstructHistograms(folder, thisprefix);
951  fIntercept[axis].ConstructHistograms(folder, thisprefix);
952  fAbsPos[axis].ConstructHistograms(folder, thisprefix);
953  fMinimumChiSquare[axis].ConstructHistograms(folder, thisprefix);
954  }
955 
956  }
957  return;
958 }
959 
960 template<typename T>
962 {
963  if (this->GetElementName()==""){
964  // This channel is not used, so skip filling the histograms.
965  }
966  else{
967  fEffectiveCharge.FillHistograms();
968  for(Short_t axis=kXAxis;axis<kNumAxes;axis++) {
969  fSlope[axis].FillHistograms();
970  fIntercept[axis].FillHistograms();
971  fAbsPos[axis].FillHistograms();
972  fMinimumChiSquare[axis].FillHistograms();
973  }
974  }
975  return;
976 }
977 
978 template<typename T>
979 void QwCombinedBPM<T>::ConstructBranchAndVector(TTree *tree, TString &prefix, std::vector<Double_t> &values)
980 {
981  if (this->GetElementName()==""){
982  // This channel is not used, so skip constructing trees.
983  } else
984  {
985 
986  TString thisprefix=prefix;
987  if(prefix=="asym_")
988  thisprefix="diff_";
989 
990  this->SetRootSaveStatus(prefix);
991 
992  fEffectiveCharge.ConstructBranchAndVector(tree,prefix,values);
993  for(Short_t axis=kXAxis;axis<kNumAxes;axis++){
994  fSlope[axis].ConstructBranchAndVector(tree,thisprefix,values);
995  fIntercept[axis].ConstructBranchAndVector(tree,thisprefix,values);
996  fAbsPos[axis].ConstructBranchAndVector(tree,thisprefix,values);
997  fMinimumChiSquare[axis].ConstructBranchAndVector(tree,thisprefix,values);
998  }
999 
1000  }
1001 
1002  return;
1003 }
1004 
1005 template<typename T>
1006 void QwCombinedBPM<T>::ConstructBranch(TTree *tree, TString &prefix)
1007 {
1008  if (this->GetElementName()==""){
1009  // This channel is not used, so skip constructing trees.
1010  } else
1011  {
1012  TString thisprefix=prefix;
1013  if(prefix=="asym_")
1014  thisprefix="diff_";
1015 
1016 
1017  fEffectiveCharge.ConstructBranch(tree,prefix);
1018 
1019  for(Short_t axis=kXAxis;axis<kNumAxes;axis++){
1020  fSlope[axis].ConstructBranch(tree,thisprefix);
1021  fIntercept[axis].ConstructBranch(tree,thisprefix);
1022  fAbsPos[axis].ConstructBranch(tree,thisprefix);
1023  fMinimumChiSquare[axis].ConstructBranch(tree,thisprefix);
1024  }
1025 
1026  }
1027  return;
1028 }
1029 
1030 template<typename T>
1031 void QwCombinedBPM<T>::ConstructBranch(TTree *tree, TString &prefix, QwParameterFile& modulelist)
1032 {
1033  TString devicename;
1034  devicename=this->GetElementName();
1035  devicename.ToLower();
1036 
1037  if (this->GetElementName()==""){
1038  // This channel is not used, so skip constructing trees.
1039  } else
1040  {
1041  if (modulelist.HasValue(devicename)){
1042  TString thisprefix=prefix;
1043  if(prefix=="asym_")
1044  thisprefix="diff_";
1045 
1046 
1047  fEffectiveCharge.ConstructBranch(tree,prefix);
1048 
1049  for(Short_t axis=kXAxis;axis<kNumAxes;axis++){
1050  fSlope[axis].ConstructBranch(tree,thisprefix);
1051  fIntercept[axis].ConstructBranch(tree,thisprefix);
1052  fAbsPos[axis].ConstructBranch(tree,thisprefix);
1053  fMinimumChiSquare[axis].ConstructBranch(tree,thisprefix);
1054  }
1055  QwMessage <<" Tree leave added to "<<devicename<<QwLog::endl;
1056  }
1057 
1058  }
1059  return;
1060 }
1061 
1062 
1063 template<typename T>
1064 void QwCombinedBPM<T>::FillTreeVector(std::vector<Double_t> &values) const
1065 {
1066  if (this->GetElementName()==""){
1067  // This channel is not used, so skip filling the tree.
1068  }
1069  else{
1070  fEffectiveCharge.FillTreeVector(values);
1071 
1072  for(Short_t axis=kXAxis;axis<kNumAxes;axis++){
1073  fSlope[axis].FillTreeVector(values);
1074  fIntercept[axis].FillTreeVector(values);
1075  fAbsPos[axis].FillTreeVector(values);
1076  fMinimumChiSquare[axis].FillTreeVector(values);
1077  }
1078  }
1079  return;
1080 }
1081 
1082 template<typename T>
1084 {
1085 
1086  // bEVENTCUTMODE=bcuts;
1087  for (Short_t axis=kXAxis;axis<kNumAxes;axis++){
1088  fSlope[axis].SetEventCutMode(bcuts);
1089  fIntercept[axis].SetEventCutMode(bcuts);
1090  fAbsPos[axis].SetEventCutMode(bcuts);
1091  fMinimumChiSquare[axis].SetEventCutMode(bcuts);
1092  }
1093  fEffectiveCharge.SetEventCutMode(bcuts);
1094 
1095  return;
1096 }
1097 
1098 
1099 template<typename T>
1101 {
1102  for (size_t axis = kXAxis; axis < kNumAxes; axis++) {
1103  T abspos(fAbsPos[axis]);
1104  abspos = fAbsPos[axis];
1105  fBPMComboElementList.push_back(abspos);
1106  T slope(fSlope[axis]);
1107  slope = fSlope[axis];
1108  fBPMComboElementList.push_back(slope);
1109  T intercept(fIntercept[axis]);
1110  intercept = fIntercept[axis];
1111  fBPMComboElementList.push_back(intercept);
1112  T minimumchisquare(fMinimumChiSquare[axis]);
1113  minimumchisquare = fMinimumChiSquare[axis];
1114  fBPMComboElementList.push_back(minimumchisquare);
1115  }
1116  T effectivecharge(fEffectiveCharge);
1117  effectivecharge = fEffectiveCharge;
1118  fBPMComboElementList.push_back(effectivecharge);
1119 }
1120 
1121 
1122 
1123 template<typename T>
1124 std::vector<QwDBInterface> QwCombinedBPM<T>::GetDBEntry()
1125 {
1126  std::vector <QwDBInterface> row_list;
1127  row_list.clear();
1128  for(size_t axis=kXAxis;axis<kNumAxes;axis++) {
1129  fAbsPos[axis].AddEntriesToList(row_list);
1130  fSlope[axis].AddEntriesToList(row_list);
1131  fIntercept[axis].AddEntriesToList(row_list);
1132  fMinimumChiSquare[axis].AddEntriesToList(row_list);
1133  }
1134  fEffectiveCharge.AddEntriesToList(row_list);
1135  return row_list;
1136 }
1137 
1138 
1139 
1140 template<typename T>
1141 std::vector<QwErrDBInterface> QwCombinedBPM<T>::GetErrDBEntry()
1142 {
1143  std::vector <QwErrDBInterface> row_list;
1144  row_list.clear();
1145  for(size_t axis=kXAxis;axis<kNumAxes;axis++) {
1146  fAbsPos[axis].AddErrEntriesToList(row_list);
1147  fSlope[axis].AddErrEntriesToList(row_list);
1148  fIntercept[axis].AddErrEntriesToList(row_list);
1149  fMinimumChiSquare[axis].AddErrEntriesToList(row_list);
1150  }
1151  // fEffectiveCharge.AddErrEntriesToList(row_list);
1152  return row_list;
1153 }
1154 
1155 template class QwCombinedBPM<QwVQWK_Channel>;
1156 template class QwCombinedBPM<QwSIS3801_Channel>;
#define QwMessage
Predefined log drain for regular messages.
Definition: QwLog.h:50
void PrintErrorCounters() const
report number of events failed due to HW and event cut failure
void CalculateRunningAverage()
void InitializeChannel(TString name)
static const double m
Definition: QwUnits.h:63
void IncrementErrorCounters()
VQwBPM & operator-=(const VQwBPM &value)
static const double e
Definition: QwUnits.h:91
void CalculateFixedParameter(std::vector< Double_t > fWeights, Int_t pos)
VQwBPM & operator=(const VQwBPM &value)
void SetEventCutMode(Int_t bcuts)
Inherited from VQwDataElement to set the upper and lower limits (fULimit and fLLimit), stability % and the error flag on this channel.
Bool_t ApplySingleEventCuts()
void FillTreeVector(std::vector< Double_t > &values) const
void ConstructBranchAndVector(TTree *tree, TString &prefix, std::vector< Double_t > &values)
UInt_t UpdateErrorFlag()
Update the error flag based on the error flags of internally contained objects Return paramter is the...
Double_t SumOver(std::vector< Double_t > weight, std::vector< T > val)
Bool_t HasValue(TString &vname)
void ClearEventData()
Clear the event data in this element.
VQwHardwareChannel * GetSubelementByName(TString ch_name)
void FillHistograms()
Fill the histograms for this data element.
UInt_t GetEventcutErrorFlag()
return the error flag on this channel/device
void DeaccumulateRunningSum(VQwBPM &value)
void LeastSquareFit(VQwBPM::EBeamPositionMonitorAxis axis, std::vector< Double_t > fWeights)
void Scale(Double_t factor)
void SetBPMForCombo(const VQwBPM *bpm, Double_t charge_weight, Double_t x_weight, Double_t y_weight, Double_t sumqw)
static const double T
Magnetic field: base unit is T.
Definition: QwUnits.h:111
void InitializeChannel(TString name)
Definition: VQwBPM.cc:25
EBeamPositionMonitorAxis
Definition: VQwBPM.h:54
void ConstructHistograms(TDirectory *folder, TString &prefix)
Construct the histograms for this data element.
static std::ostream & endl(std::ostream &)
End of the line.
Definition: QwLog.cc:299
Definition: VQwBPM.h:34
T fMinimumChiSquare[2]
virtual const TString & GetElementName() const
Get the name of this element.
void PrintInfo() const
Print multiple lines of information about this data element.
VQwBPM & operator+=(const VQwBPM &value)
void MakeBPMComboList()
std::vector< QwErrDBInterface > GetErrDBEntry()
#define QwWarning
Predefined log drain for warnings.
Definition: QwLog.h:45
virtual VQwBPM & operator=(const VQwBPM &value)=0
Definition: VQwBPM.cc:115
std::vector< QwDBInterface > GetDBEntry()
Bool_t ApplyHWChecks()
void Ratio(QwCombinedBPM &numer, QwCombinedBPM &denom)
void PrintValue() const
Print single line of value and error of this data element.
void ConstructBranch(TTree *tree, TString &prefix)
void AccumulateRunningSum(const VQwBPM &value)
Int_t ProcessEvBuffer(UInt_t *buffer, UInt_t word_position_in_buffer, UInt_t indexnumber)
Process the CODA event buffer for this element.