ATLAS Offline Software
GraphTest.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
9 #include <TGraphErrors.h>
10 #include <TClass.h>
11 #include <dqm_core/AlgorithmConfig.h>
13 #include <dqm_core/Result.h>
14 #include <ers/ers.h>
15 #include <string>
16 #include <sstream>
17 #include <iostream>
18 #include <dqm_core/AlgorithmManager.h>
19 
20 #define NPARS 6
21 
22 static dqm_algorithms::GraphTest myInstance;
23 
25  dqm_core::AlgorithmManager::instance().registerAlgorithm("GraphTest",this);
26 }
27 
29 
31  return new GraphTest();
32 }
33 
35  const TObject & obj,
36  const dqm_core::AlgorithmConfig & config )
37 {
38  std::unique_ptr<TGraph> newgraph;
39  const TGraph* graph;
40  const TGraph* refhist = 0;
41  if ( obj.IsA()->InheritsFrom("TGraph") )
42  {
43  ERS_DEBUG(2,"Got TGraph called: "<<obj.GetName()<<" of type:"<<obj.IsA()->GetName());
44  graph = static_cast<const TGraph*>(&obj);
45  }
46  else if ( obj.IsA()->InheritsFrom("TH1") )
47  {
48  ERS_DEBUG(2,"Got TH1: converting to TGraphErrors");
49  newgraph = std::make_unique<TGraphErrors>(static_cast<const TH1*>(&obj));
50  newgraph->SetNameTitle("TempG","TempG");
51  graph = newgraph.get();
52  }
53  else
54  {
55  throw dqm_core::BadConfig(ERS_HERE,name,"Object is not a TGraph or a TH1");
56  }
57  //Now get reference object and check compatibility
58  ERS_DEBUG(2,"Retreiving reference graph");
59 
60  try {
61  refhist = static_cast<const TGraph*>( config.getReference() );
62  }
63  catch ( dqm_core::Exception & ex ) {
64  ERS_DEBUG(2,"No reference specified, will skip point-by-point comparison");
65  }
66  Int_t npoints = graph->GetN();
67  ERS_DEBUG(2,"Number of points to be checked: "<<npoints);
68  if ( refhist ) {
69  if ( ! refhist->IsA()->InheritsFrom("TGraph") )
70  {
71  throw dqm_core::BadRefHist(ERS_HERE,name,"Reference is not a TGraph");
72  }
73  if ( refhist->GetN() != npoints )
74  {
75  throw dqm_core::BadConfig(ERS_HERE,name,"Reference and object with different number of points");
76  }
77  }
78  else {
79  ERS_DEBUG(2,"No reference specified, will skip point-by-point comparison");
80  }
81  // Configure the DQ algorithm
82  const std::string param[NPARS] = {"XErrHigh","XErrLow","YErrHigh","YErrLow","DistFactor","NBins"};
83  Double_t bigNumber = 1.7E+308; //some big number...
84  Double_t grValue[NPARS] = { bigNumber , bigNumber , bigNumber , bigNumber , 1, 0 };
85  Double_t reValue[NPARS] = { bigNumber , bigNumber , bigNumber , bigNumber , 1, 0 };
86  for ( unsigned int i = 0; i<NPARS;++i) {
87  // get configuration for Green Threshold
88  try
89  {
90  grValue[i] = dqm_algorithms::tools::GetFromMap(param[i] , config.getGreenThresholds() );
91  }
92  catch ( dqm_core::Exception & ex )
93  {
94  ERS_DEBUG(1,"Parameter: i"<<param[i]<<"' for Green not found in configuration, using default: "<<grValue[i]);
95  }
96  // get configuration for Red Threshold
97  try
98  {
99  reValue[i] = dqm_algorithms::tools::GetFromMap(param[i] , config.getRedThresholds() );
100  }
101  catch ( dqm_core::Exception & ex )
102  {
103  ERS_DEBUG(1,"Parameter: i"<<param[i]<<"' for Red not found in configuration, using default: "<<reValue[i]);
104  }
105  if ( reValue[i] < grValue[i] ) // Non sense values
106  {
107  std::stringstream msg;
108  msg<<"Configuration Error (Red<Green):"<<param[i]<<" G="<<grValue[i]<<" R="<<reValue[i];
109  throw dqm_core::BadConfig(ERS_HERE,name,msg.str());
110  }
111  } // End of configuration retreival
112 #if DEBUG_LEVEL > 1
113  if ( grValue[4]==0 ) { ERS_DEBUG(2,"Exact Match request for Green"); }
114  if ( reValue[4]==0 ) { ERS_DEBUG(2,"Exact Match request for Red"); }
115  std::stringstream configuration;
116  for ( int i = 0;i<NPARS;++i)
117  {
118  configuration<<" - "<<param[i]<<" Green:"<<grValue[i]<<" Red:"<<reValue[i];
119  }
120  ERS_DEBUG(2,"Configuration: "<<configuration.str());
121 #endif
122  // Just a translation in something more readable...
123  Double_t grXEH =grValue[0]; // Error (High) on X
124  Double_t grXEL =grValue[1]; // Error (Low) on X
125  Double_t grYEH =grValue[2]; // Error (High) on Y
126  Double_t grYEL =grValue[3]; // Error (Low) on Y
127  Double_t grExpF=grValue[4]; // Moltiplicative Factor for DX,DY
128  Double_t Ngreen=grValue[5]; // Number of points to fail
129  Double_t reXEH =reValue[0]; // Error (High) on X
130  Double_t reXEL =reValue[1]; // Error (Low) on X
131  Double_t reYEH =reValue[2]; // Error (High) on Y
132  Double_t reYEL =reValue[3]; // Error (Low) on Y
133  Double_t reExpF=reValue[4]; // Multiplicative Factor for DX,DY
134  Double_t Nred = reValue[5]; // Number of points to fail
135  // Everything is now configured correctly, we can start
136  Int_t yellowCounterErrorBars=0 , yellowCounterPoints=0;
137  Int_t redCounterErrorBars=0 , redCounterPoints=0;
138  std::stringstream errorsList;
139  auto result = std::make_unique<dqm_core::Result>();
140  for ( Int_t bin = 0 ; bin < npoints ; ++bin) //Loop on all points
141  {
142  // Check point error bars
143  ERS_DEBUG(3,"====> Starting check on point "<<bin);
144  ERS_DEBUG(3,"Checking error bars");
145  Double_t xEH=graph->GetErrorXhigh(bin),xEL=graph->GetErrorXlow(bin);
146  Double_t yEH=graph->GetErrorYhigh(bin),yEL=graph->GetErrorYlow(bin);
147  if ( xEH>grXEH || xEL>grXEL || yEH>grYEH || yEL>grYEL )
148  {
149  ERS_DEBUG(2,"[YELLOW] (point "<<bin<<") error bars:xH="<<xEH<<",xL="<<xEL<<",yH="<<yEH<<",yL="<<yEL);
150  ERS_DEBUG(3,"Limits are: xH="<<grValue[0]<<" xL="<<grValue[1]<<" yH="<<grValue[2]<<" yL="<<grValue[3]<<" nGreen="<<grValue[5]);
151  errorsList<<"; point "<<bin<<" Err. bars:xH="<<xEH<<",xL="<<xEL<<",yH="<<yEH<<",yL="<<yEL;
152  ++yellowCounterErrorBars;
153  }
154  if ( xEH>reXEH || xEL>reXEL || yEH>reYEH || yEL>reYEL )
155  {
156  ERS_DEBUG(2,"[RED] (point "<<bin<<") error bars:xH="<<xEH<<",xL="<<xEL<<",yH="<<yEH<<",yL="<<yEL);
157  ERS_DEBUG(3,"Limits are: xH="<<reValue[0]<<" xL="<<reValue[1]<<" yH="<<reValue[2]<<" yL="<<reValue[3]<<" nRed="<<reValue[5]);
158  ERS_DEBUG(1,"[RED] Result");// game over, RED level reached
159  ++redCounterErrorBars;
160  result->tags_.insert(std::make_pair("RedErrorBarsForPoint",bin));
161  }
162  // Now Check if point is compatible with reference point (x_r,y_r)
163  // reference point (asymmetric) errors bars
164  // (xEH,xEL,yEH,yEL) define the max. allowed distance for
165  // The ProximityFactor can be used to set two different thresholds for
166  // yellow and red.
167  // If ref. point errors bars are zeros do not check that coordinate
168  // Ex. Point is Green if: x_r - f*xEL =< x =< x_r + f*xEH AND
169  // y_r - f*yEL =< y =< y_r + f*yEH
170  ERS_DEBUG(3,"Checking compatibility with reference point");
171  Double_t x,y;
172  graph->GetPoint(bin,x,y);
173  Double_t x_r = x ,y_r = y;
174  if (refhist) refhist->GetPoint(bin,x_r,y_r);
175  Double_t DX = x-x_r , DY=y-y_r;
176  Double_t xEH_r = 0 , xEL_r = 0 , yEH_r = 0 , yEL_r = 0;
177  if ( refhist ) {
178  xEH_r = refhist->GetErrorXhigh(bin);
179  xEL_r = refhist->GetErrorXlow(bin);
180  yEH_r = refhist->GetErrorYhigh(bin);
181  yEL_r = refhist->GetErrorYlow(bin);
182  }
183  if ( xEH_r==0 && xEL_r==0 )
184  {
185  ERS_DEBUG(3,"Turn off check on x (point "<<bin<<")");
186  DX=0; // Do not check X
187  }
188  if ( yEH_r==0 && yEL_r==0 )
189  {
190  ERS_DEBUG(3,"Turn off check on y (point "<<bin<<")");
191  DY=0; // Do not check Y
192  }
193  if ( DX > grExpF*xEH_r || DX < -grExpF*xEL_r ||
194  DY > grExpF*yEH_r || DY < -grExpF*yEL_r )
195  {
196  ERS_DEBUG(2,"[YELLOW] Point "<<bin<<" does not match with reference value (DX,DY)=("<<DX<<","<<DY<<")");
197  ERS_DEBUG(3,"Limits are: "<<-grExpF*xEL_r<<"<DX<"<<grExpF*xEH_r<<" ; "<<-grExpF*yEL_r<<"<DY<"<<grExpF*yEH_r);
198  errorsList<<"; point "<<bin<<" Does not match with reference (DX,DY)=("<<DX<<","<<DY<<")";
199  ++yellowCounterPoints;
200  std::stringstream out;
201  out << yellowCounterPoints;
202  std::string yellowtag = out.str();
203  if(yellowCounterPoints<10) yellowtag= "0"+yellowtag;
204  yellowtag ="YellowPointNumber"+yellowtag;
205  result->tags_.insert(std::make_pair(yellowtag,bin));
206  }
207  if ( DX > reExpF*xEH_r || DX < -reExpF*xEL_r ||
208  DY > reExpF*yEH_r || DY < -reExpF*yEL_r )
209  {
210  ERS_DEBUG(2,"[RED] Point "<<bin<<" does not match with reference value (DX,DY)=("<<DX<<","<<DY<<")");
211  ERS_DEBUG(3,"Limits are: "<<-grExpF*xEL_r<<"<DX<"<<grExpF*xEH_r<<" ; "<<-grExpF*yEL_r<<"<DY<"<<grExpF*yEH_r);
212  ERS_DEBUG(1,"[RED] Result");
213  ++redCounterPoints;
214  std::stringstream out;
215  out << redCounterPoints;
216  std::string redtag = out.str();
217  if(redCounterPoints<10) redtag= "0"+redtag;
218  redtag ="RedPointNumber"+redtag;
219  result->tags_.insert(std::make_pair(redtag,bin));
220  //result->tags_.insert(std::make_pair("RedPointNumber"+redCounterPoints,bin));
221  }
222  ERS_DEBUG(3,"End of checks for Point "<<bin);
223  } // End loop on points
224  if ( redCounterErrorBars > Nred || redCounterPoints > Nred )
225  {
226  ERS_DEBUG(1,"[Error] Result with "<<redCounterErrorBars+redCounterPoints<<" errors");
227  ERS_DEBUG(2,"List of errors"<<errorsList.str());
228  result->status_=dqm_core::Result::Red;
229  if ( redCounterErrorBars > 0 )
230  result->tags_.insert(std::make_pair("NumRedErrorBars",redCounterErrorBars));
231  if ( redCounterPoints > 0 )
232  result->tags_.insert(std::make_pair("NumRedComparison",redCounterPoints));
233  return result.release();
234  }
235  if ( yellowCounterErrorBars > Ngreen || yellowCounterPoints > Ngreen )
236  {
237  ERS_DEBUG(1,"[YELLOW] Result with "<<yellowCounterErrorBars+yellowCounterPoints<<" errors");
238  ERS_DEBUG(2,"List of errors"<<errorsList.str());
239  if ( yellowCounterErrorBars > 0 )
240  result->tags_.insert(std::make_pair("NumYellowsErrorBars",yellowCounterErrorBars));
241  if ( yellowCounterPoints > 0 )
242  result->tags_.insert(std::make_pair("NumYellowsComparison",yellowCounterPoints));
243  result->status_=dqm_core::Result::Yellow;
244  return result.release();
245  }
246  ERS_DEBUG(1,"[GREEN] Result");
248 }
249 
250 void
252 {
253  out<<"GraphTest DQ algorithm: check validity of a TGraph (or TH1)"<<std::endl
254  <<"This test can be used to perform a test on a TGraph with (or without) error bars, in case asymmmetric."<<std::endl
255  <<"It performs two tests:"<<std::endl
256  <<"1- It checks that each point in the TGraph has \"small\" error bars"<<std::endl
257  <<"2- It checks that each point is \"close\" to a reference value"<<std::endl
258  <<"For test 2 a reference TGraph has to be provided (in this way each point may have a different reference value). "<<std::endl
259  <<"The (x,y) coordinates of the point are compared with the reference point coordinates (x_r,y_r) and REFERENCE "<<std::endl
260  <<" point error bars defining the maximum allowed distance. i.e."<<std::endl
261  <<"the point is good if: x_r - f*x_err < x < x_r + f*x_err AND y_r - f*y_err < y < y_r + f*y_err"<<std::endl
262  <<"\"f\" is a factor that can be used to specify different limits for Green and Red thresholds."<<std::endl
263  <<"If, for a specific reference point, the error bars along one coordinate are set to zero the test 2 is NOT performed for that point (this can be used to exclude, for example, a dead channel through the reference graph). "<<std::endl
264  <<"The algorithms can work also with TGraphAsymmErrors object, so high and low errors can always be specified separately."<<std::endl
265  <<"The optional parameters that can be set, separetely, for Green and Red thresholds are:"<<std::endl
266  <<"XErrHigh : Maximum (higher) error bar length x coord (default is 1.844E19)."<<std::endl
267  <<"XErrLow : Maximum (lower) error bar length x coord (default is 1.844E19)."<<std::endl
268  <<"YErrHigh : Maximum (higher) error bar length y coord (default is 1.844E19)."<<std::endl
269  <<"YErrLow : Maximum (lower) error bar length y coord (default is 1.844E19)."<<std::endl
270  <<"DistFactor : The factor \"f\" used in second part of the test (default is 1)."<<std::endl
271  <<"NBins : This is the number of points allowed to fail to change result(default is 0)."<<std::endl;
272 
273 }
get_generator_info.result
result
Definition: get_generator_info.py:21
dqm_algorithms::GraphTest
Definition: GraphTest.h:51
dqm_algorithms::GraphTest::~GraphTest
virtual ~GraphTest()
Definition: GraphTest.cxx:28
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
bin
Definition: BinsDiffFromStripMedian.h:43
yodamerge_tmp.npoints
npoints
Definition: yodamerge_tmp.py:250
dqm_algorithms::GraphTest::execute
virtual dqm_core::Result * execute(const std::string &, const TObject &obj, const dqm_core::AlgorithmConfig &conf)
Definition: GraphTest.cxx:34
x
#define x
config
Definition: PhysicsAnalysis/AnalysisCommon/AssociationUtils/python/config.py:1
instance
std::map< std::string, double > instance
Definition: Run_To_Get_Tags.h:8
lumiFormat.i
int i
Definition: lumiFormat.py:85
Result
ICscStripFitter::Result Result
Definition: CalibCscStripFitter.cxx:13
dqm_algorithms::GraphTest::printDescription
void printDescription(std::ostream &out)
Definition: GraphTest.cxx:251
GraphTest.h
python.handimod.Green
int Green
Definition: handimod.py:524
python.handimod.Red
Red
Definition: handimod.py:551
dqm_algorithms::GraphTest::clone
virtual GraphTest * clone()
Definition: GraphTest.cxx:30
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
plotBeamSpotVxVal.bin
int bin
Definition: plotBeamSpotVxVal.py:83
y
#define y
dqm_algorithms::GraphTest::GraphTest
GraphTest()
Definition: GraphTest.cxx:24
AlgorithmHelper.h
dqm_algorithms::tools::GetFromMap
const T & GetFromMap(const std::string &pname, const std::map< std::string, T > &params)
Definition: AlgorithmHelper.h:114
NPARS
#define NPARS
Definition: GraphTest.cxx:20
python.PyAthena.obj
obj
Definition: PyAthena.py:132
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7