CMS 3D CMS Logo

TrackingMaterialProducer.cc
Go to the documentation of this file.
1 #include <iostream> // FIXME: switch to MessagLogger & friends
2 #include <vector>
3 #include <string>
4 #include <cassert>
5 #include <exception>
6 #include <tuple>
7 
13 
18 
20 
21 // GEANT4
22 #include "G4Step.hh"
23 #include "G4Track.hh"
24 #include "G4VSolid.hh"
25 #include "G4LogicalVolumeStore.hh"
26 #include "G4TouchableHistory.hh"
27 #include "G4VPhysicalVolume.hh"
28 #include "G4AffineTransform.hh"
29 
31 
32 // Uncomment the following #define directive to have the full list of
33 // volumes known to G4 printed to LogInfo("TrackingMaterialProducer")
34 
35 #define DEBUG_G4_VOLUMES
36 
37 using namespace CLHEP;
38 using edm::LogInfo;
39 
40 // missing from GEANT4 < 9.0 : G4LogicalVolumeStore::GetVolume( name )
41 static const G4LogicalVolume* GetVolume(const std::string& name) {
42  const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
43 
44 #ifdef DEBUG_G4_VOLUMES
45  for (G4LogicalVolumeStore::const_iterator volume = lvs->begin(); volume != lvs->end(); ++volume)
46  LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: G4 registered volumes " << (*volume)->GetName()
47  << std::endl;
48 #endif
49 
50  for (G4LogicalVolumeStore::const_iterator volume = lvs->begin(); volume != lvs->end(); ++volume) {
51  if ((const std::string&)(*volume)->GetName() == name)
52  return (*volume);
53  }
54  return nullptr;
55 }
56 
57 // missing from GEANT4 : G4TouchableHistory::GetTransform( depth )
58 static inline const G4AffineTransform& GetTransform(const G4TouchableHistory* touchable, int depth) {
59  return touchable->GetHistory()->GetTransform(touchable->GetHistory()->GetDepth() - depth);
60 }
61 
62 // navigate up the hierarchy of volumes until one with an attached sensitive detector is found
63 // return a tuple holding
64 // - pointer to the first (deepest) sensitive G4VPhysicalVolume
65 // - how may steps up in the hierarchy it is (0 is the starting volume)
66 // if no sensitive detector is found, return a NULL pointer and 0
67 
68 std::tuple<const G4VPhysicalVolume*, int> GetSensitiveVolume(const G4VTouchable* touchable) {
69  int depth = touchable->GetHistoryDepth();
70  for (int level = 0; level < depth; ++level) { // 0 is self
71  const G4VPhysicalVolume* volume = touchable->GetVolume(level);
72  if (volume->GetLogicalVolume()->GetSensitiveDetector() != nullptr) {
73  return std::make_tuple(volume, level);
74  }
75  }
76  return std::tuple<const G4VPhysicalVolume*, int>(nullptr, 0);
77 }
78 
79 //-------------------------------------------------------------------------
81  edm::ParameterSet config = iPSet.getParameter<edm::ParameterSet>("TrackingMaterialProducer");
82  m_selectedNames = config.getParameter<std::vector<std::string> >("SelectedVolumes");
83  m_primaryTracks = config.getParameter<bool>("PrimaryTracksOnly");
84  m_txtOutFile = config.getUntrackedParameter<std::string>("txtOutFile");
85  m_hgcalzfront = config.getParameter<double>("hgcalzfront");
86  m_tracks = nullptr;
87  m_track_volume = nullptr;
88 
89  produces<std::vector<MaterialAccountingTrack> >();
90  output_file_ = new TFile("radLen_vs_eta_fromProducer.root", "RECREATE");
91  output_file_->cd();
92  radLen_vs_eta_ = new TProfile("radLen", "radLen", 250., -5., 5., 0, 10.);
93 
94  //Check if HGCal volumes are selected
95  isHGCal = false;
96  if (std::find(m_selectedNames.begin(), m_selectedNames.end(), "HGCal") != m_selectedNames.end()) {
97  isHGCal = true;
98  }
99  //Check if HFNose volumes are selected
100  isHFNose = false;
101  if (std::find(m_selectedNames.begin(), m_selectedNames.end(), "HFNose") != m_selectedNames.end()) {
102  isHFNose = true;
103  }
104  if (isHGCal or isHFNose) {
105  outVolumeZpositionTxt.open(m_txtOutFile.c_str(), std::ios::out);
106  }
107 }
108 
109 //-------------------------------------------------------------------------
111 
112 //-------------------------------------------------------------------------
114  radLen_vs_eta_->Write();
115  output_file_->Close();
116 }
117 //-------------------------------------------------------------------------
119  // INFO
120  LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: List of the selected volumes: " << std::endl;
121  for (std::vector<std::string>::const_iterator volume_name = m_selectedNames.begin();
122  volume_name != m_selectedNames.end();
123  ++volume_name) {
124  const G4LogicalVolume* volume = GetVolume(*volume_name);
125  if (volume) {
126  LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: " << *volume_name << std::endl;
127  m_selectedVolumes.push_back(volume);
128  } else {
129  // FIXME: throw an exception ?
130  std::cerr << "TrackingMaterialProducer::update(const BeginOfJob*): WARNING: selected volume \"" << *volume_name
131  << "\" not found in geometry " << std::endl;
132  }
133  }
134 }
135 
136 //-------------------------------------------------------------------------
138  m_tracks = new std::vector<MaterialAccountingTrack>();
139 }
140 
141 //-------------------------------------------------------------------------
143  m_track.reset();
144  m_track_volume = nullptr;
145 
146  // prevent secondary tracks from propagating
147  G4Track* track = const_cast<G4Track*>((*event)());
148  if (m_primaryTracks and track->GetParentID() != 0) {
149  track->SetTrackStatus(fStopAndKill);
150  }
151 
152  //For the HGCal case:
153  //In the beginning of each track, the track will first hit SS and it will
154  //save the upper z volume boundary. So, the low boundary of the first SS
155  //volume is never saved. So, here we give the low boundary hardcoded.
156  //This can be found by running
157  //Geometry/HGCalCommonData/test/testHGCalParameters_cfg.py
158  //on the geometry under study and looking for zFront print out.
159  if (isHGCal && track->GetTrackStatus() != fStopAndKill && fabs(track->GetMomentum().eta()) > outerHGCalEta &&
160  fabs(track->GetMomentum().eta()) < innerHGCalEta) {
161  if (track->GetMomentum().eta() > 0.) {
162  outVolumeZpositionTxt << "StainlessSteel " << m_hgcalzfront << " " << 0 << " " << 0 << " " << 0 << " " << 0
163  << std::endl;
164  } else if (track->GetMomentum().eta() <= 0.) {
165  outVolumeZpositionTxt << "StainlessSteel " << -m_hgcalzfront << " " << 0 << " " << 0 << " " << 0 << " " << 0
166  << std::endl;
167  }
168  }
169 
170  //For the HFnose case:
171  //restrict the outher radius to eta 3.3 since there is HGCAL shadowing
172  //restrict the innner radius to eta 4 since it's non projective
173 
174  if (isHFNose && track->GetTrackStatus() != fStopAndKill && fabs(track->GetMomentum().eta()) > outerHFnoseEta &&
175  fabs(track->GetMomentum().eta()) < innerHFnoseEta) {
176  if (track->GetMomentum().eta() > 0.) {
177  outVolumeZpositionTxt << "Polyethylene " << m_hgcalzfront << " " << 0 << " " << 0 << " " << 0 << " " << 0
178  << std::endl;
179  } else if (track->GetMomentum().eta() <= 0.) {
180  outVolumeZpositionTxt << "Polyethylene " << -m_hgcalzfront << " " << 0 << " " << 0 << " " << 0 << " " << 0
181  << std::endl;
182  }
183  }
184 }
185 
186 bool TrackingMaterialProducer::isSelectedFast(const G4TouchableHistory* touchable) {
187  for (int d = touchable->GetHistoryDepth() - 1; d >= 0; --d) {
188  if (std::find(m_selectedNames.begin(), m_selectedNames.end(), touchable->GetVolume(d)->GetName()) !=
189  m_selectedNames.end())
190  return true;
191  }
192  return false;
193 }
194 
195 //-------------------------------------------------------------------------
197  const G4TouchableHistory* touchable = static_cast<const G4TouchableHistory*>(step->GetTrack()->GetTouchable());
198  if (not isSelectedFast(touchable)) {
199  LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer:\t[...] skipping "
200  << touchable->GetVolume()->GetName() << std::endl;
201  return;
202  }
203 
204  // material and step proterties
205  const G4Material* material = touchable->GetVolume()->GetLogicalVolume()->GetMaterial();
206  double length = step->GetStepLength() / cm; // mm -> cm
207  double X0 = material->GetRadlen() / cm; // mm -> cm
208  double Ne = material->GetElectronDensity() * cm3; // 1/mm3 -> 1/cm3
209  double Xi = Ne / 6.0221415e23 * 0.307075 / 2; // MeV / cm
210  double radiationLengths = length / X0; //
211  double energyLoss = length * Xi / 1000.; // GeV
212  //double energyLoss = step->GetDeltaEnergy()/MeV; should we use this??
213 
214  G4ThreeVector globalPosPre = step->GetPreStepPoint()->GetPosition();
215  G4ThreeVector globalPosPost = step->GetPostStepPoint()->GetPosition();
216  GlobalPoint globalPositionIn(globalPosPre.x() / cm, globalPosPre.y() / cm, globalPosPre.z() / cm); // mm -> cm
217  GlobalPoint globalPositionOut(globalPosPost.x() / cm, globalPosPost.y() / cm, globalPosPost.z() / cm); // mm -> cm
218 
219  G4StepPoint* prePoint = step->GetPreStepPoint();
220  G4StepPoint* postPoint = step->GetPostStepPoint();
221  const CLHEP::Hep3Vector& postPos = postPoint->GetPosition();
222  //Go below only in HGCal case
223  if (isHGCal or isHFNose) {
224  //A step never spans across boundaries: geometry or physics define the end points
225  //If the step is limited by a boundary, the post-step point stands on the
226  //boundary and it logically belongs to the next volume.
227  if (postPoint->GetStepStatus() == fGeomBoundary && fabs(postPoint->GetMomentum().eta()) > outerHGCalEta &&
228  fabs(postPoint->GetMomentum().eta()) < innerHGCalEta) {
229  //Post point position is the low z edge of the new volume, or the upper for the prepoint volume.
230  //So, premat - postz - posteta - postR - premattotalenergylossEtable - premattotalenergylossEfull
231  //Observe the two zeros at the end which in the past where set to emCalculator.GetDEDX and
232  //emCalculator.ComputeTotalDEDX but decided not to be used. Will save the structure though for the script.
233  outVolumeZpositionTxt << prePoint->GetMaterial()->GetName() << " " << postPos.z() << " "
234  << postPoint->GetMomentum().eta() << " "
235  << sqrt(postPos.x() * postPos.x() + postPos.y() * postPos.y()) << " " << 0 << " " << 0
236  << std::endl;
237  }
238 
239  if (postPoint->GetStepStatus() == fGeomBoundary && fabs(postPoint->GetMomentum().eta()) > outerHFnoseEta &&
240  fabs(postPoint->GetMomentum().eta()) < innerHFnoseEta) {
241  outVolumeZpositionTxt << prePoint->GetMaterial()->GetName() << " " << postPos.z() << " "
242  << postPoint->GetMomentum().eta() << " "
243  << sqrt(postPos.x() * postPos.x() + postPos.y() * postPos.y()) << " " << 0 << " " << 0
244  << std::endl;
245  }
246 
247  } //end of isHGCal or HFnose if
248 
249  // check for a sensitive detector
250  bool enter_sensitive = false;
251  bool leave_sensitive = false;
252  double cosThetaPre = 0.0;
253  double cosThetaPost = 0.0;
254  int level = 0;
255  const G4VPhysicalVolume* sensitive = nullptr;
257  std::tie(sensitive, level) = GetSensitiveVolume(touchable);
258  if (sensitive) {
259  const G4VSolid& solid = *touchable->GetSolid(level);
260  const G4AffineTransform& transform = GetTransform(touchable, level);
261  G4ThreeVector pos = transform.Inverse().TransformPoint(G4ThreeVector(0., 0., 0.));
262  position = GlobalPoint(pos.x() / cm, pos.y() / cm, pos.z() / cm); // mm -> cm
263 
264  G4ThreeVector localPosPre = transform.TransformPoint(globalPosPre);
265  EInside statusPre = solid.Inside(localPosPre);
266  if (statusPre == kSurface) {
267  enter_sensitive = true;
268  G4ThreeVector globalDirPre = step->GetPreStepPoint()->GetMomentumDirection();
269  G4ThreeVector localDirPre = transform.TransformAxis(globalDirPre);
270  G4ThreeVector normalPre = solid.SurfaceNormal(localPosPre);
271  cosThetaPre = normalPre.cosTheta(-localDirPre);
272  }
273 
274  G4ThreeVector localPosPost = transform.TransformPoint(globalPosPost);
275  EInside statusPost = solid.Inside(localPosPost);
276  if (statusPost == kSurface) {
277  leave_sensitive = true;
278  G4ThreeVector globalDirPost = step->GetPostStepPoint()->GetMomentumDirection();
279  G4ThreeVector localDirPost = transform.TransformAxis(globalDirPost);
280  G4ThreeVector normalPost = solid.SurfaceNormal(localPosPost);
281  cosThetaPost = normalPost.cosTheta(localDirPost);
282  }
283  }
284 
285  // update track accounting
286  if (enter_sensitive) {
287  if (m_track_volume != nullptr) {
288  edm::LogWarning("TrackingMaterialProducer") << "Entering volume " << sensitive << " while inside volume "
289  << m_track_volume << ". Something is inconsistent";
290  m_track.reset();
291  }
292  m_track_volume = sensitive;
293  m_track.enterDetector(position, cosThetaPre);
294  }
295  m_track.step(MaterialAccountingStep(length, radiationLengths, energyLoss, globalPositionIn, globalPositionOut));
296  if (leave_sensitive) {
297  if (m_track_volume != sensitive) {
298  edm::LogWarning("TrackingMaterialProducer") << "Leaving volume " << sensitive << " while inside volume "
299  << m_track_volume << ". Something is inconsistent";
300  m_track.reset();
301  } else
302  m_track.leaveDetector(cosThetaPost);
303  m_track_volume = nullptr;
304  }
305  if (sensitive)
306  LogInfo("TrackingMaterialProducer") << "Track was near sensitive volume " << sensitive->GetName() << std::endl;
307  else
308  LogInfo("TrackingMaterialProducer") << "Track was near non-sensitive volume " << touchable->GetVolume()->GetName()
309  << std::endl;
310  LogInfo("TrackingMaterialProducer") << "Step length: " << length << " cm\n"
311  << "globalPreStep(r,z): (" << globalPositionIn.perp() << ", "
312  << globalPositionIn.z() << ") cm\n"
313  << "globalPostStep(r,z): (" << globalPositionOut.perp() << ", "
314  << globalPositionOut.z() << ") cm\n"
315  << "position(r,z): (" << position.perp() << ", " << position.z() << ") cm\n"
316  << "Radiation lengths: " << radiationLengths << " \t\t(X0: " << X0
317  << " cm)\n"
318  << "Energy loss: " << energyLoss << " MeV \t(Xi: " << Xi
319  << " MeV/cm)\n"
320  << "Track was " << (enter_sensitive ? "entering " : "in none ")
321  << "sensitive volume\n"
322  << "Track was " << (leave_sensitive ? "leaving " : "in none ")
323  << "sensitive volume\n";
324 }
325 
326 //-------------------------------------------------------------------------
328  const G4Track* track = (*event)();
329  if (m_primaryTracks and track->GetParentID() != 0)
330  return;
331 
332  radLen_vs_eta_->Fill(track->GetMomentum().eta(), m_track.summary().radiationLengths());
333  m_tracks->push_back(m_track);
334 
335  // LogInfo
336  LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: this track took " << m_track.steps().size()
337  << " steps, and passed through " << m_track.detectors().size()
338  << " sensitive detectors" << std::endl;
339  LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: track length: " << m_track.summary().length()
340  << " cm" << std::endl;
341  LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: radiation lengths: "
342  << m_track.summary().radiationLengths() << std::endl;
343  LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: energy loss: "
344  << m_track.summary().energyLoss() << " MeV" << std::endl;
345 }
346 
347 //-------------------------------------------------------------------------
349  // transfer ownership to the Event
350  std::unique_ptr<std::vector<MaterialAccountingTrack> > tracks(m_tracks);
351  iEvent.put(std::move(tracks));
352  m_tracks = nullptr;
353 }
354 
355 //-------------------------------------------------------------------------
356 bool TrackingMaterialProducer::isSelected(const G4VTouchable* touchable) {
357  for (size_t i = 0; i < m_selectedVolumes.size(); ++i)
358  if (m_selectedVolumes[i]->IsAncestor(touchable->GetVolume()) or
359  m_selectedVolumes[i] == touchable->GetVolume()->GetLogicalVolume())
360  return true;
361 
362  return false;
363 }
364 
365 //-------------------------------------------------------------------------
366 // define as a plugin
personalPlayback.level
level
Definition: personalPlayback.py:22
mps_fire.i
i
Definition: mps_fire.py:428
TrackingMaterialProducer.h
HLT_FULL_cff.track
track
Definition: HLT_FULL_cff.py:11713
MessageLogger.h
TrackingMaterialProducer::isSelectedFast
bool isSelectedFast(const G4TouchableHistory *touch)
Definition: TrackingMaterialProducer.cc:186
ESHandle.h
BeginOfJob.h
step
step
Definition: StallMonitor.cc:94
pos
Definition: PixelAliasList.h:18
EndOfTrack.h
edm::LogInfo
Log< level::Info, false > LogInfo
Definition: MessageLogger.h:125
spr::find
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
edm::LogWarning
Log< level::Warning, false > LogWarning
Definition: MessageLogger.h:122
GetTransform
static const G4AffineTransform & GetTransform(const G4TouchableHistory *touchable, int depth)
Definition: TrackingMaterialProducer.cc:58
EndOfTrack
Definition: EndOfTrack.h:6
BeginOfTrack.h
PV3DBase::z
T z() const
Definition: PV3DBase.h:61
config
Definition: config.py:1
DEFINE_SIMWATCHER
#define DEFINE_SIMWATCHER(type)
Definition: SimWatcherFactory.h:13
MakerMacros.h
TrackingMaterialProducer::isSelected
bool isSelected(const G4VTouchable *touch)
Definition: TrackingMaterialProducer.cc:356
mathSSE::sqrt
T sqrt(T t)
Definition: SSEVec.h:19
BeginOfTrack
Definition: BeginOfTrack.h:6
HcalDetIdTransform::transform
unsigned transform(const HcalDetId &id, unsigned transformCode)
Definition: HcalDetIdTransform.cc:7
BeginOfJob
Definition: BeginOfJob.h:8
GlobalPoint
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
TrackingMaterialProducer::update
void update(const BeginOfJob *) override
This routine will be called when the appropriate signal arrives.
Definition: TrackingMaterialProducer.cc:118
Point3DBase< float, GlobalTag >
LEDCalibrationChannels.depth
depth
Definition: LEDCalibrationChannels.py:65
CLHEP
Definition: CocoaGlobals.h:27
AlCaHLTBitMon_QueryRunRegistry.string
string
Definition: AlCaHLTBitMon_QueryRunRegistry.py:256
edm::ParameterSet
Definition: ParameterSet.h:47
Event.h
tracks
const uint32_t *__restrict__ const HitContainer *__restrict__ TkSoA *__restrict__ tracks
Definition: CAHitNtupletGeneratorKernelsImpl.h:159
SimWatcherFactory.h
GetVolume
static const G4LogicalVolume * GetVolume(const std::string &name)
Definition: TrackingMaterialProducer.cc:41
BeginOfEvent.h
position
static int position[264][3]
Definition: ReadPGInfo.cc:289
iEvent
int iEvent
Definition: GenABIO.cc:224
BeginOfEvent
Definition: BeginOfEvent.h:6
edm::EventSetup
Definition: EventSetup.h:58
MonitorAlCaEcalPi0_cfi.X0
X0
Definition: MonitorAlCaEcalPi0_cfi.py:77
TrackingMaterialProducer::~TrackingMaterialProducer
~TrackingMaterialProducer() override
Definition: TrackingMaterialProducer.cc:110
MaterialAccountingStep
Definition: MaterialAccountingStep.h:9
eostools.move
def move(src, dest)
Definition: eostools.py:511
TrackingMaterialProducer
Definition: TrackingMaterialProducer.h:33
trackingMaterialAnalyser_cfi.isHGCal
isHGCal
Definition: trackingMaterialAnalyser_cfi.py:12
trackingMaterialAnalyser_ForHFNosePhaseII_cfi.isHFNose
isHFNose
Definition: trackingMaterialAnalyser_ForHFNosePhaseII_cfi.py:13
Skims_PA_cff.name
name
Definition: Skims_PA_cff.py:17
EventSetup.h
or
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventID const &, edm::Timestamp const & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
edm::ParameterSet::getParameter
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
TrackingMaterialProducer::TrackingMaterialProducer
TrackingMaterialProducer(const edm::ParameterSet &)
Definition: TrackingMaterialProducer.cc:80
TrackingMaterialProducer::produce
void produce(edm::Event &, const edm::EventSetup &) override
Definition: TrackingMaterialProducer.cc:348
MillePedeFileConverter_cfg.out
out
Definition: MillePedeFileConverter_cfg.py:31
ztail.d
d
Definition: ztail.py:151
ParameterSet.h
event
Definition: event.py:1
edm::Event
Definition: Event.h:73
EcnaPython_AdcPeg12_S1_10_R170298_1_0_150_Dee0.cerr
cerr
Definition: EcnaPython_AdcPeg12_S1_10_R170298_1_0_150_Dee0.py:8
fastSimProducer_cff.energyLoss
energyLoss
Definition: fastSimProducer_cff.py:55
GlobalPoint.h
GetSensitiveVolume
std::tuple< const G4VPhysicalVolume *, int > GetSensitiveVolume(const G4VTouchable *touchable)
Definition: TrackingMaterialProducer.cc:68