CMS 3D CMS Logo

IntegralOverPhiFunction.cc
Go to the documentation of this file.
2 
3 // -*- C++ -*-
4 //
5 // Package: IntegralOverPhiFunction
6 // Class: IntegralOverPhiFunction
7 //
16 //
17 // Original Author: Christian Veelken, UC Davis
18 // Created: Thu Nov 2 13:47:40 CST 2006
19 //
20 //
21 
22 // system include files
23 #include <iostream>
24 #include <iomanip>
25 #include <vector>
26 
27 // ROOT include files
28 #include <TMath.h>
29 
30 // CMSSW include files
32 
34 
35 //
36 // declaration of auxiliary functions
37 //
38 
39 void checkSolutions(unsigned int i, unsigned int& numSolution1, unsigned int& numSolution2, unsigned int& numSolution3, unsigned int& numSolution4);
40 
41 //
42 // constructors and destructor
43 //
44 
46  : ROOT::Math::ParamFunction<ROOT::Math::IParametricGradFunctionOneDim>(3)
47 {
48  theta0_ = 0.;
49  phi0_ = 0.;
50  alpha_ = 0.;
51 
52 // !!! ONLY FOR TESTING
53  numSolutionMin1_ = 0;
54  numSolutionMax1_ = 0;
55  numSolutionMin2_ = 0;
56  numSolutionMax2_ = 0;
57  numSolutionMin3_ = 0;
58  numSolutionMax3_ = 0;
59  numSolutionMin4_ = 0;
60  numSolutionMax4_ = 0;
61 // FOR TESTING ONLY !!!
62 }
63 
65 {
66 // !!! ONLY FOR TESTING
67  if ( debugLevel_ > 0 ) {
68  edm::LogVerbatim("") << "<IntegralOverPhiFunction::~IntegralOverPhiFunction>:" << std::endl
69  << " numSolutionMin1 = " << numSolutionMin1_ << std::endl
70  << " numSolutionMax1 = " << numSolutionMax1_ << std::endl
71  << " numSolutionMin2 = " << numSolutionMin2_ << std::endl
72  << " numSolutionMax2 = " << numSolutionMax2_ << std::endl
73  << " numSolutionMin3 = " << numSolutionMin3_ << std::endl
74  << " numSolutionMax3 = " << numSolutionMax3_ << std::endl
75  << " numSolutionMin4 = " << numSolutionMin4_ << std::endl
76  << " numSolutionMax4 = " << numSolutionMax4_ << std::endl;
77  }
78 // FOR TESTING ONLY !!!
79 }
80 
81 //
82 // member functions
83 //
84 
86 {
87  theta0_ = theta0;
88 }
89 
91 {
92  phi0_ = normalizedPhi(phi0); // map azimuth angle into interval [-pi,+pi]
93 }
94 
96 {
97  alpha_ = alpha;
98 }
99 
100 void IntegralOverPhiFunction::SetParameters(const double* param)
101 {
102  theta0_ = param[0];
103  phi0_ = param[1];
104  alpha_ = param[2];
105 }
106 
107 double IntegralOverPhiFunction::DoEvalPar(double x, const double* param) const //FIXME: in the current implementation const is not entirely true
108 {
109  theta0_ = param[0];
110  phi0_ = param[1];
111  alpha_ = param[2];
112 
113  return DoEval(x);
114 }
115 
116 
117 
118 double IntegralOverPhiFunction::DoEval(double x) const
119 {
120 //--- return zero if theta either close to zero or close to Pi
121 // (phi not well-defined in that case;
122 // numerical expressions might become "NaN"s)
123  const double epsilon = 1.e-3;
124  if ( x < epsilon || x > (TMath::Pi() - epsilon) ) return 0.;
125 
126 //--- calculate trigonometric expressions
127 // (dependend on angle theta0;
128 // polar angle of cone axis);
129 // avoid theta0 exactly zero or exactly Pi
130 // (numerical expressions become "NaN"s)
131  double theta0 = theta0_;
132  if ( theta0 < epsilon ) theta0 = epsilon;
133  if ( theta0 > (TMath::Pi() - epsilon)) theta0 = (TMath::Pi() - epsilon);
134  double cosTheta0 = TMath::Cos(theta0);
135  double cos2Theta0 = TMath::Cos(2*theta0);
136  double sinTheta0 = TMath::Sin(theta0);
137  double cotTheta0 = 1./TMath::Tan(theta0);
138  double cscTheta0 = 1./TMath::Sin(theta0);
139 // (dependend on angle phi0;
140 // azimuth angle of cone axis)
141  double cosPhi0 = TMath::Cos(phi0_);
142  double tanPhi0 = TMath::Tan(phi0_);
143 // (dependend on angle theta;
144 // polar angle of point within cone)
145  double cosTheta = TMath::Cos(x);
146  double cos2Theta = TMath::Cos(2*x);
147  double sinTheta = TMath::Sin(x);
148  double cotTheta = 1./TMath::Tan(x);
149  double cscTheta = 1./TMath::Sin(x);
150 // (dependent on angle alpha;
151 // opening angle of cone, measured from cone axis)
152  double cosAlpha = TMath::Cos(alpha_);
153 
154  double s = -cosPhi0*cosPhi0*(2*cosAlpha*cosAlpha + cos2Theta - 4*cosAlpha*cosTheta*cosTheta0 + cos2Theta0)*sinTheta*sinTheta*sinTheta0*sinTheta0;
155 
156 //--- return either zero or 2 Pi
157 // in case argument of square-root is zero or negative
158 // (negative values solely arise from rounding errors);
159 // check whether to return zero or 2 Pi:
160 // o return zero
161 // if |theta- theta0| > alpha,
162 // (theta outside cone of opening angle alpha, so vanishing integral over phi)
163 // o return 2 Pi
164 // if |theta- theta0| < alpha
165 // (theta within cone of opening angle alpha;
166 // actually theta0 < alpha in forward/backward direction,
167 // so that integral includes all phi values, hence yielding 2 Pi)
168  if ( s <= 0 ) {
169  if ( TMath::Abs(x - theta0) > alpha_ ) return 0;
170  if ( TMath::Abs(x - theta0) <= alpha_ ) return 2*TMath::Pi();
171  std::cerr << "Error in <IntegralOverPhiFunction::operator()>: failed to compute return value !" << std::endl;
172  }
173 
174  double r = (1./TMath::Sqrt(2.))*(cscTheta*cscTheta*cscTheta0*cscTheta0*TMath::Sqrt(s)*tanPhi0);
175  double t = cosPhi0*(-cotTheta*cotTheta0 + cosAlpha*cscTheta*cscTheta0);
176 
177  double phi[4];
178  phi[0] = -TMath::ACos(t - r);
179  phi[1] = TMath::ACos(t - r);
180  phi[2] = -TMath::ACos(t + r);
181  phi[3] = TMath::ACos(t + r);
182 
183  if ( debugLevel_ > 0 ) {
184  edm::LogVerbatim("") << "phi0 = " << phi0_ << std::endl
185  << "phi[0] = " << phi[0] << " (phi[0] - phi0 = " << (phi[0] - phi0_)*180/TMath::Pi() << ")" << std::endl
186  << "phi[1] = " << phi[1] << " (phi[1] - phi0 = " << (phi[1] - phi0_)*180/TMath::Pi() << ")" << std::endl
187  << "phi[2] = " << phi[2] << " (phi[2] - phi0 = " << (phi[2] - phi0_)*180/TMath::Pi() << ")" << std::endl
188  << "phi[3] = " << phi[3] << " (phi[3] - phi0 = " << (phi[3] - phi0_)*180/TMath::Pi() << ")" << std::endl;
189  }
190 
191  double phiMin = 0.;
192  double phiMax = 0.;
193  for ( unsigned int i = 0; i < 4; ++i ) {
194  for ( unsigned int j = (i + 1); j < 4; ++j ) {
195 //--- search for the two solutions for phi
196 // that have an equal distance to phi0
197 // and are on either side
198  double dPhi_i = phi[i] - phi0_;
199  double dPhi_j = phi0_ - phi[j];
200  if ( TMath::Abs(normalizedPhi(dPhi_i - dPhi_j)) < epsilon ) { // map difference in azimuth angle into interval [-pi,+pi] and require it to be negligible
201  //if ( TMath::Abs((phi[i] - phi0_) - (phi0_ - phi[j])) < epsilon ) { // map difference in azimuth angle into interval [-pi,+pi] and require it to be negligible
202  phiMin = TMath::Min(phi[i], phi[j]);
203  phiMax = TMath::Max(phi[i], phi[j]);
204 
205 // !!! ONLY FOR TESTING
210 // FOR TESTING ONLY !!!
211  }
212  }
213  }
214 
215  if ( phiMin == 0 && phiMax == 0 ) {
216  edm::LogError("") << "failed to compute Return Value !" << std::endl;
217  }
218 
219  return TMath::Abs(normalizedPhi(phi0_ - phiMin)) + TMath::Abs(normalizedPhi(phiMax - phi0_));
220 }
221 
223 {
224 //--- virtual function inherited from ROOT::Math::ParamFunction base class;
225 // not implemented, because not neccessary, but needs to be defined to make code compile...
226  edm::LogWarning("") << "Function not implemented yet !" << std::endl;
227 
228  return 0.;
229 }
230 
231 double IntegralOverPhiFunction::DoParameterDerivative(double, const double*, unsigned int) const
232 {
233 //--- virtual function inherited from ROOT::Math::ParamFunction base class;
234 // not implemented, because not neccessary, but needs to be defined to make code compile...
235  edm::LogWarning("") << "Function not implemented yet !" << std::endl;
236 
237  return 0.;
238 }
239 
240 void IntegralOverPhiFunction::DoParameterGradient(double x, double* paramGradient) const
241 {
242 //--- virtual function inherited from ROOT::Math::ParamFunction base class;
243 // not implemented, because not neccessary, but needs to be defined to make code compile...
244  edm::LogWarning("") << "Function not implemented yet !" << std::endl;
245 }
246 
247 //
248 // definition of auxiliary functions
249 //
250 
251 void checkSolutions(unsigned int i, unsigned int& numSolution1, unsigned int& numSolution2, unsigned int& numSolution3, unsigned int& numSolution4)
252 {
253  switch ( i ) {
254  case 0 :
255  ++numSolution1;
256  break;
257  case 1 :
258  ++numSolution2;
259  break;
260  case 2 :
261  ++numSolution3;
262  break;
263  case 3 :
264  ++numSolution4;
265  break;
266  }
267 }
const double Pi
void SetParameters(double const *param) override
float alpha
Definition: AMPTWrapper.h:95
T Min(T a, T b)
Definition: MathUtil.h:39
void checkSolutions(unsigned int i, unsigned int &numSolution1, unsigned int &numSolution2, unsigned int &numSolution3, unsigned int &numSolution4)
void SetParameterAlpha(double alpha)
T Abs(T a)
Definition: MathUtil.h:49
double DoDerivative(double x) const
virtual double DoEvalPar(double x, const double *param) const override
T Max(T a, T b)
Definition: MathUtil.h:44
static const unsigned int debugLevel_
double DoEval(double x) const override
void DoParameterGradient(double x, double *paramGradient) const
virtual double DoParameterDerivative(double, const double *, unsigned int) const override
T normalizedPhi(T phi)
Definition: normalizedPhi.h:9
void SetParameterTheta0(double theta0)