00001 #include "PhysicsTools/IsolationUtils/interface/IntegralOverPhiFunction.h"
00002
00003
00004
00005
00006
00007
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <iostream>
00025 #include <iomanip>
00026 #include <vector>
00027
00028
00029 #include <TMath.h>
00030
00031
00032 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00033
00034 #include "DataFormats/Math/interface/normalizedPhi.h"
00035
00036
00037
00038
00039
00040 void checkSolutions(unsigned int i, unsigned int& numSolution1, unsigned int& numSolution2, unsigned int& numSolution3, unsigned int& numSolution4);
00041
00042
00043
00044
00045
00046 IntegralOverPhiFunction::IntegralOverPhiFunction()
00047 : ROOT::Math::ParamFunction(3)
00048 {
00049 theta0_ = 0.;
00050 phi0_ = 0.;
00051 alpha_ = 0.;
00052
00053
00054 numSolutionMin1_ = 0;
00055 numSolutionMax1_ = 0;
00056 numSolutionMin2_ = 0;
00057 numSolutionMax2_ = 0;
00058 numSolutionMin3_ = 0;
00059 numSolutionMax3_ = 0;
00060 numSolutionMin4_ = 0;
00061 numSolutionMax4_ = 0;
00062
00063 }
00064
00065 IntegralOverPhiFunction::~IntegralOverPhiFunction()
00066 {
00067
00068 if ( debugLevel_ > 0 ) {
00069 edm::LogVerbatim("") << "<IntegralOverPhiFunction::~IntegralOverPhiFunction>:" << std::endl
00070 << " numSolutionMin1 = " << numSolutionMin1_ << std::endl
00071 << " numSolutionMax1 = " << numSolutionMax1_ << std::endl
00072 << " numSolutionMin2 = " << numSolutionMin2_ << std::endl
00073 << " numSolutionMax2 = " << numSolutionMax2_ << std::endl
00074 << " numSolutionMin3 = " << numSolutionMin3_ << std::endl
00075 << " numSolutionMax3 = " << numSolutionMax3_ << std::endl
00076 << " numSolutionMin4 = " << numSolutionMin4_ << std::endl
00077 << " numSolutionMax4 = " << numSolutionMax4_ << std::endl;
00078 }
00079
00080 }
00081
00082
00083
00084
00085
00086 void IntegralOverPhiFunction::SetParameterTheta0(double theta0)
00087 {
00088 theta0_ = theta0;
00089 }
00090
00091 void IntegralOverPhiFunction::SetParameterPhi0(double phi0)
00092 {
00093 phi0_ = normalizedPhi(phi0);
00094 }
00095
00096 void IntegralOverPhiFunction::SetParameterAlpha(double alpha)
00097 {
00098 alpha_ = alpha;
00099 }
00100
00101 void IntegralOverPhiFunction::SetParameters(double* param)
00102 {
00103 theta0_ = param[0];
00104 phi0_ = param[1];
00105 alpha_ = param[2];
00106 }
00107
00108 double IntegralOverPhiFunction::DoEval(double x) const
00109 {
00110
00111
00112
00113 const double epsilon = 1.e-3;
00114 if ( x < epsilon || x > (TMath::Pi() - epsilon) ) return 0.;
00115
00116
00117
00118
00119
00120
00121 double theta0 = theta0_;
00122 if ( theta0 < epsilon ) theta0 = epsilon;
00123 if ( theta0 > (TMath::Pi() - epsilon)) theta0 = (TMath::Pi() - epsilon);
00124 double cosTheta0 = TMath::Cos(theta0);
00125 double cos2Theta0 = TMath::Cos(2*theta0);
00126 double sinTheta0 = TMath::Sin(theta0);
00127 double cotTheta0 = 1./TMath::Tan(theta0);
00128 double cscTheta0 = 1./TMath::Sin(theta0);
00129
00130
00131 double cosPhi0 = TMath::Cos(phi0_);
00132 double tanPhi0 = TMath::Tan(phi0_);
00133
00134
00135 double cosTheta = TMath::Cos(x);
00136 double cos2Theta = TMath::Cos(2*x);
00137 double sinTheta = TMath::Sin(x);
00138 double cotTheta = 1./TMath::Tan(x);
00139 double cscTheta = 1./TMath::Sin(x);
00140
00141
00142 double cosAlpha = TMath::Cos(alpha_);
00143
00144 double s = -cosPhi0*cosPhi0*(2*cosAlpha*cosAlpha + cos2Theta - 4*cosAlpha*cosTheta*cosTheta0 + cos2Theta0)*sinTheta*sinTheta*sinTheta0*sinTheta0;
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 if ( s <= 0 ) {
00159 if ( TMath::Abs(x - theta0) > alpha_ ) return 0;
00160 if ( TMath::Abs(x - theta0) <= alpha_ ) return 2*TMath::Pi();
00161 std::cerr << "Error in <IntegralOverPhiFunction::operator()>: failed to compute return value !" << std::endl;
00162 }
00163
00164 double r = (1./TMath::Sqrt(2.))*(cscTheta*cscTheta*cscTheta0*cscTheta0*TMath::Sqrt(s)*tanPhi0);
00165 double t = cosPhi0*(-cotTheta*cotTheta0 + cosAlpha*cscTheta*cscTheta0);
00166
00167 double phi[4];
00168 phi[0] = -TMath::ACos(t - r);
00169 phi[1] = TMath::ACos(t - r);
00170 phi[2] = -TMath::ACos(t + r);
00171 phi[3] = TMath::ACos(t + r);
00172
00173 if ( debugLevel_ > 0 ) {
00174 edm::LogVerbatim("") << "phi0 = " << phi0_ << std::endl
00175 << "phi[0] = " << phi[0] << " (phi[0] - phi0 = " << (phi[0] - phi0_)*180/TMath::Pi() << ")" << std::endl
00176 << "phi[1] = " << phi[1] << " (phi[1] - phi0 = " << (phi[1] - phi0_)*180/TMath::Pi() << ")" << std::endl
00177 << "phi[2] = " << phi[2] << " (phi[2] - phi0 = " << (phi[2] - phi0_)*180/TMath::Pi() << ")" << std::endl
00178 << "phi[3] = " << phi[3] << " (phi[3] - phi0 = " << (phi[3] - phi0_)*180/TMath::Pi() << ")" << std::endl;
00179 }
00180
00181 double phiMin = 0.;
00182 double phiMax = 0.;
00183 for ( unsigned int i = 0; i < 4; ++i ) {
00184 for ( unsigned int j = (i + 1); j < 4; ++j ) {
00185
00186
00187
00188 double dPhi_i = phi[i] - phi0_;
00189 double dPhi_j = phi0_ - phi[j];
00190 if ( TMath::Abs(normalizedPhi(dPhi_i - dPhi_j)) < epsilon ) {
00191
00192 phiMin = TMath::Min(phi[i], phi[j]);
00193 phiMax = TMath::Max(phi[i], phi[j]);
00194
00195
00196 if ( phi[i] == phiMin ) checkSolutions(i, numSolutionMin1_, numSolutionMin2_, numSolutionMin3_, numSolutionMin4_);
00197 if ( phi[i] == phiMax ) checkSolutions(i, numSolutionMax1_, numSolutionMax2_, numSolutionMax3_, numSolutionMax4_);
00198 if ( phi[j] == phiMin ) checkSolutions(j, numSolutionMin1_, numSolutionMin2_, numSolutionMin3_, numSolutionMin4_);
00199 if ( phi[j] == phiMax ) checkSolutions(j, numSolutionMax1_, numSolutionMax2_, numSolutionMax3_, numSolutionMax4_);
00200
00201 }
00202 }
00203 }
00204
00205 if ( phiMin == 0 && phiMax == 0 ) {
00206 edm::LogError("") << "failed to compute Return Value !" << std::endl;
00207 }
00208
00209 return TMath::Abs(normalizedPhi(phi0_ - phiMin)) + TMath::Abs(normalizedPhi(phiMax - phi0_));
00210 }
00211
00212 double IntegralOverPhiFunction::DoDerivative(double x) const
00213 {
00214
00215
00216 edm::LogWarning("") << "Function not implemented yet !" << std::endl;
00217
00218 return 0.;
00219 }
00220
00221 void IntegralOverPhiFunction::DoParameterGradient(double x, double* paramGradient) const
00222 {
00223
00224
00225 edm::LogWarning("") << "Function not implemented yet !" << std::endl;
00226 }
00227
00228
00229
00230
00231
00232 void checkSolutions(unsigned int i, unsigned int& numSolution1, unsigned int& numSolution2, unsigned int& numSolution3, unsigned int& numSolution4)
00233 {
00234 switch ( i ) {
00235 case 0 :
00236 ++numSolution1;
00237 break;
00238 case 1 :
00239 ++numSolution2;
00240 break;
00241 case 2 :
00242 ++numSolution3;
00243 break;
00244 case 3 :
00245 ++numSolution4;
00246 break;
00247 }
00248 }