CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
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 <boost/tuple/tuple.hpp>
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 LogDebug("TrackingMaterialProducer")
34 
35 #define DEBUG_G4_VOLUMES
36 
37 using namespace CLHEP;
38 
39 // missing from GEANT4 < 9.0 : G4LogicalVolumeStore::GetVolume( name )
40 static
41 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  LogDebug("TrackingMaterialProducer") << "TrackingMaterialProducer: G4 registered volumes "
47  << (*volume)->GetName() << 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 0;
55 }
56 
57 // missing from GEANT4 : G4TouchableHistory::GetTransform( depth )
58 static inline
59 const G4AffineTransform& GetTransform(const G4TouchableHistory* touchable, int depth)
60 {
61  return touchable->GetHistory()->GetTransform( touchable->GetHistory()->GetDepth() - depth );
62 }
63 
64 // navigate up the hierarchy of volumes until one with an attached sensitive detector is found
65 // return a tuple holding
66 // - pointer to the first (deepest) sensitive G4VPhysicalVolume
67 // - how may steps up in the hierarchy it is (0 is the starting volume)
68 // if no sensitive detector is found, return a NULL pointer and 0
69 
70 boost::tuple<const G4VPhysicalVolume*, int> GetSensitiveVolume( const G4VTouchable* touchable )
71 {
72  int depth = touchable->GetHistoryDepth();
73  for (int level = 0; level < depth; ++level) { // 0 is self
74  const G4VPhysicalVolume* volume = touchable->GetVolume(level);
75  if (volume->GetLogicalVolume()->GetSensitiveDetector() != 0) {
76  return boost::make_tuple(volume, level);
77  }
78  }
79  return boost::tuple<const G4VPhysicalVolume*, int>(0, 0);
80 }
81 
82 //-------------------------------------------------------------------------
84 {
85  edm::ParameterSet config = iPSet.getParameter<edm::ParameterSet>("TrackingMaterialProducer");
86  m_selectedNames = config.getParameter< std::vector<std::string> >("SelectedVolumes");
87  m_primaryTracks = config.getParameter<bool>("PrimaryTracksOnly");
88  m_tracks = 0;
89 
90  produces< std::vector<MaterialAccountingTrack> >();
91 }
92 
93 //-------------------------------------------------------------------------
95 {
96 }
97 
98 //-------------------------------------------------------------------------
100 {
101  // INFO
102  LogDebug("TrackingMaterialProducer") << "TrackingMaterialProducer: List of the selected volumes: " << std::endl;
103  for (std::vector<std::string>::const_iterator volume_name = m_selectedNames.begin();
104  volume_name != m_selectedNames.end(); ++volume_name) {
105  const G4LogicalVolume* volume = GetVolume(*volume_name);
106  if (volume) {
107  LogDebug("TrackingMaterialProducer") << "TrackingMaterialProducer: " << *volume_name << std::endl;
108  m_selectedVolumes.push_back( volume );
109  } else {
110  // FIXME: throw an exception ?
111  std::cerr << "TrackingMaterialProducer::update(const BeginOfJob*): WARNING: selected volume \"" << *volume_name << "\" not found in geometry " << std::endl;
112  }
113  }
114 }
115 
116 
117 //-------------------------------------------------------------------------
119 {
120  m_tracks = new std::vector<MaterialAccountingTrack>();
121 }
122 
123 
124 //-------------------------------------------------------------------------
126 {
127  m_track.reset();
128 
129  // prevent secondary tracks from propagating
130  G4Track* track = const_cast<G4Track*>((*event)());
131  if (m_primaryTracks and track->GetParentID() != 0) {
132  track->SetTrackStatus(fStopAndKill);
133  }
134 }
135 
136 
137 //-------------------------------------------------------------------------
139 {
140  const G4TouchableHistory* touchable = (G4TouchableHistory*)(step->GetTrack()->GetTouchable());
141  if (not isSelected( touchable )) {
142  LogDebug("TrackingMaterialProducer") << "TrackingMaterialProducer:\t[...] skipping "
143  << touchable->GetVolume()->GetName() << std::endl;
144  return;
145  }
146 
147  // material and step proterties
148  const G4Material* material = touchable->GetVolume()->GetLogicalVolume()->GetMaterial();
149  double length = step->GetStepLength() / cm; // mm -> cm
150  double X0 = material->GetRadlen() / cm; // mm -> cm
151  double Ne = material->GetElectronDensity() * cm3; // 1/mm3 -> 1/cm3
152  double Xi = Ne / 6.0221415e23 * 0.307075 / 2; // MeV / cm
153  double radiationLengths = length / X0; //
154  double energyLoss = length * Xi / 1000.; // GeV
155  //double energyLoss = step->GetDeltaEnergy()/MeV; should we use this??
156 
157  G4ThreeVector globalPosPre = step->GetPreStepPoint()->GetPosition();
158  G4ThreeVector globalPosPost = step->GetPostStepPoint()->GetPosition();
159  GlobalPoint globalPositionIn( globalPosPre.x() / cm, globalPosPre.y() / cm, globalPosPre.z() / cm ); // mm -> cm
160  GlobalPoint globalPositionOut( globalPosPost.x() / cm, globalPosPost.y() / cm, globalPosPost.z() / cm ); // mm -> cm
161 
162  // check for a sensitive detector
163  bool enter_sensitive = false;
164  bool leave_sensitive = false;
165  double cosThetaPre = 0.0;
166  double cosThetaPost = 0.0;
167  int level = 0;
168  const G4VPhysicalVolume* sensitive = 0;
170  boost::tuples::tie(sensitive, level) = GetSensitiveVolume(touchable);
171  if (sensitive) {
172  const G4VSolid & solid = *touchable->GetSolid( level );
173  const G4AffineTransform & transform = GetTransform( touchable, level );
174  G4ThreeVector pos = transform.Inverse().TransformPoint( G4ThreeVector( 0., 0., 0. ) );
175  position = GlobalPoint( pos.x() / cm, pos.y() / cm, pos.z() / cm ); // mm -> cm
176 
177  G4ThreeVector localPosPre = transform.TransformPoint( globalPosPre );
178  EInside statusPre = solid.Inside( localPosPre );
179  if (statusPre == kSurface) {
180  enter_sensitive = true;
181  G4ThreeVector globalDirPre = step->GetPreStepPoint()->GetMomentumDirection();
182  G4ThreeVector localDirPre = transform.TransformAxis( globalDirPre );
183  G4ThreeVector normalPre = solid.SurfaceNormal( localPosPre );
184  cosThetaPre = normalPre.cosTheta( -localDirPre );
185  }
186 
187  G4ThreeVector localPosPost = transform.TransformPoint( globalPosPost );
188  EInside statusPost = solid.Inside( localPosPost );
189  if (statusPost == kSurface) {
190  leave_sensitive = true;
191  G4ThreeVector globalDirPost = step->GetPostStepPoint()->GetMomentumDirection();
192  G4ThreeVector localDirPost = transform.TransformAxis( globalDirPost );
193  G4ThreeVector normalPost = solid.SurfaceNormal( localPosPost );
194  cosThetaPost = normalPost.cosTheta( localDirPost );
195  }
196  }
197 
198  // update track accounting
199  if (enter_sensitive)
200  m_track.enterDetector( sensitive, position, cosThetaPre );
201  m_track.step(MaterialAccountingStep( length, radiationLengths, energyLoss, globalPositionIn, globalPositionOut ));
202  if (leave_sensitive)
203  m_track.leaveDetector( sensitive, cosThetaPost );
204 
205  if (sensitive)
206  LogDebug("TrackingMaterialProducer") << "Track was near sensitive volume "
207  << sensitive->GetName() << std::endl;
208  else
209  LogDebug("TrackingMaterialProducer") << "Track was near non-sensitive volume "
210  << touchable->GetVolume()->GetName() << std::endl;
211  LogDebug("TrackingMaterialProducer") << "Step length: "
212  << length << " cm" << std::endl;
213  LogDebug("TrackingMaterialProducer") << "Radiation lengths: "
214  << radiationLengths << " \t\t(X0: "
215  << X0 << " cm)" << std::endl;
216  LogDebug("TrackingMaterialProducer") << "Energy loss: "
217  << energyLoss << " MeV \t(Xi: "
218  << Xi << " MeV/cm)" << std::endl;
219  LogDebug("TrackingMaterialProducer") << "Track was " << (enter_sensitive ? "entering " : "in none ")
220  << "sensitive volume" << std::endl;
221  LogDebug("TrackingMaterialProducer") << "Track was " << (leave_sensitive ? "leaving " : "in none ")
222  << "sensitive volume" << std::endl;
223 
224 }
225 
226 
227 //-------------------------------------------------------------------------
229 {
230  const G4Track * track = (*event)();
231  if (m_primaryTracks and track->GetParentID() != 0)
232  return;
233 
234  m_tracks->push_back(m_track);
235 
236  // LogDebug
237  LogDebug("TrackingMaterialProducer") << "TrackingMaterialProducer: this track took "
238  << m_track.steps().size()
239  << " steps, and passed through "
240  << m_track.detectors().size()
241  << " sensitive detectors" << std::endl;
242  LogDebug("TrackingMaterialProducer") << "TrackingMaterialProducer: track length: "
243  << m_track.summary().length()
244  << " cm" << std::endl;
245  LogDebug("TrackingMaterialProducer") << "TrackingMaterialProducer: radiation lengths: "
246  << m_track.summary().radiationLengths() << std::endl;
247  LogDebug("TrackingMaterialProducer") << "TrackingMaterialProducer: energy loss: "
248  << m_track.summary().energyLoss()
249  << " MeV" << std::endl;
250 }
251 
252 //-------------------------------------------------------------------------
254 {
255  // transfer ownership to the Event
256  std::auto_ptr<std::vector<MaterialAccountingTrack> > tracks( m_tracks );
257  iEvent.put( tracks );
258  m_tracks = 0;
259 }
260 
261 //-------------------------------------------------------------------------
262 bool TrackingMaterialProducer::isSelected( const G4VTouchable* touchable )
263 {
264  for (size_t i = 0; i < m_selectedVolumes.size(); ++i)
265  if (m_selectedVolumes[i]->IsAncestor( touchable->GetVolume() )
266  or m_selectedVolumes[i] == touchable->GetVolume()->GetLogicalVolume())
267  return true;
268 
269  return false;
270 }
271 
272 //-------------------------------------------------------------------------
273 // define as a plugin
#define LogDebug(id)
T getParameter(std::string const &) const
int i
Definition: DBlmapReader.cc:9
#define DEFINE_SIMWATCHER(type)
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::EventIDconst &, edm::Timestampconst & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
Definition: Activities.doc:12
void produce(edm::Event &, const edm::EventSetup &)
Global3DPoint GlobalPoint
Definition: GlobalPoint.h:10
TrackingMaterialProducer(const edm::ParameterSet &)
static const G4AffineTransform & GetTransform(const G4TouchableHistory *touchable, int depth)
int iEvent
Definition: GenABIO.cc:230
OrphanHandle< PROD > put(std::auto_ptr< PROD > product)
Put a new product.
Definition: Event.h:120
boost::tuple< const G4VPhysicalVolume *, int > GetSensitiveVolume(const G4VTouchable *touchable)
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger but the state exists so we define the behavior If all triggers are the negative crieriion will lead to accepting the event(this again matches the behavior of"!*"before the partial wildcard feature was incorporated).The per-event"cost"of each negative criterion with multiple relevant triggers is about the same as!*was in the past
static const G4LogicalVolume * GetVolume(const std::string &name)
tuple tracks
Definition: testEve_cfg.py:39
void update(const BeginOfJob *)
This routine will be called when the appropriate signal arrives.
static int position[264][3]
Definition: ReadPGInfo.cc:509
tuple level
Definition: testEve_cfg.py:34
static const double X0
bool isSelected(const G4VTouchable *touch)