MINT2
Chi2Binning.cpp
Go to the documentation of this file.
2 
3 #include "Mint/Chi2Binning.h"
4 #include "Mint/Chi2Box.h"
5 #include "Mint/Chi2BoxSet.h"
6 
8 
9 #include "TCanvas.h"
10 #include "TH1D.h"
11 
12 #include <algorithm>
13 #include <iostream>
14 
15 using namespace MINT;
16 using namespace std;
17 
19 int Chi2Binning::__Ncol=256;
20 
22  static const int NRGBs = 7;
23  if(0 != __colourPalette) delete[] __colourPalette;
24  __colourPalette = new int[__Ncol];
25 
26  Double_t stops[NRGBs] = { 0.00, 0.10, 0.25, 0.45, 0.60, 0.75, 1.00 };
27  Double_t red[NRGBs] = { 0.85, 0.00, 0.00, 0.00, 0.80, 0.80, 0.99 };
28  Double_t green[NRGBs] = { 0.85, 0.80, 0.40, 0.40, 0.80, 0.00, 0.00 };
29  Double_t blue[NRGBs] = { 0.85, 0.85, 0.80, 0.00, 0.00, 0.00, 0.00 };
30  Int_t Fi = TColor::CreateGradientColorTable(NRGBs
31  , stops
32  , red, green, blue
33  , __Ncol);
34 
35  for(int i=0; i < __Ncol; i++) __colourPalette[i]=Fi + i;
36 }
38  static const int NRGBs = 7;
39  if(0 != __colourPalette) delete[] __colourPalette;
40  __colourPalette = new int[__Ncol];
41 
42  Double_t stops[NRGBs] = { 0.00, 0.10, 0.25, 0.45, 0.60, 0.75, 1.00 };
43  Double_t red[NRGBs] = { 1.00, 0.00, 0.00, 0.00, 0.97, 0.97, 0.10 };
44  Double_t green[NRGBs] = { 1.00, 0.97, 0.30, 0.40, 0.97, 0.00, 0.00 };
45  Double_t blue[NRGBs] = { 1.00, 0.97, 0.97, 0.00, 0.00, 0.00, 0.00 };
46  Int_t Fi = TColor::CreateGradientColorTable(NRGBs
47  , stops
48  , red, green, blue
49  , __Ncol);
50 
51  for(int i=0; i < __Ncol; i++) __colourPalette[i]=Fi + i;
52 }
54  static const int NRGBs = 5;
55 
56  if(0 != __colourPalette) delete[] __colourPalette;
57  __colourPalette = new int[__Ncol];
58 
59  Double_t red[NRGBs] = {0., 0.0, 1.0, 1.0, 1.0};
60  Double_t green[NRGBs] = {0., 0.0, 0.0, 1.0, 1.0};
61  Double_t blue[NRGBs] = {0., 1.0, 0.0, 0.0, 1.0};
62  Double_t stops[NRGBs] = {0., .25, .50, .75, 1.0};
63  Int_t Fi = TColor::CreateGradientColorTable(NRGBs
64  , stops
65  , red, green, blue
66  , __Ncol);
67 
68  for(int i=0; i < __Ncol; i++) __colourPalette[i]=Fi + i;
69 }
71  makeColourPaletteBlueGrey();
72  //makeColourPaletteRGB();
73  //makeColourPaletteBlueWhite();
74 }
75 
77  if(0 == __colourPalette) makeColourPalette();
78  return __colourPalette;
79 }
80 
82  : _nData(0)
83  , _nMC(0)
84  , _totalMCWeight(0)
85 {
86 }
88  , int minPerBin
89  , int maxPerBin
90  ){
91 
92  if(0 == events) return 0;
93  if(0 == events->size()) return 0;
94 
95  Chi2BoxSet boxes = splitBoxes(events, maxPerBin);
96 
97  mergeBoxes(boxes, minPerBin);
98 
99  return numBins();
100 }
101 
102 int Chi2Binning::mergeBoxes(Chi2BoxSet& boxes, int minPerBin){
103  lessByChi2BoxData sorter;
104  sort(boxes.begin(), boxes.end(), sorter);
105  // this way, the smalles boxes come first
106  // makes sure no empty box is left over at the end.
107 
108  Chi2BoxSet boxSet;
109  for(unsigned int i=0; i < boxes.size(); i++){
110  boxSet.add(boxes[i]);
111  if(boxSet.nData() >= minPerBin){
112  _boxSets.push_back(boxSet);
113  boxSet.clear();
114  }
115  }
116 
117  return _boxSets.size();
118 }
119 
120 
122  , int maxPerBin
123  ) const{
124  bool dbThis=false;
125  if(dbThis){
126  cout << "Chi2Binning::splitBoxes(MINT::IEventList<DalitzEvent>* events , int maxPerBin = "
127  << maxPerBin << ") called" << endl;
128  }
129 
130  Chi2BoxSet dummy;
131  if(0 == events) return dummy;
132  return splitBoxes(*events, maxPerBin);
133 }
134 
136  , int maxPerBin
137  ) const{
138  bool dbThis=false;
139  Chi2BoxSet dummy;
140  if(0 == events.size()) return dummy;
141  const IDalitzEvent& evt0 = events.getEvent(0);
142 
143  Chi2Box box(evt0.eventPattern());
144 
145  Chi2BoxSet boxes(box.split(0));
146  bool needToSplitMore=false;
147  int counter=0;
148  do{
149  counter++;
150  boxes.resetEventCounts();
151  int failedSet=0, failedBox=0;
152 
153  for(unsigned int i=0; i < events.size(); i++){
154  bool added = boxes.addData(events.getEvent(i));
155  if(! added) failedSet++;
156  if(! box.addData(events.getEvent(i))){
157  failedBox++;
158  }
159  }
160  if(failedSet > 0 || dbThis){
161  cout << " Chi2Binning::splitBoxes: ERROR split level " << counter
162  << ", num boxes: " << boxes.size()
163  << ", failedSet: " << failedSet
164  << ", failedBox: " << failedBox << endl;
165  }
166 
167  Chi2BoxSet newBoxes;
168  needToSplitMore=false;
169  for(unsigned int i=0; i < boxes.size(); i++){
170  if( boxes[i].nData() > maxPerBin ){
171  needToSplitMore=true;
172  newBoxes.add(boxes[i].split());
173  }else{
174  newBoxes.add(boxes[i]);
175  }
176  }
177  boxes = newBoxes;
178  }while(needToSplitMore);
179 
180  return boxes;
181 }
182 
184  _nData=0;
185  _nMC=0;
186  _totalMCWeight=0.0;
187  for(unsigned int i=0; i < _boxSets.size(); i++){
188  _boxSets[i].resetEventCounts();
189  }
190 }
192  for(unsigned int k=0; k < data.size(); k++){
193  bool foundBox=false;
194  DalitzEvent evt(data.getEvent(k));
195  for(unsigned int i=0; i < _boxSets.size(); i++){
196  if(_boxSets[i].addData(evt)){
197  foundBox=true;
198  _nData++;
199  break;
200  }
201  }
202  if(! foundBox){
203  cout << "WARNING in Chi2Binning::fillData:"
204  << "\n\t didn't find box for event "
205  << endl;
206  evt.print();
207  cout << "compare to first event: " << endl;
208  DalitzEvent firstEvt(data.getEvent(0));
209  firstEvt.print();
210  Chi2Box box(evt.eventPattern());
211  cout << "would have fit into large? "
212  << box.addData(evt) << endl;
213  }
214  }
215 }
217  , IDalitzPdf* pdf){
218  bool dbThis=false;
219  if(dbThis){
220  cout << "Chi2Binning::fillMC called with "
221  << &mc << ", " << pdf << endl;
222  }
223  int printevery=10000;
224  for(unsigned int k=0; k < mc.size(); k++){
225  bool printit = (0 == k%printevery);
226  if(printit) cout << "...fillMC filling event number " << k;
227  DalitzEvent evt(mc.getEvent(k));
228  double weight = pdf->getVal_noPs(evt) * evt.getWeight() /
229  evt.getGeneratorPdfRelativeToPhaseSpace();
230 
231  if(printit) cout << ", with weight " << weight << endl;
232  int n=0;
233  for(unsigned int i=0; i < _boxSets.size(); i++){
234  if(_boxSets[i].addMC(evt, weight)){
235  _totalMCWeight += weight;
236  _nMC++;
237  n++;
238  break;
239  }
240  }
241  if(dbThis){
242  cout << "event " << k << " in " << n << " out of " << numBins()
243  << " box sets" << endl;
244  if(0 == n) evt.print();
245  cout << "mc weight now: " << _totalMCWeight << endl;
246  }
247  }
248  if(dbThis) cout << "Total MC weight: " << _totalMCWeight << endl;
249 }
250 
252  lessByChi2BoxSetChi2 sorter;
253  stable_sort(_boxSets.rbegin(), _boxSets.rend(), sorter);
254 }
257  , IDalitzPdf* pdf
259  ){
260  bool dbThis=false;
261  if(dbThis) cout << "Chi2Binning::setEventsAndPdf" << endl;
262  if(0 == data) return -9999;
263  if(0 == mc) return -9999;
264  if(0 == pdf) return -9999;
265  //(could do this: if 0 == pdf: mc generated with pdf from fit result.
266  // But for now, leave it like this for safety)
267 
268  if(0 == numBins()) createBinning(data);
269  if(0 != fas) setFas(fas);
270  if(dbThis) cout << "...number of chi2 bins = " << numBins() << endl;
272  if(dbThis) cout << "...about to fill in the data " << endl;
273  fillData(data);
274  if(dbThis) cout << "...done that - now the MC" << endl;
275  fillMC(mc, pdf);
276  if(dbThis) cout << "... fillMC done, now setting norm factors" << endl;
278  if(dbThis) cout << " done the norm factors, now sorting by chi2" << endl;
279  sortByChi2();
280  if(dbThis) cout << " Chi2Binning::setEventsAndPdf done" << endl;
281  return 0;
282 }
283 
285  bool dbThis=true;
286 
288  ic = fas->makeIntegrationCalculator();
289 
290  if(dbThis) {
291  cout << "Chi2Binning::setFas: this is the fas:" << endl;
292  fas->print(cout);
293  cout << endl;
294  }
295  for(unsigned int i=0; i < _boxSets.size(); i++){
297  _boxSets[i].setIIntegrationCalculator(fap);
298  }
299 }
300 
301 void Chi2Binning::print(std::ostream& os) const{
302 
303  int nDataCheck=0;
304  double nMCCheck=0;
305  double chi2sum=0;
306  double sumVarData =0;
307  double sumVarMC =0;
308  for(unsigned int i=0; i < _boxSets.size(); i++){
309  int n_data = _boxSets[i].nData();
310  nDataCheck += n_data;
311  double weight_mc = _boxSets[i].weightedMC() * normFactor();
312  nMCCheck += weight_mc;
313 
314  double var_mc_noNorm = _boxSets[i].rmsMC(_nMC);
315  double var_mc = var_mc_noNorm* normFactor()*normFactor();
316  double varData_expected = weight_mc;
317  sumVarData += varData_expected;
318  sumVarMC += var_mc;
319  double chi2 = chi2_ofBin(i);
320  chi2sum += chi2;
321 
322  os << " bin " << i;
323  os << " data " << _boxSets[i].nData();
324  os << ", mcweight " << _boxSets[i].weightedMC() * normFactor();
325  os << ", (nMC " << _boxSets[i].nMC() << ")";
326  os << ", chi2 " << chi2 << endl;
327  _boxSets[i].printBoxInfo(os);
328  }
329  os << "\n=========================================================="<< endl;
330  os << "chi2 / nbins = " << chi2sum << " / " << numBins()
331  << " = " << chi2sum/numBins() << endl;
332  os << "===========================================================" << endl;
333  os << " total data weight: " << nDataCheck
334  << " .. _nData = " << _nData
335  << " should be same as normalised total MC weight = " << nMCCheck
336  << " (un-normalised = " << _totalMCWeight << ")"
337  << endl;
338  if(sumVarMC > sumVarData){
339  os << "Severe WARNING in Chi2Binning::getChi2_perBin()"
340  << "\n error on difference between data and MC dominated by MC"
341  << "\n mean data variance: " << sumVarData/numBins()
342  << ", ... mc: " << sumVarMC/numBins()
343  << ".\n Get more MC!"
344  << endl;
345  }
346 }
347 
348 double Chi2Binning::normFactor() const{
349  return ((double)_nData)/_totalMCWeight;
350 }
351 
353  for(unsigned int i=0; i < _boxSets.size(); i++){
354  _boxSets[i].setNormFactor(normFactor());
355  }
356 }
357 
358 double Chi2Binning::chi2_ofBin(unsigned int i) const{
359  if(i > _boxSets.size()) return -9999;
360  return _boxSets[i].chi2(normFactor());
361 }
363  if(_nMC <= 0) return -9999;
364  if(_nData <=0 ) return -9999;
365  if(_totalMCWeight <= 0.0) return -9999;
366 
367  double sum=0;
368  for(unsigned int i=0; i < _boxSets.size(); i++){
369  double chi2 = chi2_ofBin(i);
370  sum += chi2;
371  }
372 
373  return sum/numBins();
374 }
375 double Chi2Binning::getMaxChi2() const{
376  double max=-1;
377  for(unsigned int i=0; i < _boxSets.size(); i++){
378  double chi2 = chi2_ofBin(i);
379  if(chi2 > max) max=chi2;
380  }
381  return max;
382 }
383 
385  return _boxSets.size();
386 }
387 /*
388 void Chi2Binning::setHistoColours(){
389  double maxChi2 = getMaxChi2();
390  for(unsigned int i=0; i < _boxSets.size(); i++){
391  double chi2 = chi2_ofBin(i);
392  int colIndex = (chi2/maxChi2)*__Ncol;
393  int col = (getColourPalette())[colIndex];
394  _boxSets[i].setHistoColour(col);
395  }
396 }
397 */
399  double maxChi2 = getMaxChi2();
400  for(unsigned int i=0; i < _boxSets.size(); i++){
401  double chi2 = chi2_ofBin(i);
402  int colIndex = (chi2/maxChi2)*(__Ncol-1);
403  int col = (getColourPalette())[colIndex];
404  _boxSets[i].setHistoColour(col);
405  }
406 }
408  setHistoColours();
409  DalitzHistoStackSet hstack;
410 
411  for(unsigned int i=0; i < _boxSets.size(); i++){
412  hstack.add(_boxSets[i].histoData());
413  }
414  double mx = getMaxChi2();
415  if(mx > 20) mx=20;
417  //cout << "printing newly made data histo stack" << endl;
418  //hstack.draw("experimental_chi2DataHisto");
419  return hstack;
420 }
422  setHistoColours();
423  DalitzHistoStackSet hstack;
424 
425  for(unsigned int i=0; i < _boxSets.size(); i++){
426  hstack.add(_boxSets[i].histoMC());
427  }
428  double mx = getMaxChi2();
429  if(mx > 20) mx=20;
430 
432  // cout << "printing newly made MC histo stack" << endl;
433  // hstack.draw("experimental_chi2MCHisto");
434  return hstack;
435 }
436 
438  int nbins=100;
439  double from=0, to=getMaxChi2();
440  cout << "from " << from << " to " << to << endl;
441  counted_ptr<TH1D> h(new TH1D("chi2 distribution", "chi2 distribution"
442  , nbins, from, to));
443  h->SetDirectory(0);
444  for(unsigned int i=0; i < _boxSets.size(); i++){
445  //cout << "filling chi2 " << _boxSets[i].chi2() << endl;
446  h->Fill(_boxSets[i].chi2());
447  }
448  return h;
449 }
450 void Chi2Binning::drawChi2Distribution(const std::string& fname)const{
451  TCanvas can;
452  can.SetLogy();
454  h->Draw();
455  can.Print(fname.c_str());
456 }
457 
458 bool lessByChi2BoxData::operator()(const Chi2Box& a, const Chi2Box& b) const{
459 
460  return a.nData() < b.nData();
461 }
462 
464 
465  return a.chi2() < b.chi2();
466 }
467 
468 std::ostream& operator<<(std::ostream& os, const Chi2Binning& c2b){
469  c2b.print(os);
470  return os;
471 }
472 //
MINT::counted_ptr< TH1D > getChi2Distribution() const
static void makeColourPaletteBlueGrey()
Definition: Chi2Binning.cpp:21
double getChi2_perBin() const
void add(const Chi2Box &box)
Definition: Chi2BoxSet.cpp:53
double getMaxChi2() const
static void makeColourPaletteBlueWhite()
Definition: Chi2Binning.cpp:37
void resetEventCounts()
Definition: Chi2BoxSet.cpp:63
void setHistoColours()
double chi2(double normFactorPassed=-1) const
Definition: Chi2BoxSet.cpp:209
static int * __colourPalette
Definition: Chi2Binning.h:27
Chi2BoxSet splitBoxes(MINT::IMinimalEventList< DalitzEvent > *events, int maxPerBin) const
std::vector< T >::iterator end()
virtual MINT::counted_ptr< IIntegrationCalculator > clone_IIntegrationCalculator() const =0
static void makeColourPaletteRGB()
Definition: Chi2Binning.cpp:53
double setEventsAndPdf(MINT::IMinimalEventList< DalitzEvent > *data, MINT::IMinimalEventList< DalitzEvent > *mc, IDalitzPdf *pdf, IFastAmplitudeIntegrable *fas=0)
void drawChi2Distribution(const std::string &fname="chi2Distribution.eps") const
void resetEventCounts()
std::ostream & operator<<(std::ostream &os, const Chi2Binning &c2b)
virtual MINT::counted_ptr< IIntegrationCalculator > makeIntegrationCalculator()=0
void fillMC(MINT::IMinimalEventList< DalitzEvent > &mc, IDalitzPdf *pdf)
double chi2_ofBin(unsigned int i) const
int createBinning(MINT::IMinimalEventList< DalitzEvent > *events, int minPerBin=10, int maxPerBin=100)
Definition: Chi2Binning.cpp:87
bool operator()(const Chi2BoxSet &a, const Chi2BoxSet &b) const
virtual void add(const DalitzCoordSet &coord, const MINT::counted_ptr< TH1 > &histo)
void setBoxesNormFactors()
static void makeColourPalette()
Definition: Chi2Binning.cpp:70
bool addData(const IDalitzEvent &evt)
Definition: Chi2Box.cpp:68
void fillData(MINT::IMinimalEventList< DalitzEvent > &data)
double _totalMCWeight
Definition: Chi2Binning.h:25
std::vector< T >::iterator begin()
virtual EVENT_TYPE getEvent(unsigned int i) const =0
static int __Ncol
Definition: Chi2Binning.h:28
static int * getColourPalette()
Definition: Chi2Binning.cpp:76
virtual const DalitzEventPattern & eventPattern() const =0
DalitzHistoStackSet getMCHistoStack()
virtual void print(std::ostream &os=std::cout) const =0
int numBins() const
unsigned int size() const
std::vector< Chi2BoxSet > _boxSets
Definition: Chi2Binning.h:22
void setColourPalette(int nCol, int *pal, double max, double min=0.000001)
void print(std::ostream &os=std::cout) const
DalitzHistoStackSet getDataHistoStack()
void sortByChi2()
void setFas(IFastAmplitudeIntegrable *fas)
int nData() const
Definition: Chi2Box.cpp:109
virtual unsigned int size() const =0
int mergeBoxes(Chi2BoxSet &boxes, int minPerBin)
void print(std::ostream &os=std::cout) const
double normFactor() const
virtual double getVal_noPs(IDalitzEvent &evt)=0
bool operator()(const Chi2Box &a, const Chi2Box &b) const