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 
88  produces<std::vector<MaterialAccountingTrack> >();
89  output_file_ = new TFile("radLen_vs_eta_fromProducer.root", "RECREATE");
90  output_file_->cd();
91  radLen_vs_eta_ = new TProfile("radLen", "radLen", 250., -5., 5., 0, 10.);
92 
93  //Check if HGCal volumes are selected
94  isHGCal = false;
95  if (std::find(m_selectedNames.begin(), m_selectedNames.end(), "HGCal") != m_selectedNames.end()) {
96  isHGCal = true;
97  }
98  //Check if HFNose volumes are selected
99  isHFNose = false;
100  if (std::find(m_selectedNames.begin(), m_selectedNames.end(), "HFNose") != m_selectedNames.end()) {
101  isHFNose = true;
102  }
103  if (isHGCal or isHFNose) {
104  outVolumeZpositionTxt.open(m_txtOutFile.c_str(), std::ios::out);
105  }
106 }
107 
108 //-------------------------------------------------------------------------
110 
111 //-------------------------------------------------------------------------
113  radLen_vs_eta_->Write();
114  output_file_->Close();
115 }
116 //-------------------------------------------------------------------------
118  // INFO
119  LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: List of the selected volumes: " << std::endl;
120  for (std::vector<std::string>::const_iterator volume_name = m_selectedNames.begin();
121  volume_name != m_selectedNames.end();
122  ++volume_name) {
123  const G4LogicalVolume* volume = GetVolume(*volume_name);
124  if (volume) {
125  LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: " << *volume_name << std::endl;
126  m_selectedVolumes.push_back(volume);
127  } else {
128  // FIXME: throw an exception ?
129  std::cerr << "TrackingMaterialProducer::update(const BeginOfJob*): WARNING: selected volume \"" << *volume_name
130  << "\" not found in geometry " << std::endl;
131  }
132  }
133 }
134 
135 //-------------------------------------------------------------------------
137  m_tracks = new std::vector<MaterialAccountingTrack>();
138 }
139 
140 //-------------------------------------------------------------------------
142  m_track.reset();
143 
144  // prevent secondary tracks from propagating
145  G4Track* track = const_cast<G4Track*>((*event)());
146  if (m_primaryTracks and track->GetParentID() != 0) {
147  track->SetTrackStatus(fStopAndKill);
148  }
149 
150  //For the HGCal case:
151  //In the beginning of each track, the track will first hit SS and it will
152  //save the upper z volume boundary. So, the low boundary of the first SS
153  //volume is never saved. So, here we give the low boundary hardcoded.
154  //This can be found by running
155  //Geometry/HGCalCommonData/test/testHGCalParameters_cfg.py
156  //on the geometry under study and looking for zFront print out.
157  if (isHGCal && track->GetTrackStatus() != fStopAndKill && fabs(track->GetMomentum().eta()) > outerHGCalEta &&
158  fabs(track->GetMomentum().eta()) < innerHGCalEta) {
159  if (track->GetMomentum().eta() > 0.) {
160  outVolumeZpositionTxt << "StainlessSteel " << m_hgcalzfront << " " << 0 << " " << 0 << " " << 0 << " " << 0
161  << std::endl;
162  } else if (track->GetMomentum().eta() <= 0.) {
163  outVolumeZpositionTxt << "StainlessSteel " << -m_hgcalzfront << " " << 0 << " " << 0 << " " << 0 << " " << 0
164  << std::endl;
165  }
166  }
167 
168  //For the HFnose case:
169  //restrict the outher radius to eta 3.3 since there is HGCAL shadowing
170  //restrict the innner radius to eta 4 since it's non projective
171 
172  if (isHFNose && track->GetTrackStatus() != fStopAndKill && fabs(track->GetMomentum().eta()) > outerHFnoseEta &&
173  fabs(track->GetMomentum().eta()) < innerHFnoseEta) {
174  if (track->GetMomentum().eta() > 0.) {
175  outVolumeZpositionTxt << "Polyethylene " << m_hgcalzfront << " " << 0 << " " << 0 << " " << 0 << " " << 0
176  << std::endl;
177  } else if (track->GetMomentum().eta() <= 0.) {
178  outVolumeZpositionTxt << "Polyethylene " << -m_hgcalzfront << " " << 0 << " " << 0 << " " << 0 << " " << 0
179  << std::endl;
180  }
181  }
182 }
183 
184 bool TrackingMaterialProducer::isSelectedFast(const G4TouchableHistory* touchable) {
185  for (int d = touchable->GetHistoryDepth() - 1; d >= 0; --d) {
186  if (std::find(m_selectedNames.begin(), m_selectedNames.end(), touchable->GetVolume(d)->GetName()) !=
187  m_selectedNames.end())
188  return true;
189  }
190  return false;
191 }
192 
193 //-------------------------------------------------------------------------
195  const G4TouchableHistory* touchable = static_cast<const G4TouchableHistory*>(step->GetTrack()->GetTouchable());
196  if (not isSelectedFast(touchable)) {
197  LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer:\t[...] skipping "
198  << touchable->GetVolume()->GetName() << std::endl;
199  return;
200  }
201 
202  // material and step proterties
203  const G4Material* material = touchable->GetVolume()->GetLogicalVolume()->GetMaterial();
204  double length = step->GetStepLength() / cm; // mm -> cm
205  double X0 = material->GetRadlen() / cm; // mm -> cm
206  double Ne = material->GetElectronDensity() * cm3; // 1/mm3 -> 1/cm3
207  double Xi = Ne / 6.0221415e23 * 0.307075 / 2; // MeV / cm
208  double radiationLengths = length / X0; //
209  double energyLoss = length * Xi / 1000.; // GeV
210  //double energyLoss = step->GetDeltaEnergy()/MeV; should we use this??
211 
212  G4ThreeVector globalPosPre = step->GetPreStepPoint()->GetPosition();
213  G4ThreeVector globalPosPost = step->GetPostStepPoint()->GetPosition();
214  GlobalPoint globalPositionIn(globalPosPre.x() / cm, globalPosPre.y() / cm, globalPosPre.z() / cm); // mm -> cm
215  GlobalPoint globalPositionOut(globalPosPost.x() / cm, globalPosPost.y() / cm, globalPosPost.z() / cm); // mm -> cm
216 
217  G4StepPoint* prePoint = step->GetPreStepPoint();
218  G4StepPoint* postPoint = step->GetPostStepPoint();
219  const CLHEP::Hep3Vector& postPos = postPoint->GetPosition();
220  //Go below only in HGCal case
221  if (isHGCal or isHFNose) {
222  //A step never spans across boundaries: geometry or physics define the end points
223  //If the step is limited by a boundary, the post-step point stands on the
224  //boundary and it logically belongs to the next volume.
225  if (postPoint->GetStepStatus() == fGeomBoundary && fabs(postPoint->GetMomentum().eta()) > outerHGCalEta &&
226  fabs(postPoint->GetMomentum().eta()) < innerHGCalEta) {
227  //Post point position is the low z edge of the new volume, or the upper for the prepoint volume.
228  //So, premat - postz - posteta - postR - premattotalenergylossEtable - premattotalenergylossEfull
229  //Observe the two zeros at the end which in the past where set to emCalculator.GetDEDX and
230  //emCalculator.ComputeTotalDEDX but decided not to be used. Will save the structure though for the script.
231  outVolumeZpositionTxt << prePoint->GetMaterial()->GetName() << " " << postPos.z() << " "
232  << postPoint->GetMomentum().eta() << " "
233  << sqrt(postPos.x() * postPos.x() + postPos.y() * postPos.y()) << " " << 0 << " " << 0
234  << std::endl;
235  }
236 
237  if (postPoint->GetStepStatus() == fGeomBoundary && fabs(postPoint->GetMomentum().eta()) > outerHFnoseEta &&
238  fabs(postPoint->GetMomentum().eta()) < innerHFnoseEta) {
239  outVolumeZpositionTxt << prePoint->GetMaterial()->GetName() << " " << postPos.z() << " "
240  << postPoint->GetMomentum().eta() << " "
241  << sqrt(postPos.x() * postPos.x() + postPos.y() * postPos.y()) << " " << 0 << " " << 0
242  << std::endl;
243  }
244 
245  } //end of isHGCal or HFnose if
246 
247  // check for a sensitive detector
248  bool enter_sensitive = false;
249  bool leave_sensitive = false;
250  double cosThetaPre = 0.0;
251  double cosThetaPost = 0.0;
252  int level = 0;
253  const G4VPhysicalVolume* sensitive = nullptr;
255  std::tie(sensitive, level) = GetSensitiveVolume(touchable);
256  if (sensitive) {
257  const G4VSolid& solid = *touchable->GetSolid(level);
258  const G4AffineTransform& transform = GetTransform(touchable, level);
259  G4ThreeVector pos = transform.Inverse().TransformPoint(G4ThreeVector(0., 0., 0.));
260  position = GlobalPoint(pos.x() / cm, pos.y() / cm, pos.z() / cm); // mm -> cm
261 
262  G4ThreeVector localPosPre = transform.TransformPoint(globalPosPre);
263  EInside statusPre = solid.Inside(localPosPre);
264  if (statusPre == kSurface) {
265  enter_sensitive = true;
266  G4ThreeVector globalDirPre = step->GetPreStepPoint()->GetMomentumDirection();
267  G4ThreeVector localDirPre = transform.TransformAxis(globalDirPre);
268  G4ThreeVector normalPre = solid.SurfaceNormal(localPosPre);
269  cosThetaPre = normalPre.cosTheta(-localDirPre);
270  }
271 
272  G4ThreeVector localPosPost = transform.TransformPoint(globalPosPost);
273  EInside statusPost = solid.Inside(localPosPost);
274  if (statusPost == kSurface) {
275  leave_sensitive = true;
276  G4ThreeVector globalDirPost = step->GetPostStepPoint()->GetMomentumDirection();
277  G4ThreeVector localDirPost = transform.TransformAxis(globalDirPost);
278  G4ThreeVector normalPost = solid.SurfaceNormal(localPosPost);
279  cosThetaPost = normalPost.cosTheta(localDirPost);
280  }
281  }
282 
283  // update track accounting
284  if (enter_sensitive)
285  m_track.enterDetector(sensitive, position, cosThetaPre);
286  m_track.step(MaterialAccountingStep(length, radiationLengths, energyLoss, globalPositionIn, globalPositionOut));
287  if (leave_sensitive)
288  m_track.leaveDetector(sensitive, cosThetaPost);
289 
290  if (sensitive)
291  LogInfo("TrackingMaterialProducer") << "Track was near sensitive volume " << sensitive->GetName() << std::endl;
292  else
293  LogInfo("TrackingMaterialProducer") << "Track was near non-sensitive volume " << touchable->GetVolume()->GetName()
294  << std::endl;
295  LogInfo("TrackingMaterialProducer") << "Step length: " << length << " cm\n"
296  << "globalPreStep(r,z): (" << globalPositionIn.perp() << ", "
297  << globalPositionIn.z() << ") cm\n"
298  << "globalPostStep(r,z): (" << globalPositionOut.perp() << ", "
299  << globalPositionOut.z() << ") cm\n"
300  << "position(r,z): (" << position.perp() << ", " << position.z() << ") cm\n"
301  << "Radiation lengths: " << radiationLengths << " \t\t(X0: " << X0
302  << " cm)\n"
303  << "Energy loss: " << energyLoss << " MeV \t(Xi: " << Xi
304  << " MeV/cm)\n"
305  << "Track was " << (enter_sensitive ? "entering " : "in none ")
306  << "sensitive volume\n"
307  << "Track was " << (leave_sensitive ? "leaving " : "in none ")
308  << "sensitive volume\n";
309 }
310 
311 //-------------------------------------------------------------------------
313  const G4Track* track = (*event)();
314  if (m_primaryTracks and track->GetParentID() != 0)
315  return;
316 
317  radLen_vs_eta_->Fill(track->GetMomentum().eta(), m_track.summary().radiationLengths());
318  m_tracks->push_back(m_track);
319 
320  // LogInfo
321  LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: this track took " << m_track.steps().size()
322  << " steps, and passed through " << m_track.detectors().size()
323  << " sensitive detectors" << std::endl;
324  LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: track length: " << m_track.summary().length()
325  << " cm" << std::endl;
326  LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: radiation lengths: "
327  << m_track.summary().radiationLengths() << std::endl;
328  LogInfo("TrackingMaterialProducer") << "TrackingMaterialProducer: energy loss: "
329  << m_track.summary().energyLoss() << " MeV" << std::endl;
330 }
331 
332 //-------------------------------------------------------------------------
334  // transfer ownership to the Event
335  std::unique_ptr<std::vector<MaterialAccountingTrack> > tracks(m_tracks);
336  iEvent.put(std::move(tracks));
337  m_tracks = nullptr;
338 }
339 
340 //-------------------------------------------------------------------------
341 bool TrackingMaterialProducer::isSelected(const G4VTouchable* touchable) {
342  for (size_t i = 0; i < m_selectedVolumes.size(); ++i)
343  if (m_selectedVolumes[i]->IsAncestor(touchable->GetVolume()) or
344  m_selectedVolumes[i] == touchable->GetVolume()->GetLogicalVolume())
345  return true;
346 
347  return false;
348 }
349 
350 //-------------------------------------------------------------------------
351 // define as a plugin
personalPlayback.level
level
Definition: personalPlayback.py:22
PDWG_EXOHSCP_cff.tracks
tracks
Definition: PDWG_EXOHSCP_cff.py:28
mps_fire.i
i
Definition: mps_fire.py:355
TrackingMaterialProducer.h
MessageLogger.h
TrackingMaterialProducer::isSelectedFast
bool isSelectedFast(const G4TouchableHistory *touch)
Definition: TrackingMaterialProducer.cc:184
ESHandle.h
BeginOfJob.h
step
step
Definition: StallMonitor.cc:94
pos
Definition: PixelAliasList.h:18
edm::LogInfo
Definition: MessageLogger.h:254
EndOfTrack.h
spr::find
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
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:341
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:117
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:36
Event.h
SimWatcherFactory.h
beam_dqm_sourceclient-live_cfg.cerr
cerr
Definition: beam_dqm_sourceclient-live_cfg.py:17
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:57
MonitorAlCaEcalPi0_cfi.X0
X0
Definition: MonitorAlCaEcalPi0_cfi.py:77
TrackingMaterialProducer::~TrackingMaterialProducer
~TrackingMaterialProducer() override
Definition: TrackingMaterialProducer.cc:109
edm::ParameterSet::getParameter
T getParameter(std::string const &) const
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
TrackingMaterialProducer::TrackingMaterialProducer
TrackingMaterialProducer(const edm::ParameterSet &)
Definition: TrackingMaterialProducer.cc:80
TrackingMaterialProducer::produce
void produce(edm::Event &, const edm::EventSetup &) override
Definition: TrackingMaterialProducer.cc:333
MillePedeFileConverter_cfg.out
out
Definition: MillePedeFileConverter_cfg.py:31
HLT_2018_cff.track
track
Definition: HLT_2018_cff.py:10352
ztail.d
d
Definition: ztail.py:151
ParameterSet.h
event
Definition: event.py:1
edm::Event
Definition: Event.h:73
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