File indexing completed on 2024-04-06 12:31:31
0001 #include "TrackingTools/GsfTracking/interface/GsfBetheHeitlerUpdator.h"
0002
0003 #include "DataFormats/GeometrySurface/interface/MediumProperties.h"
0004 #include "FWCore/ParameterSet/interface/FileInPath.h"
0005 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0006
0007 #include <string>
0008 #include <fstream>
0009 #include <cmath>
0010
0011 #include <cassert>
0012
0013 namespace {
0014
0015 inline float logisticFunction(const float x) { return 1. / (1. + unsafe_expf<4>(-x)); }
0016
0017 inline float BetheHeitlerMean(const float rl) { return unsafe_expf<4>(-rl); }
0018
0019 inline float BetheHeitlerVariance(const float rl) {
0020 #if defined(__clang__) || defined(__INTEL_COMPILER)
0021 const
0022 #else
0023 constexpr
0024 #endif
0025 float l3ol2 = std::log(3.) / std::log(2.);
0026 float mean = BetheHeitlerMean(rl);
0027 return unsafe_expf<4>(-rl * l3ol2) - mean * mean;
0028 }
0029 }
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 GsfBetheHeitlerUpdator::GsfBetheHeitlerUpdator(const std::string fileName, const int correctionFlag)
0054 : GsfMaterialEffectsUpdator(0.000511, 6), theNrComponents(0), theCorrectionFlag(correctionFlag) {
0055 if (theCorrectionFlag == 1)
0056 edm::LogInfo("GsfBetheHeitlerUpdator") << "1st moment of mixture will be corrected";
0057 if (theCorrectionFlag >= 2)
0058 edm::LogInfo("GsfBetheHeitlerUpdator") << "1st and 2nd moments of mixture will be corrected";
0059
0060 readParameters(fileName);
0061 assert(theNrComponents <= 6);
0062 resize(theNrComponents);
0063 }
0064
0065 void GsfBetheHeitlerUpdator::readParameters(const std::string fileName) {
0066 std::string name = "TrackingTools/GsfTracking/data/";
0067 name += fileName;
0068
0069 edm::FileInPath parFile(name);
0070 edm::LogInfo("GsfBetheHeitlerUpdator") << "Reading GSF parameterization "
0071 << "of Bethe-Heitler energy loss from " << parFile.fullPath();
0072 std::ifstream ifs(parFile.fullPath().c_str());
0073
0074 ifs >> theNrComponents;
0075 int orderP;
0076 ifs >> orderP;
0077 ifs >> theTransformationCode;
0078
0079 assert(orderP < MaxOrder);
0080
0081 for (int ic = 0; ic != theNrComponents; ++ic) {
0082 thePolyWeights[ic] = readPolynomial(ifs, orderP);
0083 thePolyMeans[ic] = readPolynomial(ifs, orderP);
0084 thePolyVars[ic] = readPolynomial(ifs, orderP);
0085 }
0086 }
0087
0088 GsfBetheHeitlerUpdator::Polynomial GsfBetheHeitlerUpdator::readPolynomial(std::ifstream& aStream,
0089 const unsigned int order) {
0090 float coeffs[order + 1];
0091 for (unsigned int i = 0; i < (order + 1); ++i)
0092 aStream >> coeffs[i];
0093 return Polynomial(coeffs, order + 1);
0094 }
0095
0096 void GsfBetheHeitlerUpdator::compute(const TrajectoryStateOnSurface& TSoS,
0097 const PropagationDirection propDir,
0098 Effect effects[]) const {
0099
0100
0101
0102 const Surface& surface = TSoS.surface();
0103
0104
0105
0106 float rl(0.f);
0107 float p(0.f);
0108 if (surface.mediumProperties().isValid()) {
0109 LocalVector pvec = TSoS.localMomentum();
0110 p = pvec.mag();
0111 rl = surface.mediumProperties().radLen() / fabs(pvec.z()) * p;
0112 }
0113
0114
0115
0116 if (rl > 0.0001f) {
0117
0118
0119
0120
0121 if (rl < 0.01f)
0122 rl = 0.01f;
0123 if (rl > 0.20f)
0124 rl = 0.20f;
0125
0126 float mixtureData[3][theNrComponents];
0127 GSContainer mixture{mixtureData[0], mixtureData[1], mixtureData[2]};
0128
0129 getMixtureParameters(rl, mixture);
0130 correctWeights(mixture);
0131 if (theCorrectionFlag >= 1)
0132 mixture.second[0] = correctedFirstMean(rl, mixture);
0133 if (theCorrectionFlag >= 2)
0134 mixture.third[0] = correctedFirstVar(rl, mixture);
0135
0136 for (int i = 0; i < theNrComponents; i++) {
0137 float varPinv;
0138 effects[i].weight *= mixture.first[i];
0139 if (propDir == alongMomentum) {
0140
0141
0142
0143
0144 effects[i].deltaP += p * (mixture.second[i] - 1.f);
0145
0146
0147 float f = 1.f / (p * mixture.second[i]);
0148 varPinv = f * f * mixture.third[i];
0149 } else {
0150
0151
0152
0153
0154 effects[i].deltaP += p * (1.f / mixture.second[i] - 1.f);
0155 varPinv = mixture.third[i] / (p * p);
0156 }
0157 using namespace materialEffect;
0158 effects[i].deltaCov[elos] += varPinv;
0159 }
0160 }
0161 }
0162
0163
0164
0165 void GsfBetheHeitlerUpdator::getMixtureParameters(const float rl, GSContainer& mixture) const {
0166 float weight[theNrComponents], z[theNrComponents], vz[theNrComponents];
0167 for (int i = 0; i < theNrComponents; i++) {
0168 weight[i] = thePolyWeights[i](rl);
0169 z[i] = thePolyMeans[i](rl);
0170 vz[i] = thePolyVars[i](rl);
0171 }
0172 if (theTransformationCode)
0173 for (int i = 0; i < theNrComponents; i++) {
0174 mixture.first[i] = logisticFunction(weight[i]);
0175 mixture.second[i] = logisticFunction(z[i]);
0176 mixture.third[i] = unsafe_expf<4>(vz[i]);
0177 ;
0178 }
0179 else
0180 for (int i = 0; i < theNrComponents; i++) {
0181 mixture.first[i] = weight[i];
0182 mixture.second[i] = z[i];
0183 mixture.third[i] = vz[i] * vz[i];
0184 }
0185 }
0186
0187
0188
0189
0190 void GsfBetheHeitlerUpdator::correctWeights(GSContainer& mixture) const {
0191
0192
0193
0194 float wsum(0);
0195 for (int i = 0; i < theNrComponents; i++)
0196 wsum += mixture.first[i];
0197
0198
0199
0200 wsum = 1.f / wsum;
0201 for (int i = 0; i < theNrComponents; i++)
0202 mixture.first[i] *= wsum;
0203 }
0204
0205
0206
0207 float GsfBetheHeitlerUpdator::correctedFirstMean(const float rl, const GSContainer& mixture) const {
0208
0209
0210
0211 float mean = BetheHeitlerMean(rl);
0212 for (int i = 1; i < theNrComponents; i++)
0213 mean -= mixture.first[i] * mixture.second[i];
0214
0215
0216
0217 return std::max(std::min(mean / mixture.first[0], 1.f), 0.f);
0218 }
0219
0220
0221
0222 float GsfBetheHeitlerUpdator::correctedFirstVar(const float rl, const GSContainer& mixture) const {
0223
0224
0225
0226 float var = BetheHeitlerVariance(rl) + BetheHeitlerMean(rl) * BetheHeitlerMean(rl) -
0227 mixture.first[0] * mixture.second[0] * mixture.second[0];
0228 for (int i = 1; i < theNrComponents; i++)
0229 var -= mixture.first[i] * (mixture.second[i] * mixture.second[i] + mixture.third[i]);
0230
0231
0232
0233 return std::max(var / mixture.first[0], 0.f);
0234 }