File indexing completed on 2024-04-06 12:23:32
0001 #include "PhysicsTools/IsolationUtils/interface/IntegralOverPhiFunction.h"
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #include <iostream>
0024 #include <iomanip>
0025 #include <vector>
0026
0027
0028 #include <TMath.h>
0029
0030
0031 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0032
0033 #include "DataFormats/Math/interface/normalizedPhi.h"
0034
0035
0036
0037
0038
0039 void checkSolutions(unsigned int i,
0040 unsigned int& numSolution1,
0041 unsigned int& numSolution2,
0042 unsigned int& numSolution3,
0043 unsigned int& numSolution4);
0044
0045
0046
0047
0048
0049 IntegralOverPhiFunction::IntegralOverPhiFunction()
0050 : ROOT::Math::ParamFunction<ROOT::Math::IParametricGradFunctionOneDim>(3) {
0051 theta0_ = 0.;
0052 phi0_ = 0.;
0053 alpha_ = 0.;
0054
0055
0056 numSolutionMin1_ = 0;
0057 numSolutionMax1_ = 0;
0058 numSolutionMin2_ = 0;
0059 numSolutionMax2_ = 0;
0060 numSolutionMin3_ = 0;
0061 numSolutionMax3_ = 0;
0062 numSolutionMin4_ = 0;
0063 numSolutionMax4_ = 0;
0064
0065 }
0066
0067 IntegralOverPhiFunction::~IntegralOverPhiFunction() {
0068
0069 if (debugLevel_ > 0) {
0070 edm::LogVerbatim("") << "<IntegralOverPhiFunction::~IntegralOverPhiFunction>:" << std::endl
0071 << " numSolutionMin1 = " << numSolutionMin1_ << std::endl
0072 << " numSolutionMax1 = " << numSolutionMax1_ << std::endl
0073 << " numSolutionMin2 = " << numSolutionMin2_ << std::endl
0074 << " numSolutionMax2 = " << numSolutionMax2_ << std::endl
0075 << " numSolutionMin3 = " << numSolutionMin3_ << std::endl
0076 << " numSolutionMax3 = " << numSolutionMax3_ << std::endl
0077 << " numSolutionMin4 = " << numSolutionMin4_ << std::endl
0078 << " numSolutionMax4 = " << numSolutionMax4_ << std::endl;
0079 }
0080
0081 }
0082
0083
0084
0085
0086
0087 void IntegralOverPhiFunction::SetParameterTheta0(double theta0) { theta0_ = theta0; }
0088
0089 void IntegralOverPhiFunction::SetParameterPhi0(double phi0) {
0090 phi0_ = normalizedPhi(phi0);
0091 }
0092
0093 void IntegralOverPhiFunction::SetParameterAlpha(double alpha) { alpha_ = alpha; }
0094
0095 void IntegralOverPhiFunction::SetParameters(const double* param) {
0096 theta0_ = param[0];
0097 phi0_ = param[1];
0098 alpha_ = param[2];
0099 }
0100
0101 double IntegralOverPhiFunction::DoEvalPar(
0102 double x, const double* param) const
0103 {
0104 theta0_ = param[0];
0105 phi0_ = param[1];
0106 alpha_ = param[2];
0107
0108 return DoEval(x);
0109 }
0110
0111 double IntegralOverPhiFunction::DoEval(double x) const {
0112
0113
0114
0115 const double epsilon = 1.e-3;
0116 if (x < epsilon || x > (TMath::Pi() - epsilon))
0117 return 0.;
0118
0119
0120
0121
0122
0123
0124 double theta0 = theta0_;
0125 if (theta0 < epsilon)
0126 theta0 = epsilon;
0127 if (theta0 > (TMath::Pi() - epsilon))
0128 theta0 = (TMath::Pi() - epsilon);
0129 double cosTheta0 = TMath::Cos(theta0);
0130 double cos2Theta0 = TMath::Cos(2 * theta0);
0131 double sinTheta0 = TMath::Sin(theta0);
0132 double cotTheta0 = 1. / TMath::Tan(theta0);
0133 double cscTheta0 = 1. / TMath::Sin(theta0);
0134
0135
0136 double cosPhi0 = TMath::Cos(phi0_);
0137 double tanPhi0 = TMath::Tan(phi0_);
0138
0139
0140 double cosTheta = TMath::Cos(x);
0141 double cos2Theta = TMath::Cos(2 * x);
0142 double sinTheta = TMath::Sin(x);
0143 double cotTheta = 1. / TMath::Tan(x);
0144 double cscTheta = 1. / TMath::Sin(x);
0145
0146
0147 double cosAlpha = TMath::Cos(alpha_);
0148
0149 double s = -cosPhi0 * cosPhi0 *
0150 (2 * cosAlpha * cosAlpha + cos2Theta - 4 * cosAlpha * cosTheta * cosTheta0 + cos2Theta0) * sinTheta *
0151 sinTheta * sinTheta0 * sinTheta0;
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165 if (s <= 0) {
0166 if (TMath::Abs(x - theta0) > alpha_)
0167 return 0;
0168 if (TMath::Abs(x - theta0) <= alpha_)
0169 return 2 * TMath::Pi();
0170 std::cerr << "Error in <IntegralOverPhiFunction::operator()>: failed to compute return value !" << std::endl;
0171 }
0172
0173 double r = (1. / TMath::Sqrt(2.)) * (cscTheta * cscTheta * cscTheta0 * cscTheta0 * TMath::Sqrt(s) * tanPhi0);
0174 double t = cosPhi0 * (-cotTheta * cotTheta0 + cosAlpha * cscTheta * cscTheta0);
0175
0176 double phi[4];
0177 phi[0] = -TMath::ACos(t - r);
0178 phi[1] = TMath::ACos(t - r);
0179 phi[2] = -TMath::ACos(t + r);
0180 phi[3] = TMath::ACos(t + r);
0181
0182 if (debugLevel_ > 0) {
0183 edm::LogVerbatim("") << "phi0 = " << phi0_ << std::endl
0184 << "phi[0] = " << phi[0] << " (phi[0] - phi0 = " << (phi[0] - phi0_) * 180 / TMath::Pi() << ")"
0185 << std::endl
0186 << "phi[1] = " << phi[1] << " (phi[1] - phi0 = " << (phi[1] - phi0_) * 180 / TMath::Pi() << ")"
0187 << std::endl
0188 << "phi[2] = " << phi[2] << " (phi[2] - phi0 = " << (phi[2] - phi0_) * 180 / TMath::Pi() << ")"
0189 << std::endl
0190 << "phi[3] = " << phi[3] << " (phi[3] - phi0 = " << (phi[3] - phi0_) * 180 / TMath::Pi() << ")"
0191 << std::endl;
0192 }
0193
0194 double phiMin = 0.;
0195 double phiMax = 0.;
0196 for (unsigned int i = 0; i < 4; ++i) {
0197 for (unsigned int j = (i + 1); j < 4; ++j) {
0198
0199
0200
0201 double dPhi_i = phi[i] - phi0_;
0202 double dPhi_j = phi0_ - phi[j];
0203 if (TMath::Abs(normalizedPhi(dPhi_i - dPhi_j)) <
0204 epsilon) {
0205
0206 phiMin = TMath::Min(phi[i], phi[j]);
0207 phiMax = TMath::Max(phi[i], phi[j]);
0208
0209
0210 if (phi[i] == phiMin)
0211 checkSolutions(i, numSolutionMin1_, numSolutionMin2_, numSolutionMin3_, numSolutionMin4_);
0212 if (phi[i] == phiMax)
0213 checkSolutions(i, numSolutionMax1_, numSolutionMax2_, numSolutionMax3_, numSolutionMax4_);
0214 if (phi[j] == phiMin)
0215 checkSolutions(j, numSolutionMin1_, numSolutionMin2_, numSolutionMin3_, numSolutionMin4_);
0216 if (phi[j] == phiMax)
0217 checkSolutions(j, numSolutionMax1_, numSolutionMax2_, numSolutionMax3_, numSolutionMax4_);
0218
0219 }
0220 }
0221 }
0222
0223 if (phiMin == 0 && phiMax == 0) {
0224 edm::LogError("") << "failed to compute Return Value !" << std::endl;
0225 }
0226
0227 return TMath::Abs(normalizedPhi(phi0_ - phiMin)) + TMath::Abs(normalizedPhi(phiMax - phi0_));
0228 }
0229
0230 double IntegralOverPhiFunction::DoDerivative(double x) const {
0231
0232
0233 edm::LogWarning("") << "Function not implemented yet !" << std::endl;
0234
0235 return 0.;
0236 }
0237
0238 double IntegralOverPhiFunction::DoParameterDerivative(double, const double*, unsigned int) const {
0239
0240
0241 edm::LogWarning("") << "Function not implemented yet !" << std::endl;
0242
0243 return 0.;
0244 }
0245
0246 void IntegralOverPhiFunction::DoParameterGradient(double x, double* paramGradient) const {
0247
0248
0249 edm::LogWarning("") << "Function not implemented yet !" << std::endl;
0250 }
0251
0252
0253
0254
0255
0256 void checkSolutions(unsigned int i,
0257 unsigned int& numSolution1,
0258 unsigned int& numSolution2,
0259 unsigned int& numSolution3,
0260 unsigned int& numSolution4) {
0261 switch (i) {
0262 case 0:
0263 ++numSolution1;
0264 break;
0265 case 1:
0266 ++numSolution2;
0267 break;
0268 case 2:
0269 ++numSolution3;
0270 break;
0271 case 3:
0272 ++numSolution4;
0273 break;
0274 }
0275 }