CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch12/src/TrackingTools/GsfTracking/src/GsfBetheHeitlerUpdator.cc

Go to the documentation of this file.
00001 #include "TrackingTools/GsfTracking/interface/GsfBetheHeitlerUpdator.h"
00002 
00003 #include "DataFormats/GeometrySurface/interface/MediumProperties.h"
00004 #include "FWCore/ParameterSet/interface/FileInPath.h"
00005 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00006 
00007 #include <string>
00008 #include <fstream>
00009 #include <cmath>
00010 
00011 GsfBetheHeitlerUpdator::GsfBetheHeitlerUpdator(const std::string fileName,
00012                                                const int correctionFlag) :
00013   //                                           const CorrectionFlag correctionFlag) :
00014   GsfMaterialEffectsUpdator(0.000511),
00015   theNrComponents(0),
00016   theCorrectionFlag(correctionFlag),
00017   theLastDz(0.),
00018   theLastP(-1.),
00019   theLastPropDir(alongMomentum),
00020   theLastRadLength(-1.)
00021 {
00022   if ( theCorrectionFlag==1 )
00023     edm::LogInfo("GsfBetheHeitlerUpdator") << "1st moment of mixture will be corrected";
00024   if ( theCorrectionFlag>=2 )
00025     edm::LogInfo("GsfBetheHeitlerUpdator")
00026       << "1st and 2nd moments of mixture will be corrected";
00027 
00028   readParameters(fileName);
00029 }
00030 
00031 void GsfBetheHeitlerUpdator::readParameters (const std::string fileName)
00032 {  
00033   std::string name = "TrackingTools/GsfTracking/data/";
00034   name += fileName;
00035   
00036   edm::FileInPath parFile(name);
00037   edm::LogInfo("GsfBetheHeitlerUpdator") << "Reading GSF parameterization " 
00038                                          << "of Bethe-Heitler energy loss from "
00039                                          << parFile.fullPath();
00040   std::ifstream ifs(parFile.fullPath().c_str());
00041 
00042   ifs >> theNrComponents;
00043   int orderP;
00044   ifs >> orderP;
00045   ifs >> theTransformationCode;
00046   for ( int ic=0; ic<theNrComponents; ic++ ) {
00047     thePolyWeights.push_back(readPolynomial(ifs,orderP));
00048     thePolyMeans.push_back(readPolynomial(ifs,orderP));
00049     thePolyVars.push_back(readPolynomial(ifs,orderP));
00050   }
00051 }
00052 
00053 GsfBetheHeitlerUpdator::Polynomial
00054 GsfBetheHeitlerUpdator::readPolynomial (std::ifstream& aStream, 
00055                                         const int order) {
00056   std::vector<double> coeffs(order+1);
00057   for ( int i=0; i<(order+1); i++ ) aStream >> coeffs[i];
00058   return Polynomial(coeffs);
00059 }
00060 
00061 void
00062 GsfBetheHeitlerUpdator::compute (const TrajectoryStateOnSurface& TSoS,
00063                                  const PropagationDirection propDir) const 
00064 {
00065   //
00066   // clear cache
00067   //
00068   theWeights.clear();
00069   theDeltaPs.clear();
00070   theDeltaCovs.clear();
00071   //
00072   // Get surface and check presence of medium properties
00073   //
00074   const Surface& surface = TSoS.surface();
00075   //
00076   // calculate components: first check associated material constants
00077   //
00078   double rl(0.);
00079   double p(0.);
00080   if ( surface.mediumProperties() ) {
00081     LocalVector pvec = TSoS.localMomentum();
00082     p = pvec.mag();
00083     rl = surface.mediumProperties()->radLen()/fabs(pvec.z())*p;
00084   }
00085   //
00086   // produce multi-state only in case of x/X0>0
00087   //
00088   if ( rl>0.0001 ) {
00089     //
00090     // limit x/x0 to valid range for parametrisation
00091     // should be done in a more elegant way ...
00092     //
00093     if ( rl<0.01 )  rl = 0.01;
00094     if ( rl>0.20 )  rl = 0.20;
00095 
00096     GSContainer mixture;
00097     getMixtureParameters(rl,mixture);
00098     correctWeights(mixture);
00099     if ( theCorrectionFlag>=1 )
00100       mixture[0].second = correctedFirstMean(rl,mixture);
00101     if ( theCorrectionFlag>=2 )
00102       mixture[0].third = correctedFirstVar(rl,mixture);
00103 
00104     for ( int i=0; i<theNrComponents; i++ ) {
00105       double varPinv;
00106       theWeights.push_back(mixture[i].first);
00107       if ( propDir==alongMomentum ) {
00108         //
00109         // for forward propagation: calculate in p (linear in 1/z=p_inside/p_outside),
00110         // then convert sig(p) to sig(1/p). 
00111         //
00112         theDeltaPs.push_back(p*(mixture[i].second-1));
00113         //    double f = 1./p/mixture[i].second/mixture[i].second;
00114         // patch to ensure consistency between for- and backward propagation
00115         double f = 1./p/mixture[i].second;
00116         varPinv = f*f*mixture[i].third;
00117       }
00118       else {
00119         //
00120         // for backward propagation: delta(1/p) is linear in z=p_outside/p_inside
00121         // convert to obtain equivalent delta(p)
00122         //
00123         theDeltaPs.push_back(p*(1/mixture[i].second-1));
00124         varPinv = mixture[i].third/p/p;
00125       }
00126       AlgebraicSymMatrix55 errors;
00127       errors(0,0) = varPinv;
00128       theDeltaCovs.push_back(errors);
00129     }
00130   }
00131   else {
00132     theWeights.push_back(1.);
00133     theDeltaPs.push_back(0.);
00134     theDeltaCovs.push_back(AlgebraicSymMatrix55());
00135   }
00136   //
00137   // Save arguments to avoid duplication of computation
00138   //
00139   storeArguments(TSoS,propDir); 
00140 }
00141 //
00142 // Mixture parameters (in z)
00143 //
00144 void 
00145 GsfBetheHeitlerUpdator::getMixtureParameters (const double rl,
00146                                               GSContainer& mixture) const
00147 {
00148   mixture.clear();
00149   mixture.reserve(theNrComponents);
00150 
00151   for ( int i=0; i<theNrComponents; i++ ) {
00152 
00153     double weight = thePolyWeights[i](rl);
00154     if ( theTransformationCode )  weight = logisticFunction(weight);
00155 
00156     double z = thePolyMeans[i](rl);
00157     if ( theTransformationCode )  z = logisticFunction(z);
00158 
00159     double vz = thePolyVars[i](rl);
00160     if ( theTransformationCode )  vz = exp(vz);
00161     else                          vz = vz*vz;
00162 
00163     mixture.push_back(Triplet<double,double,double>(weight,z,vz));
00164   }
00165 }
00166 
00167 //
00168 // Correct weights
00169 //
00170 void
00171 GsfBetheHeitlerUpdator::correctWeights (GSContainer& mixture) const
00172 {
00173   if ( mixture.empty() )  return;
00174   //
00175   // get sum of weights
00176   //
00177   double wsum(0);
00178   for ( GSContainer::const_iterator i=mixture.begin();
00179         i!=mixture.end(); i++ )  wsum += (*i).first;
00180   //
00181   // rescale to obtain 1
00182   //
00183   for ( GSContainer::iterator i=mixture.begin();
00184         i!=mixture.end(); i++ )  (*i).first /= wsum;
00185 }
00186 //
00187 // Correct means
00188 //
00189 double
00190 GsfBetheHeitlerUpdator::correctedFirstMean (const double rl,
00191                                             const GSContainer& mixture) const
00192 {
00193   if ( mixture.empty() )  return 0.;
00194   //
00195   // calculate difference true mean - weighted sum
00196   //
00197   double mean = BetheHeitlerMean(rl);
00198   for ( GSContainer::const_iterator i=mixture.begin()+1;
00199         i!=mixture.end(); i++ )  mean -= (*i).first*(*i).second;
00200   //
00201   // return corrected mean for first component
00202   //
00203   return std::max(std::min(mean/mixture[0].first,1.),0.);
00204 }
00205 //
00206 // Correct variances
00207 //
00208 double
00209 GsfBetheHeitlerUpdator::correctedFirstVar (const double rl,
00210                                            const GSContainer& mixture) const
00211 {
00212   if ( mixture.empty() )  return 0.;
00213   //
00214   // calculate difference true variance - weighted sum
00215   //
00216   double var = BetheHeitlerVariance(rl) +
00217     BetheHeitlerMean(rl)*BetheHeitlerMean(rl) -
00218     mixture[0].first*mixture[0].second*mixture[0].second;
00219   for ( GSContainer::const_iterator i=mixture.begin()+1;
00220         i!=mixture.end(); i++ )
00221     var -= (*i).first*((*i).second*(*i).second+(*i).third);
00222   //
00223   // return corrected variance for first component
00224   //
00225   return std::max(var/mixture[0].first,0.);
00226 }
00227 
00228 //
00229 // Compare arguments with the ones of the previous call
00230 //
00231 bool 
00232 GsfBetheHeitlerUpdator::newArguments (const TrajectoryStateOnSurface& TSoS, 
00233                                       const PropagationDirection propDir) const {
00234   return TSoS.localMomentum().unit().z()!=theLastDz ||
00235     TSoS.localMomentum().mag()!=theLastP || propDir!=theLastPropDir ||
00236     TSoS.surface().mediumProperties()->radLen()!=theLastRadLength;
00237 }
00238 //
00239 // Save arguments
00240 //
00241 void GsfBetheHeitlerUpdator::storeArguments (const TrajectoryStateOnSurface& TSoS, 
00242                                              const PropagationDirection propDir) const {
00243   theLastDz = TSoS.localMomentum().unit().z();
00244   theLastP = TSoS.localMomentum().mag();
00245   theLastPropDir = propDir;
00246   theLastRadLength = TSoS.surface().mediumProperties()->radLen();
00247 }