00001
00002
00003
00004
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "FWCore/ServiceRegistry/interface/Service.h"
00024 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00025 #include "FWCore/Framework/interface/MakerMacros.h"
00026
00027
00028 #include "FastSimulation/Utilities/interface/RandomEngine.h"
00029 #include "FastSimulation/MuonSimHitProducer/interface/MuonSimHitProducer.h"
00030 #include "FastSimulation/MaterialEffects/interface/MaterialEffects.h"
00031 #include "FastSimulation/MaterialEffects/interface/MultipleScatteringSimulator.h"
00032 #include "FastSimulation/MaterialEffects/interface/EnergyLossSimulator.h"
00033 #include "FastSimulation/ParticlePropagator/interface/ParticlePropagator.h"
00034
00035
00036 #include "SimDataFormats/Track/interface/SimTrack.h"
00037 #include "SimDataFormats/Vertex/interface/SimVertex.h"
00038 #include "SimDataFormats/TrackingHit/interface/PSimHitContainer.h"
00039
00040
00041 #include <vector>
00042 #include <iostream>
00043
00044
00045 #include "RecoMuon/TrackingTools/interface/MuonServiceProxy.h"
00046 #include "RecoMuon/Navigation/interface/DirectMuonNavigation.h"
00047 #include "RecoMuon/MeasurementDet/interface/MuonDetLayerMeasurements.h"
00048 #include "RecoMuon/TrackingTools/interface/MuonPatternRecoDumper.h"
00049
00050
00051 #include "TrackingTools/GeomPropagators/interface/HelixArbitraryPlaneCrossing.h"
00052 #include "TrackPropagation/SteppingHelixPropagator/interface/SteppingHelixPropagator.h"
00053
00054
00055 #include "DataFormats/MuonDetId/interface/DTWireId.h"
00056 #include "DataFormats/GeometrySurface/interface/PlaneBuilder.h"
00057 #include "DataFormats/GeometrySurface/interface/TangentPlane.h"
00058
00059
00061
00062 #include "Geometry/DTGeometry/interface/DTGeometry.h"
00063 #include "Geometry/CSCGeometry/interface/CSCGeometry.h"
00064 #include "Geometry/RPCGeometry/interface/RPCGeometry.h"
00065 #include "Geometry/Records/interface/MuonGeometryRecord.h"
00066 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
00067
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 MuonSimHitProducer::MuonSimHitProducer(const edm::ParameterSet& iConfig):
00079 theEstimator(iConfig.getParameter<double>("Chi2EstimatorCut")),
00080 propagatorWithoutMaterial(0)
00081 {
00082
00083
00084
00085
00086 edm::Service<edm::RandomNumberGenerator> rng;
00087 if ( ! rng.isAvailable() ) {
00088 throw cms::Exception("Configuration") <<
00089 "MuonSimHitProducer requires the RandomGeneratorService \n"
00090 "which is not present in the configuration file. \n"
00091 "You must add the service in the configuration file\n"
00092 "or remove the module that requires it.";
00093 }
00094
00095 random = new RandomEngine(&(*rng));
00096
00097
00098 readParameters(iConfig.getParameter<edm::ParameterSet>("MUONS"),
00099 iConfig.getParameter<edm::ParameterSet>("TRACKS"),
00100 iConfig.getParameter<edm::ParameterSet>("MaterialEffectsForMuons"));
00101
00102
00103
00104
00105 produces<edm::PSimHitContainer>("MuonCSCHits");
00106 produces<edm::PSimHitContainer>("MuonDTHits");
00107 produces<edm::PSimHitContainer>("MuonRPCHits");
00108
00109 edm::ParameterSet serviceParameters =
00110 iConfig.getParameter<edm::ParameterSet>("ServiceParameters");
00111 theService = new MuonServiceProxy(serviceParameters);
00112 }
00113
00114
00115 void
00116 MuonSimHitProducer::beginRun(edm::Run & run, const edm::EventSetup & es) {
00117
00118
00119 edm::ESHandle<MagneticField> magField;
00120 edm::ESHandle<DTGeometry> dtGeometry;
00121 edm::ESHandle<CSCGeometry> cscGeometry;
00122 edm::ESHandle<RPCGeometry> rpcGeometry;
00123 edm::ESHandle<Propagator> propagator;
00124
00125 es.get<IdealMagneticFieldRecord>().get(magField);
00126 es.get<MuonGeometryRecord>().get("MisAligned",dtGeometry);
00127 es.get<MuonGeometryRecord>().get("MisAligned",cscGeometry);
00128 es.get<MuonGeometryRecord>().get(rpcGeometry);
00129
00130 magfield = &(*magField);
00131 dtGeom = &(*dtGeometry);
00132 cscGeom = &(*cscGeometry);
00133 rpcGeom = &(*rpcGeometry);
00134
00135 theService->update(es);
00136
00137
00138 propagatorWithMaterial = &(*(theService->propagator("SteppingHelixPropagatorAny")));
00139 propagatorWithoutMaterial = propagatorWithMaterial->clone();
00140 SteppingHelixPropagator* SHpropagator = dynamic_cast<SteppingHelixPropagator*> (propagatorWithoutMaterial);
00141 SHpropagator->setMaterialMode(true);
00142
00143 }
00144
00145 MuonSimHitProducer::~MuonSimHitProducer()
00146 {
00147
00148
00149
00150 if ( random ) {
00151 delete random;
00152 }
00153
00154 if ( theMaterialEffects ) delete theMaterialEffects;
00155 if ( propagatorWithoutMaterial) delete propagatorWithoutMaterial;
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165 void
00166 MuonSimHitProducer::produce(edm::Event& iEvent,const edm::EventSetup& iSetup) {
00167
00168
00169
00170 MuonPatternRecoDumper dumper;
00171
00172 edm::Handle<std::vector<SimTrack> > simMuons;
00173 edm::Handle<std::vector<SimVertex> > simVertices;
00174 std::vector<PSimHit> theCSCHits;
00175 std::vector<PSimHit> theDTHits;
00176 std::vector<PSimHit> theRPCHits;
00177
00178 DirectMuonNavigation navigation(theService->detLayerGeometry());
00179 iEvent.getByLabel(theSimModuleLabel_,theSimModuleProcess_,simMuons);
00180 iEvent.getByLabel(theSimModuleLabel_,simVertices);
00181
00182 for ( unsigned int itrk=0; itrk<simMuons->size(); itrk++ ) {
00183 const SimTrack &mySimTrack = (*simMuons)[itrk];
00184 math::XYZTLorentzVector mySimP4(mySimTrack.momentum().x(),
00185 mySimTrack.momentum().y(),
00186 mySimTrack.momentum().z(),
00187 mySimTrack.momentum().t());
00188
00189
00190
00191 int pid = mySimTrack.type();
00192 if ( abs(pid) != 13 ) continue;
00193
00194 double t0 = 0;
00195 GlobalPoint initialPosition;
00196 int ivert = mySimTrack.vertIndex();
00197 if ( ivert >= 0 ) {
00198 t0 = (*simVertices)[ivert].position().t();
00199 GlobalPoint xyzzy((*simVertices)[ivert].position().x(),
00200 (*simVertices)[ivert].position().y(),
00201 (*simVertices)[ivert].position().z());
00202 initialPosition = xyzzy;
00203 }
00204
00205
00206
00207
00208
00209 double tof = t0/29.98;
00210
00211 #ifdef FAMOS_DEBUG
00212 std::cout << " ===> MuonSimHitProducer::reconstruct() found SIMTRACK - pid = "
00213 << pid ;
00214 std::cout << " : pT = " << mySimP4.Pt()
00215 << ", eta = " << mySimP4.Eta()
00216 << ", phi = " << mySimP4.Phi() << std::endl;
00217 #endif
00218
00219
00220
00221
00222
00223 GlobalPoint startingPosition(mySimTrack.trackerSurfacePosition().x(),
00224 mySimTrack.trackerSurfacePosition().y(),
00225 mySimTrack.trackerSurfacePosition().z());
00226 GlobalVector startingMomentum(mySimTrack.trackerSurfaceMomentum().x(),
00227 mySimTrack.trackerSurfaceMomentum().y(),
00228 mySimTrack.trackerSurfaceMomentum().z());
00229
00230
00231
00232
00233
00234 GlobalVector dtracker = startingPosition-initialPosition;
00235 tof += dtracker.mag()/29.98;
00236
00237 #ifdef FAMOS_DEBUG
00238 std::cout << " the Muon START position " << startingPosition << std::endl;
00239 std::cout << " the Muon START momentum " << startingMomentum << std::endl;
00240 #endif
00241
00242
00243
00244
00245 PlaneBuilder pb;
00246 GlobalVector zAxis = startingMomentum.unit();
00247 GlobalVector yAxis(zAxis.y(),-zAxis.x(),0);
00248 GlobalVector xAxis = yAxis.cross(zAxis);
00249 Surface::RotationType rot = Surface::RotationType(xAxis,yAxis,zAxis);
00250 PlaneBuilder::ReturnType startingPlane = pb.plane(startingPosition,rot);
00251 GlobalTrajectoryParameters gtp(startingPosition,
00252 startingMomentum,
00253 (int)mySimTrack.charge(),
00254 magfield);
00255 TrajectoryStateOnSurface startingState(gtp,*startingPlane);
00256
00257 std::vector<const DetLayer *> navLayers;
00258 if ( fabs(startingState.globalMomentum().eta()) > 4.5 ) {
00259 navLayers = navigation.compatibleEndcapLayers(*(startingState.freeState()),
00260 alongMomentum);
00261 }
00262 else {
00263 navLayers = navigation.compatibleLayers(*(startingState.freeState()),
00264 alongMomentum);
00265 }
00266
00267
00268
00269
00270
00271 if ( navLayers.empty() ) continue;
00272
00273 #ifdef FAMOS_DEBUG
00274 std::cout << "Found " << navLayers.size()
00275 << " compatible DetLayers..." << std::endl;
00276 #endif
00277
00278 TrajectoryStateOnSurface propagatedState = startingState;
00279 for ( unsigned int ilayer=0; ilayer<navLayers.size(); ilayer++ ) {
00280
00281 #ifdef FAMOS_DEBUG
00282 std::cout << "Propagating to layer " << ilayer << " "
00283 << dumper.dumpLayer(navLayers[ilayer])
00284 << std::endl;
00285 #endif
00286
00287 std::vector<DetWithState> comps =
00288 navLayers[ilayer]->compatibleDets(propagatedState,*propagatorWithMaterial,theEstimator);
00289 if ( comps.empty() ) continue;
00290
00291 #ifdef FAMOS_DEBUG
00292 std::cout << "Propagating " << propagatedState << std::endl;
00293 #endif
00294
00295
00296 double pi = propagatedState.globalMomentum().mag();
00297
00298
00299 SteppingHelixStateInfo shsStart(*(propagatedState.freeTrajectoryState()));
00300 const SteppingHelixStateInfo& shsDest =
00301 ((const SteppingHelixPropagator*)propagatorWithMaterial)->propagate(shsStart,navLayers[ilayer]->surface());
00302 std::pair<TrajectoryStateOnSurface,double> next(shsDest.getStateOnSurface(navLayers[ilayer]->surface()),
00303 shsDest.path());
00304
00305
00306 if ( !next.first.isValid() ) continue;
00307
00308
00309 double radPath = shsDest.radPath();
00310 double pathLength = next.second;
00311
00312
00313
00314 std::pair<TrajectoryStateOnSurface,double> nextNoMaterial =
00315 propagatorWithoutMaterial->propagateWithPath(propagatedState,navLayers[ilayer]->surface());
00316
00317
00318 propagatedState = next.first;
00319 double pf = propagatedState.globalMomentum().mag();
00320
00321
00322
00323
00324 if ( theMaterialEffects && nextNoMaterial.first.isValid() ) applyMaterialEffects(propagatedState,nextNoMaterial.first,radPath);
00325
00326 if ( !propagatedState.isValid() ) continue;
00327
00328
00329
00330
00331
00332
00333 double pavg = 0.5*(pi+pf);
00334 double m = mySimP4.M();
00335 double rbeta = sqrt(1+m*m/(pavg*pavg))/29.98;
00336 double dtof = pathLength*rbeta;
00337
00338 #ifdef FAMOS_DEBUG
00339 std::cout << "Propagated to next surface... path length = " << pathLength
00340 << " cm, dTOF = " << dtof << " ns" << std::endl;
00341 #endif
00342
00343 tof += dtof;
00344
00345 for ( unsigned int icomp=0; icomp<comps.size(); icomp++ )
00346 {
00347 const GeomDet *gd = comps[icomp].first;
00348 if ( gd->subDetector() == GeomDetEnumerators::DT ) {
00349 DTChamberId id(gd->geographicalId());
00350 const DTChamber *chamber = dtGeom->chamber(id);
00351 std::vector<const DTSuperLayer *> superlayer = chamber->superLayers();
00352 for ( unsigned int isl=0; isl<superlayer.size(); isl++ ) {
00353 std::vector<const DTLayer *> layer = superlayer[isl]->layers();
00354 for ( unsigned int ilayer=0; ilayer<layer.size(); ilayer++ ) {
00355 DTLayerId lid = layer[ilayer]->id();
00356 #ifdef FAMOS_DEBUG
00357 std::cout << " Extrapolated to DT ("
00358 << lid.wheel() << ","
00359 << lid.station() << ","
00360 << lid.sector() << ","
00361 << lid.superlayer() << ","
00362 << lid.layer() << ")" << std::endl;
00363 #endif
00364
00365 const GeomDetUnit *det = dtGeom->idToDetUnit(lid);
00366
00367 HelixArbitraryPlaneCrossing crossing(propagatedState.globalPosition().basicVector(),
00368 propagatedState.globalMomentum().basicVector(),
00369 propagatedState.transverseCurvature(),
00370 anyDirection);
00371 std::pair<bool,double> path = crossing.pathLength(det->surface());
00372 if ( ! path.first ) continue;
00373 LocalPoint lpos = det->toLocal(GlobalPoint(crossing.position(path.second)));
00374 if ( ! det->surface().bounds().inside(lpos) ) continue;
00375 const DTTopology& dtTopo = layer[ilayer]->specificTopology();
00376 int wire = dtTopo.channel(lpos);
00377 if (wire < dtTopo.firstChannel() || wire > dtTopo.lastChannel()) continue;
00378
00379
00380
00381 DTWireId wid(lid,wire);
00382 double thickness = det->surface().bounds().thickness();
00383 LocalVector lmom = det->toLocal(GlobalVector(crossing.direction(path.second)));
00384 lmom = lmom.unit()*propagatedState.localMomentum().mag();
00385
00386
00387
00388 double pmu = lmom.mag();
00389 double theDTHitIneff = pmu>0? exp(kDT*log(pmu)+fDT):0.;
00390 if (random->flatShoot()<theDTHitIneff) continue;
00391
00392 double eloss = 0;
00393 double pz = fabs(lmom.z());
00394 LocalPoint entry = lpos - 0.5*thickness*lmom/pz;
00395 LocalPoint exit = lpos + 0.5*thickness*lmom/pz;
00396 double dtof = path.second*rbeta;
00397 int trkid = mySimTrack.trackId();
00398 unsigned int id = wid.rawId();
00399 short unsigned int processType = 2;
00400 PSimHit hit(entry,exit,lmom.mag(),
00401 tof+dtof,eloss,pid,id,trkid,lmom.theta(),lmom.phi(),processType);
00402 theDTHits.push_back(hit);
00403
00404 }
00405 }
00406 }
00407 else if ( gd->subDetector() == GeomDetEnumerators::CSC ) {
00408 CSCDetId id(gd->geographicalId());
00409 const CSCChamber *chamber = cscGeom->chamber(id);
00410 std::vector<const CSCLayer *> layers = chamber->layers();
00411 for ( unsigned int ilayer=0; ilayer<layers.size(); ilayer++ ) {
00412 CSCDetId lid = layers[ilayer]->id();
00413
00414 #ifdef FAMOS_DEBUG
00415 std::cout << " Extrapolated to CSC ("
00416 << lid.endcap() << ","
00417 << lid.ring() << ","
00418 << lid.station() << ","
00419 << lid.layer() << ")" << std::endl;
00420 #endif
00421
00422 const GeomDetUnit *det = cscGeom->idToDetUnit(lid);
00423 HelixArbitraryPlaneCrossing crossing(propagatedState.globalPosition().basicVector(),
00424 propagatedState.globalMomentum().basicVector(),
00425 propagatedState.transverseCurvature(),
00426 anyDirection);
00427 std::pair<bool,double> path = crossing.pathLength(det->surface());
00428 if ( ! path.first ) continue;
00429 LocalPoint lpos = det->toLocal(GlobalPoint(crossing.position(path.second)));
00430
00431
00432
00433 const CSCLayerGeometry* laygeom = layers[ilayer]->geometry();
00434 if ( ! laygeom->inside( lpos ) ) continue;
00435
00436 double thickness = det->surface().bounds().thickness();
00437 LocalVector lmom = det->toLocal(GlobalVector(crossing.direction(path.second)));
00438 lmom = lmom.unit()*propagatedState.localMomentum().mag();
00439
00440
00441
00442 double pmu = lmom.mag();
00443 double theCSCHitIneff = pmu>0? exp(kCSC*log(pmu)+fCSC):0.;
00444
00445 if (id.station()==1 && id.ring()==1) theCSCHitIneff = theCSCHitIneff*0.442;
00446 if (random->flatShoot()<theCSCHitIneff) continue;
00447
00448 double eloss = 0;
00449 double pz = fabs(lmom.z());
00450 LocalPoint entry = lpos - 0.5*thickness*lmom/pz;
00451 LocalPoint exit = lpos + 0.5*thickness*lmom/pz;
00452 double dtof = path.second*rbeta;
00453 int trkid = mySimTrack.trackId();
00454 unsigned int id = lid.rawId();
00455 short unsigned int processType = 2;
00456 PSimHit hit(entry,exit,lmom.mag(),
00457 tof+dtof,eloss,pid,id,trkid,lmom.theta(),lmom.phi(),processType);
00458 theCSCHits.push_back(hit);
00459 }
00460 }
00461 else if ( gd->subDetector() == GeomDetEnumerators::RPCBarrel ||
00462 gd->subDetector() == GeomDetEnumerators::RPCEndcap ) {
00463 RPCDetId id(gd->geographicalId());
00464 const RPCChamber *chamber = rpcGeom->chamber(id);
00465 std::vector<const RPCRoll *> roll = chamber->rolls();
00466 for ( unsigned int iroll=0; iroll<roll.size(); iroll++ ) {
00467 RPCDetId rid = roll[iroll]->id();
00468
00469 #ifdef FAMOS_DEBUG
00470 std::cout << " Extrapolated to RPC ("
00471 << rid.ring() << ","
00472 << rid.station() << ","
00473 << rid.sector() << ","
00474 << rid.subsector() << ","
00475 << rid.layer() << ","
00476 << rid.roll() << ")" << std::endl;
00477 #endif
00478
00479 const GeomDetUnit *det = rpcGeom->idToDetUnit(rid);
00480 HelixArbitraryPlaneCrossing crossing(propagatedState.globalPosition().basicVector(),
00481 propagatedState.globalMomentum().basicVector(),
00482 propagatedState.transverseCurvature(),
00483 anyDirection);
00484 std::pair<bool,double> path = crossing.pathLength(det->surface());
00485 if ( ! path.first ) continue;
00486 LocalPoint lpos = det->toLocal(GlobalPoint(crossing.position(path.second)));
00487 if ( ! det->surface().bounds().inside(lpos) ) continue;
00488 double thickness = det->surface().bounds().thickness();
00489 LocalVector lmom = det->toLocal(GlobalVector(crossing.direction(path.second)));
00490 lmom = lmom.unit()*propagatedState.localMomentum().mag();
00491 double eloss = 0;
00492 double pz = fabs(lmom.z());
00493 LocalPoint entry = lpos - 0.5*thickness*lmom/pz;
00494 LocalPoint exit = lpos + 0.5*thickness*lmom/pz;
00495 double dtof = path.second*rbeta;
00496 int trkid = mySimTrack.trackId();
00497 unsigned int id = rid.rawId();
00498 short unsigned int processType = 2;
00499 PSimHit hit(entry,exit,lmom.mag(),
00500 tof+dtof,eloss,pid,id,trkid,lmom.theta(),lmom.phi(),processType);
00501 theRPCHits.push_back(hit);
00502 }
00503 }
00504 else {
00505 std::cout << "Extrapolated to unknown subdetector '" << gd->subDetector() << "'..." << std::endl;
00506 }
00507 }
00508 }
00509 }
00510
00511 std::auto_ptr<edm::PSimHitContainer> pcsc(new edm::PSimHitContainer);
00512 int n = 0;
00513 for ( std::vector<PSimHit>::const_iterator i = theCSCHits.begin();
00514 i != theCSCHits.end(); i++ ) {
00515 pcsc->push_back(*i);
00516 n += 1;
00517 }
00518 iEvent.put(pcsc,"MuonCSCHits");
00519
00520 std::auto_ptr<edm::PSimHitContainer> pdt(new edm::PSimHitContainer);
00521 n = 0;
00522 for ( std::vector<PSimHit>::const_iterator i = theDTHits.begin();
00523 i != theDTHits.end(); i++ ) {
00524 pdt->push_back(*i);
00525 n += 1;
00526 }
00527 iEvent.put(pdt,"MuonDTHits");
00528
00529 std::auto_ptr<edm::PSimHitContainer> prpc(new edm::PSimHitContainer);
00530 n = 0;
00531 for ( std::vector<PSimHit>::const_iterator i = theRPCHits.begin();
00532 i != theRPCHits.end(); i++ ) {
00533 prpc->push_back(*i);
00534 n += 1;
00535 }
00536 iEvent.put(prpc,"MuonRPCHits");
00537
00538 }
00539
00540
00541
00542 void
00543 MuonSimHitProducer::endJob()
00544 {
00545 }
00546
00547
00548 void
00549 MuonSimHitProducer::readParameters(const edm::ParameterSet& fastMuons,
00550 const edm::ParameterSet& fastTracks,
00551 const edm::ParameterSet& matEff) {
00552
00553 theSimModuleLabel_ = fastMuons.getParameter<std::string>("simModuleLabel");
00554 theSimModuleProcess_ = fastMuons.getParameter<std::string>("simModuleProcess");
00555 theTrkModuleLabel_ = fastMuons.getParameter<std::string>("trackModuleLabel");
00556 std::vector<double> simHitIneffDT = fastMuons.getParameter<std::vector<double> >("simHitDTIneffParameters");
00557 std::vector<double> simHitIneffCSC = fastMuons.getParameter<std::vector<double> >("simHitCSCIneffParameters");
00558 kDT = simHitIneffDT[0];
00559 fDT = simHitIneffDT[1];
00560 kCSC = simHitIneffCSC[0];
00561 fCSC = simHitIneffCSC[1];
00562
00563
00564 fullPattern_ = fastTracks.getUntrackedParameter<bool>("FullPatternRecognition");
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575 theMaterialEffects = 0;
00576 if ( matEff.getParameter<bool>("PairProduction") ||
00577 matEff.getParameter<bool>("Bremsstrahlung") ||
00578 matEff.getParameter<bool>("EnergyLoss") ||
00579 matEff.getParameter<bool>("MultipleScattering") )
00580 theMaterialEffects = new MaterialEffects(matEff,random);
00581
00582 }
00583
00584 void
00585 MuonSimHitProducer::applyMaterialEffects(TrajectoryStateOnSurface& tsosWithdEdx,
00586 TrajectoryStateOnSurface& tsos,
00587 double radPath) {
00588
00589
00590 EnergyLossSimulator* energyLoss = theMaterialEffects->energyLossSimulator();
00591
00592
00593 MultipleScatteringSimulator* multipleScattering = theMaterialEffects->multipleScatteringSimulator();
00594
00595
00596 const Surface& nextSurface = tsos.surface();
00597 GlobalPoint gPos = energyLoss ? tsos.globalPosition() : tsosWithdEdx.globalPosition();
00598 GlobalVector gMom = energyLoss ? tsos.globalMomentum() : tsosWithdEdx.globalMomentum();
00599 double mu = 0.1056583692;
00600 double en = std::sqrt(gMom.mag2()+mu*mu);
00601
00602
00603 XYZTLorentzVector position(gPos.x(),gPos.y(),gPos.z(),0.);
00604 XYZTLorentzVector momentum(gMom.x(),gMom.y(),gMom.z(),en);
00605 float charge = (float)(tsos.charge());
00606 ParticlePropagator theMuon(momentum,position,charge,0);
00607 theMuon.setID(-(int)charge*13);
00608
00609
00610 if ( energyLoss ) {
00611
00612
00613 GlobalPoint gPosWithdEdx = tsosWithdEdx.globalPosition();
00614 GlobalVector gMomWithdEdx = tsosWithdEdx.globalMomentum();
00615 double enWithdEdx = std::sqrt(gMomWithdEdx.mag2()+mu*mu);
00616 XYZTLorentzVector
00617 deltaPos(gPosWithdEdx.x()-gPos.x(),gPosWithdEdx.y()-gPos.y(),
00618 gPosWithdEdx.z()-gPos.z(),0.);
00619 XYZTLorentzVector
00620 deltaMom(gMomWithdEdx.x()-gMom.x(),gMomWithdEdx.y()-gMom.y(),
00621 gMomWithdEdx.z()-gMom.z(), enWithdEdx -en);
00622
00623
00624 energyLoss->updateState(theMuon,radPath);
00625
00626
00627
00628 radPath *= -deltaMom.E()/energyLoss->mostLikelyLoss();
00629 double fac = energyLoss->deltaMom().E()/energyLoss->mostLikelyLoss();
00630
00631
00632 XYZTLorentzVector theNewMomentum = theMuon.momentum() + energyLoss->deltaMom() + fac * deltaMom;
00633 XYZTLorentzVector theNewPosition = theMuon.vertex() + fac * deltaPos;
00634 fac = (theNewMomentum.E()*theNewMomentum.E()-mu*mu)/theNewMomentum.Vect().Mag2();
00635 fac = fac>0.? std::sqrt(fac) : 1E-9;
00636 theMuon.SetXYZT(theNewMomentum.Px()*fac,theNewMomentum.Py()*fac,
00637 theNewMomentum.Pz()*fac,theNewMomentum.E());
00638 theMuon.setVertex(theNewPosition);
00639
00640 }
00641
00642
00643 if ( multipleScattering ) {
00644
00645 GlobalVector normal = nextSurface.tangentPlane(tsos.globalPosition())->normalVector();
00646 multipleScattering->setNormalVector(normal);
00647
00648 multipleScattering->updateState(theMuon,radPath);
00649 }
00650
00651
00652 GlobalPoint propagatedPosition(theMuon.X(),theMuon.Y(),theMuon.Z());
00653 GlobalVector propagatedMomentum(theMuon.Px(),theMuon.Py(),theMuon.Pz());
00654 GlobalTrajectoryParameters propagatedGtp(propagatedPosition,propagatedMomentum,(int)charge,magfield);
00655 tsosWithdEdx = TrajectoryStateOnSurface(propagatedGtp,nextSurface);
00656
00657 }
00658
00659
00660
00661
00662 DEFINE_FWK_MODULE(MuonSimHitProducer);