CMS 3D CMS Logo

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