00001
00002 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00003
00004
00005
00006
00007 #include "FastSimulation/Event/interface/FSimEvent.h"
00008 #include "FastSimulation/ParticlePropagator/interface/ParticlePropagator.h"
00009 #include "FastSimulation/TrackerSetup/interface/TrackerLayer.h"
00010 #include "FastSimulation/MaterialEffects/interface/MaterialEffects.h"
00011
00012 #include "FastSimulation/MaterialEffects/interface/PairProductionSimulator.h"
00013 #include "FastSimulation/MaterialEffects/interface/MultipleScatteringSimulator.h"
00014 #include "FastSimulation/MaterialEffects/interface/BremsstrahlungSimulator.h"
00015 #include "FastSimulation/MaterialEffects/interface/EnergyLossSimulator.h"
00016 #include "FastSimulation/MaterialEffects/interface/NuclearInteractionSimulator.h"
00017
00018 #include <list>
00019 #include <map>
00020 #include <string>
00021
00022 MaterialEffects::MaterialEffects(const edm::ParameterSet& matEff,
00023 const RandomEngine* engine)
00024 : PairProduction(0), Bremsstrahlung(0),
00025 MultipleScattering(0), EnergyLoss(0),
00026 NuclearInteraction(0),
00027 pTmin(999.), random(engine)
00028 {
00029
00030
00031 bool doPairProduction = matEff.getParameter<bool>("PairProduction");
00032 bool doBremsstrahlung = matEff.getParameter<bool>("Bremsstrahlung");
00033 bool doEnergyLoss = matEff.getParameter<bool>("EnergyLoss");
00034 bool doMultipleScattering = matEff.getParameter<bool>("MultipleScattering");
00035 bool doNuclearInteraction = matEff.getParameter<bool>("NuclearInteraction");
00036
00037 double A = matEff.getParameter<double>("A");
00038 double Z = matEff.getParameter<double>("Z");
00039 double density = matEff.getParameter<double>("Density");
00040 double radLen = matEff.getParameter<double>("RadiationLength");
00041
00042
00043
00044 if ( doPairProduction ) {
00045
00046 double photonEnergy = matEff.getParameter<double>("photonEnergy");
00047 PairProduction = new PairProductionSimulator(photonEnergy,
00048 random);
00049
00050 }
00051
00052 if ( doBremsstrahlung ) {
00053
00054 double bremEnergy = matEff.getParameter<double>("bremEnergy");
00055 double bremEnergyFraction = matEff.getParameter<double>("bremEnergyFraction");
00056 Bremsstrahlung = new BremsstrahlungSimulator(bremEnergy,
00057 bremEnergyFraction,
00058 random);
00059
00060 }
00061
00062 if ( doEnergyLoss ) {
00063
00064 pTmin = matEff.getParameter<double>("pTmin");
00065 EnergyLoss = new EnergyLossSimulator(random,A,Z,density,radLen);
00066
00067 }
00068
00069 if ( doMultipleScattering ) {
00070
00071 MultipleScattering = new MultipleScatteringSimulator(random,A,Z,density,radLen);
00072
00073 }
00074
00075 if ( doNuclearInteraction ) {
00076
00077
00078 std::vector<double> pionEnergies
00079 = matEff.getUntrackedParameter<std::vector<double> >("pionEnergies");
00080
00081
00082 std::vector<int> pionTypes
00083 = matEff.getUntrackedParameter<std::vector<int> >("pionTypes");
00084
00085
00086 std::vector<std::string> pionNames
00087 = matEff.getUntrackedParameter<std::vector<std::string> >("pionNames");
00088
00089
00090 std::vector<double> pionMasses
00091 = matEff.getUntrackedParameter<std::vector<double> >("pionMasses");
00092
00093
00094 std::vector<double> pionPMin
00095 = matEff.getUntrackedParameter<std::vector<double> >("pionMinP");
00096
00097
00098 std::vector<double> lengthRatio
00099 = matEff.getParameter<std::vector<double> >("lengthRatio");
00100
00101
00102
00103
00104
00105
00106 theTECFudgeFactor = matEff.getParameter<double>("fudgeFactor");
00107
00108
00109 std::vector<double> theRatios
00110 = matEff.getUntrackedParameter<std::vector<double> >("ratios");
00111
00112
00113
00114
00115
00116
00117 std::vector< std::vector<double> > ratios;
00118 ratios.resize(pionTypes.size());
00119 for ( unsigned i=0; i<pionTypes.size(); ++i ) {
00120 for ( unsigned j=0; j<pionEnergies.size(); ++j ) {
00121 ratios[i].push_back(theRatios[ i*pionEnergies.size() + j ]);
00122 }
00123 }
00124
00125
00126 double pionEnergy
00127 = matEff.getParameter<double>("pionEnergy");
00128
00129
00130
00131 unsigned distAlgo
00132 = matEff.getParameter<unsigned>("distAlgo");
00133 double distCut
00134 = matEff.getParameter<double>("distCut");
00135
00136
00137
00138 std::string inputFile
00139 = matEff.getUntrackedParameter<std::string>("inputFile");
00140
00141
00142 std::map<int,int> idMap;
00143
00144 std::vector<int> idProtons
00145 = matEff.getUntrackedParameter<std::vector<int> >("protons");
00146 for ( unsigned i=0; i<idProtons.size(); ++i )
00147 idMap[idProtons[i]] = 2212;
00148
00149 std::vector<int> idAntiProtons
00150 = matEff.getUntrackedParameter<std::vector<int> >("antiprotons");
00151 for ( unsigned i=0; i<idAntiProtons.size(); ++i )
00152 idMap[idAntiProtons[i]] = -2212;
00153
00154 std::vector<int> idNeutrons
00155 = matEff.getUntrackedParameter<std::vector<int> >("neutrons");
00156 for ( unsigned i=0; i<idNeutrons.size(); ++i )
00157 idMap[idNeutrons[i]] = 2112;
00158
00159 std::vector<int> idAntiNeutrons
00160 = matEff.getUntrackedParameter<std::vector<int> >("antineutrons");
00161 for ( unsigned i=0; i<idAntiNeutrons.size(); ++i )
00162 idMap[idAntiNeutrons[i]] = -2112;
00163
00164 std::vector<int> idK0Ls
00165 = matEff.getUntrackedParameter<std::vector<int> >("K0Ls");
00166 for ( unsigned i=0; i<idK0Ls.size(); ++i )
00167 idMap[idK0Ls[i]] = 130;
00168
00169 std::vector<int> idKplusses
00170 = matEff.getUntrackedParameter<std::vector<int> >("Kplusses");
00171 for ( unsigned i=0; i<idKplusses.size(); ++i )
00172 idMap[idKplusses[i]] = 321;
00173
00174 std::vector<int> idKminusses
00175 = matEff.getUntrackedParameter<std::vector<int> >("Kminusses");
00176 for ( unsigned i=0; i<idKminusses.size(); ++i )
00177 idMap[idKminusses[i]] = -321;
00178
00179 std::vector<int> idPiplusses
00180 = matEff.getUntrackedParameter<std::vector<int> >("Piplusses");
00181 for ( unsigned i=0; i<idPiplusses.size(); ++i )
00182 idMap[idPiplusses[i]] = 211;
00183
00184 std::vector<int> idPiminusses
00185 = matEff.getUntrackedParameter<std::vector<int> >("Piminusses");
00186 for ( unsigned i=0; i<idPiminusses.size(); ++i )
00187 idMap[idPiminusses[i]] = -211;
00188
00189
00190 NuclearInteraction =
00191 new NuclearInteractionSimulator(pionEnergies, pionTypes, pionNames,
00192 pionMasses, pionPMin, pionEnergy,
00193 lengthRatio, ratios, idMap,
00194 inputFile, distAlgo, distCut, random);
00195 }
00196
00197 }
00198
00199
00200 MaterialEffects::~MaterialEffects() {
00201
00202 if ( PairProduction ) delete PairProduction;
00203 if ( Bremsstrahlung ) delete Bremsstrahlung;
00204 if ( EnergyLoss ) delete EnergyLoss;
00205 if ( MultipleScattering ) delete MultipleScattering;
00206 if ( NuclearInteraction ) delete NuclearInteraction;
00207
00208 }
00209
00210 void MaterialEffects::interact(FSimEvent& mySimEvent,
00211 const TrackerLayer& layer,
00212 ParticlePropagator& myTrack,
00213 unsigned itrack) {
00214
00215 MaterialEffectsSimulator::RHEP_const_iter DaughterIter;
00216 double radlen;
00217 theEnergyLoss = 0;
00218 theNormalVector = normalVector(layer,myTrack);
00219 radlen = radLengths(layer,myTrack);
00220
00221
00222
00223
00224
00225 if ( PairProduction && myTrack.pid()==22 ) {
00226
00227
00228 PairProduction->updateState(myTrack,radlen);
00229
00230 if ( PairProduction->nDaughters() ) {
00231
00232 int ivertex = mySimEvent.addSimVertex(myTrack.vertex(),itrack);
00233
00234
00235 for ( DaughterIter = PairProduction->beginDaughters();
00236 DaughterIter != PairProduction->endDaughters();
00237 ++DaughterIter) {
00238
00239 mySimEvent.addSimTrack(&(*DaughterIter), ivertex);
00240
00241 }
00242
00243 return;
00244 }
00245 }
00246
00247 if ( myTrack.pid() == 22 ) return;
00248
00249
00250
00251
00252
00253 if ( NuclearInteraction && abs(myTrack.pid()) > 100
00254 && abs(myTrack.pid()) < 1000000) {
00255
00256
00257 double factor = 1.0;
00258 if (layer.layerNumber() >= 19 && layer.layerNumber() <= 27 )
00259 factor = theTECFudgeFactor;
00260 NuclearInteraction->updateState(myTrack,radlen*factor);
00261
00262 if ( NuclearInteraction->nDaughters() ) {
00263
00264
00265 int ivertex = mySimEvent.addSimVertex(myTrack.vertex(),itrack);
00266
00267
00268 int idaugh = 0;
00269 for ( DaughterIter = NuclearInteraction->beginDaughters();
00270 DaughterIter != NuclearInteraction->endDaughters();
00271 ++DaughterIter) {
00272
00273
00274 int daughId = mySimEvent.addSimTrack(&(*DaughterIter), ivertex);
00275
00276
00277 if ( NuclearInteraction->closestDaughterId() == idaugh++ ) {
00278 if ( mySimEvent.track(itrack).vertex().position().Pt() < 4.0 )
00279 mySimEvent.track(itrack).setClosestDaughterId(daughId);
00280 }
00281
00282 }
00283
00284 return;
00285 }
00286
00287 }
00288
00289 if ( myTrack.charge() == 0 ) return;
00290
00291 if ( !Bremsstrahlung && !EnergyLoss && !MultipleScattering ) return;
00292
00293
00294
00295
00296
00297 if ( Bremsstrahlung && abs(myTrack.pid())==11 ) {
00298
00299 Bremsstrahlung->updateState(myTrack,radlen);
00300
00301 if ( Bremsstrahlung->nDaughters() ) {
00302
00303
00304
00305 int ivertex = mySimEvent.addSimVertex(myTrack.vertex(),itrack);
00306
00307 for ( DaughterIter = Bremsstrahlung->beginDaughters();
00308 DaughterIter != Bremsstrahlung->endDaughters();
00309 ++DaughterIter) {
00310 mySimEvent.addSimTrack(&(*DaughterIter), ivertex);
00311
00312 }
00313
00314 }
00315
00316 }
00317
00318
00322
00323 if ( EnergyLoss )
00324 {
00325 theEnergyLoss = myTrack.E();
00326 EnergyLoss->updateState(myTrack,radlen);
00327 theEnergyLoss -= myTrack.E();
00328 }
00329
00330
00334
00335 if ( MultipleScattering && myTrack.Pt() > pTmin ) {
00336
00337 MultipleScattering->setNormalVector(theNormalVector);
00338 MultipleScattering->updateState(myTrack,radlen);
00339 }
00340
00341 }
00342
00343 double
00344 MaterialEffects::radLengths(const TrackerLayer& layer,
00345 ParticlePropagator& myTrack) {
00346
00347
00348 theThickness = layer.surface().mediumProperties()->radLen();
00349
00350 GlobalVector P(myTrack.Px(),myTrack.Py(),myTrack.Pz());
00351
00352
00353
00354 double radlen = theThickness / fabs(P.dot(theNormalVector)) * P.mag();
00355
00356
00357
00358 double rad = myTrack.R();
00359 double zed = fabs(myTrack.Z());
00360
00361 double factor = 1;
00362
00363
00364 if ( layer.fudgeNumber() )
00365
00366
00367 for ( unsigned int iLayer=0; iLayer < layer.fudgeNumber(); ++iLayer ) {
00368
00369
00370 if ( ( layer.forward() && layer.fudgeMin(iLayer) < rad && rad < layer.fudgeMax(iLayer) ) ||
00371 ( !layer.forward() && layer.fudgeMin(iLayer) < zed && zed < layer.fudgeMax(iLayer) ) ) {
00372 factor = layer.fudgeFactor(iLayer);
00373 break;
00374 }
00375
00376 }
00377
00378 theThickness *= factor;
00379
00380 return radlen * factor;
00381
00382 }
00383
00384 GlobalVector
00385 MaterialEffects::normalVector(const TrackerLayer& layer,
00386 ParticlePropagator& myTrack ) const {
00387 return layer.forward() ?
00388 layer.disk()->normalVector() :
00389 GlobalVector(myTrack.X(),myTrack.Y(),0.)/myTrack.R();
00390 }
00391
00392 void
00393 MaterialEffects::save() {
00394
00395
00396 if ( NuclearInteraction ) NuclearInteraction->save();
00397
00398 }