CMS 3D CMS Logo

SymmetryFit.cc
Go to the documentation of this file.
2 #include <cmath>
3 #include <cassert>
4 #include <memory>
5 
7  const std::vector<TH1*>& candidates,
8  const std::pair<unsigned, unsigned> range) {
9  TH1* fake = (TH1*)(candidates[0]->Clone(basename.c_str()));
10  fake->Reset();
11  SymmetryFit combined(fake, range);
12  delete fake;
13 
14  for (auto const* candidate : candidates) {
15  SymmetryFit sf(candidate, range);
16  combined += sf;
17  delete sf.chi2_;
18  }
19 
20  int status = combined.fit();
21  if (status) {
22  delete combined.chi2_;
23  combined.chi2_ = nullptr;
24  }
25  return combined.chi2_;
26 }
27 
28 TH1* SymmetryFit::symmetryChi2(const TH1* candidate, const std::pair<unsigned, unsigned> range) {
29  SymmetryFit sf(candidate, range);
30  int status = sf.fit();
31  if (status) {
32  delete sf.chi2_;
33  sf.chi2_ = nullptr;
34  }
35  return sf.chi2_;
36 }
37 
38 SymmetryFit::SymmetryFit(const TH1* h, const std::pair<unsigned, unsigned> r)
39  : symm_candidate_(h),
40  minDF_(r.second - r.first),
41  range_(r),
42  minmaxUsable_(findUsableMinMax()),
43  ndf_(minmaxUsable_.first < minmaxUsable_.second ? minmaxUsable_.second - minmaxUsable_.first : 0),
44  chi2_(nullptr) {
46  fillchi2();
47 }
48 
50  std::string XXname = name(symm_candidate_->GetName());
51  unsigned Nbins = 2 * (range_.second - range_.first) + 1;
52  double binwidth = symm_candidate_->GetBinWidth(1);
53  double low = symm_candidate_->GetBinCenter(range_.first) - 3 * binwidth / 4;
54  double up = symm_candidate_->GetBinCenter(range_.second - 1) + 3 * binwidth / 4;
55  chi2_ = new TH1F(XXname.c_str(), "", Nbins, low, up);
56 }
57 
58 std::pair<unsigned, unsigned> SymmetryFit::findUsableMinMax() const {
59  unsigned NEAR(0), FAR(0);
60  const std::vector<std::pair<unsigned, unsigned> > cont = continuousRanges();
61  for (unsigned L = 0; L < cont.size(); L++) {
62  if (cont[L].first > range_.first)
63  continue;
64  for (unsigned R = L; R < cont.size(); R++) {
65  if (cont[R].second < range_.second)
66  continue;
67 
68  const unsigned far = std::min(range_.first - cont[L].first, cont[R].second - range_.second);
69  const unsigned near = std::max(range_.second < cont[L].second ? 0 : range_.second - cont[L].second,
70  cont[R].first < range_.first ? 0 : cont[R].first - range_.first);
71 
72  if ((far > near) && (far - near) > (FAR - NEAR)) {
73  FAR = far;
74  NEAR = near;
75  }
76  }
77  }
78  return std::make_pair(NEAR, FAR);
79 }
80 
81 std::vector<std::pair<unsigned, unsigned> > SymmetryFit::continuousRanges() const {
82  std::vector<std::pair<unsigned, unsigned> > ranges;
83  const unsigned Nbins = symm_candidate_->GetNbinsX();
84  unsigned i = 0;
85  while (++i <= Nbins) {
86  if (symm_candidate_->GetBinError(i)) {
87  std::pair<unsigned, unsigned> range(i, i + 1);
88  while (++i <= Nbins && symm_candidate_->GetBinError(i))
89  range.second++;
90  ranges.push_back(range);
91  }
92  }
93  return ranges;
94 }
95 
97  if (ndf_ < minDF_)
98  return;
99 
100  for (int i = 1; i <= chi2_->GetNbinsX(); ++i) {
101  const unsigned L(range_.first - 1 + (i - 1) / 2), R(range_.first + i / 2);
102  chi2_->SetBinContent(i, chi2(std::make_pair(L, R)));
103  }
104 }
105 
106 float SymmetryFit::chi2(std::pair<unsigned, unsigned> point) {
107  point.first -= minmaxUsable_.first;
108  point.second += minmaxUsable_.first;
109  float XX = 0;
110  unsigned i = ndf_;
111  while (i-- > 0) {
112  XX += chi2_element(point);
113  point.first--;
114  point.second++;
115  }
116  return XX;
117 }
118 
119 float SymmetryFit::chi2_element(std::pair<unsigned, unsigned> range) {
120  float y0(symm_candidate_->GetBinContent(range.first)), y1(symm_candidate_->GetBinContent(range.second)),
121  e0(symm_candidate_->GetBinError(range.first)), e1(symm_candidate_->GetBinError(range.second));
122  assert(e0 && e1);
123 
124  return pow(y0 - y1, 2) / (e0 * e0 + e1 * e1);
125 }
126 
128  std::vector<double> p = pol2_from_pol3(chi2_);
129  if (p.empty() || p[0] < chi2_->GetBinCenter(1) || p[0] > chi2_->GetBinCenter(chi2_->GetNbinsX()))
130  return 7;
131 
132  std::unique_ptr<TF1> f(fitfunction());
133  f->SetParameter(0, p[0]);
134  f->SetParLimits(0, p[0], p[0]);
135  f->SetParameter(1, p[1]);
136  f->SetParLimits(1, p[1], p[1]);
137  f->SetParameter(2, p[2]);
138  f->SetParLimits(2, p[2], p[2]);
139  f->SetParameter(3, ndf_);
140  f->SetParLimits(3, ndf_, ndf_); //Fixed
141  chi2_->Fit(f.get(), "WQ");
142  return 0;
143 }
144 
146  TF1* f = new TF1("SymmetryFit", "((x-[0])/[1])**2+[2]+0*[3]");
147  f->SetParName(0, "middle");
148  f->SetParName(1, "uncertainty");
149  f->SetParName(2, "chi2");
150  f->SetParName(3, "NDF");
151  return f;
152 }
153 
154 std::vector<double> SymmetryFit::pol2_from_pol2(TH1* hist) {
155  std::vector<double> v;
156 
157  //Need our own copy for thread safety
158  TF1 func("mypol2", "pol2");
159  int status = hist->Fit(&func, "WQ");
160  if (!status) {
161  std::vector<double> p;
162  p.push_back(func.GetParameter(0));
163  p.push_back(func.GetParameter(1));
164  p.push_back(func.GetParameter(2));
165  if (p[2] > 0) {
166  v.push_back(-0.5 * p[1] / p[2]);
167  v.push_back(1. / sqrt(p[2]));
168  v.push_back(p[0] - 0.25 * p[1] * p[1] / p[2]);
169  }
170  }
171  return v;
172 }
173 
174 std::vector<double> SymmetryFit::pol2_from_pol3(TH1* hist) {
175  std::vector<double> v;
176 
177  auto func = std::make_unique<TF1>("mypol3", "pol3");
178  int status = hist->Fit(func.get(), "WQ");
179  if (!status) {
180  std::vector<double> p;
181  p.push_back(func->GetParameter(0));
182  p.push_back(func->GetParameter(1));
183  p.push_back(func->GetParameter(2));
184  p.push_back(func->GetParameter(3));
185  double radical = p[2] * p[2] - 3 * p[1] * p[3];
186  if (radical > 0) {
187  double x0 = (-p[2] + sqrt(radical)) / (3 * p[3]);
188  v.push_back(x0);
189  v.push_back(pow(radical, -0.25));
190  v.push_back(p[0] + p[1] * x0 + p[2] * x0 * x0 + p[3] * x0 * x0 * x0);
191  }
192  }
193  return v;
194 }
Definition: BitonicSort.h:7
SymmetryFit(const TH1 *, const std::pair< unsigned, unsigned >)
Definition: SymmetryFit.cc:38
static std::string name(std::string base)
Definition: SymmetryFit.h:12
constexpr int pow(int x)
Definition: conifer.h:24
static std::vector< double > pol2_from_pol2(TH1 *hist)
Definition: SymmetryFit.cc:154
std::pair< unsigned, unsigned > findUsableMinMax() const
Definition: SymmetryFit.cc:58
assert(be >=bs)
float chi2_element(std::pair< unsigned, unsigned >)
Definition: SymmetryFit.cc:119
TH1 * chi2_
Definition: SymmetryFit.h:36
U second(std::pair< T, U > const &p)
unsigned ndf_
Definition: SymmetryFit.h:35
static std::vector< double > pol2_from_pol3(TH1 *hist)
Definition: SymmetryFit.cc:174
std::vector< std::pair< unsigned, unsigned > > continuousRanges() const
Definition: SymmetryFit.cc:81
T sqrt(T t)
Definition: SSEVec.h:19
float chi2(std::pair< unsigned, unsigned >)
Definition: SymmetryFit.cc:106
static TF1 * fitfunction()
Definition: SymmetryFit.cc:145
double f[11][100]
string ranges
Definition: diffTwoXMLs.py:79
const TH1 * symm_candidate_
Definition: SymmetryFit.h:32
static TH1 * symmetryChi2(std::string, const std::vector< TH1 *> &, const std::pair< unsigned, unsigned >)
Definition: SymmetryFit.cc:6
void fillchi2()
Definition: SymmetryFit.cc:96
const unsigned minDF_
Definition: SymmetryFit.h:33
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
const std::pair< unsigned, unsigned > minmaxUsable_
Definition: SymmetryFit.h:34
const std::pair< unsigned, unsigned > range_
Definition: SymmetryFit.h:34
cont
load Luminosity info ##
Definition: generateEDF.py:628
*vegas h *****************************************************used in the default bin number in original ***version of VEGAS is ***a higher bin number might help to derive a more precise ***grade subtle point
Definition: invegas.h:5
void makeChi2Histogram()
Definition: SymmetryFit.cc:49