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 
12 
17 
19 
20 // GEANT4
21 #include "G4Step.hh"
22 #include "G4Track.hh"
23 #include "G4VSolid.hh"
24 #include "G4LogicalVolumeStore.hh"
25 #include "G4TouchableHistory.hh"
26 #include "G4VPhysicalVolume.hh"
27 #include "G4AffineTransform.hh"
28 
30 
31 using namespace CLHEP;
32 
33 // missing from GEANT4 < 9.0 : G4LogicalVolumeStore::GetVolume( name )
34 static
35 const G4LogicalVolume* GetVolume(const std::string& name) {
36  const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
37 
38  for (G4LogicalVolumeStore::const_iterator volume = lvs->begin(); volume != lvs->end(); ++volume) {
39  if ((const std::string&) (*volume)->GetName() == name)
40  return (*volume);
41  }
42 
43  return 0;
44 }
45 
46 // missing from GEANT4 : G4TouchableHistory::GetTransform( depth )
47 static inline
48 const G4AffineTransform& GetTransform(const G4TouchableHistory* touchable, int depth)
49 {
50  return touchable->GetHistory()->GetTransform( touchable->GetHistory()->GetDepth() - depth );
51 }
52 
53 // navigate up the hierarchy of volumes until one with an attached sensitive detector is found
54 // return a tuple holding
55 // - pointer to the first (deepest) sensitive G4VPhysicalVolume
56 // - how may steps up in the hierarchy it is (0 is the starting volume)
57 // if no sensitive detector is found, return a NULL pointer and 0
58 
59 boost::tuple<const G4VPhysicalVolume*, int> GetSensitiveVolume( const G4VTouchable* touchable )
60 {
61  int depth = touchable->GetHistoryDepth();
62  for (int level = 0; level < depth; ++level) { // 0 is self
63  const G4VPhysicalVolume* volume = touchable->GetVolume(level);
64  if (volume->GetLogicalVolume()->GetSensitiveDetector() != 0) {
65  return boost::make_tuple(volume, level);
66  }
67  }
68  return boost::tuple<const G4VPhysicalVolume*, int>(0, 0);
69 }
70 
71 //-------------------------------------------------------------------------
73 {
74  edm::ParameterSet config = iPSet.getParameter<edm::ParameterSet>("TrackingMaterialProducer");
75  m_selectedNames = config.getParameter< std::vector<std::string> >("SelectedVolumes");
76  m_primaryTracks = config.getParameter<bool>("PrimaryTracksOnly");
77  m_tracks = 0;
78 
79  produces< std::vector<MaterialAccountingTrack> >();
80 }
81 
82 //-------------------------------------------------------------------------
84 {
85 }
86 
87 //-------------------------------------------------------------------------
89 {
90  // INFO
91  std::cout << "TrackingMaterialProducer: List of the selected volumes: " << std::endl;
92  for (std::vector<std::string>::const_iterator volume_name = m_selectedNames.begin(); volume_name != m_selectedNames.end(); ++volume_name) {
93  const G4LogicalVolume* volume = GetVolume(*volume_name);
94  if (volume) {
95  std::cout << '\t' << *volume_name << std::endl;
96  m_selectedVolumes.push_back( volume );
97  } else {
98  // FIXME: throw an exception ?
99  std::cerr << "TrackingMaterialProducer::update(const BeginOfJob*): WARNING: selected volume \"" << *volume_name << "\" not found in geometry " << std::endl;
100  }
101  }
102  std::cout << std::endl;
103 }
104 
105 
106 //-------------------------------------------------------------------------
108 {
109  m_tracks = new std::vector<MaterialAccountingTrack>();
110 }
111 
112 
113 //-------------------------------------------------------------------------
115 {
116  m_track.reset();
117 
118  // prevent secondary tracks from propagating
119  G4Track* track = const_cast<G4Track*>((*event)());
120  if (m_primaryTracks and track->GetParentID() != 0) {
121  track->SetTrackStatus(fStopAndKill);
122  }
123 }
124 
125 
126 //-------------------------------------------------------------------------
128 {
129  const G4TouchableHistory* touchable = (G4TouchableHistory*)(step->GetTrack()->GetTouchable());
130  if (not isSelected( touchable )) {
131  //std::cout << "\t[...] skipping " << touchable->GetVolume()->GetName() << std::endl;
132  return;
133  }
134 
135  // material and step proterties
136  const G4Material* material = touchable->GetVolume()->GetLogicalVolume()->GetMaterial();
137  double length = step->GetStepLength() / cm; // mm -> cm
138  double X0 = material->GetRadlen() / cm; // mm -> cm
139  double Ne = material->GetElectronDensity() * cm3; // 1/mm3 -> 1/cm3
140  double Xi = Ne / 6.0221415e23 * 0.307075 / 2.; // MeV / cm
141  double radiationLengths = length / X0; //
142  double energyLoss = length * Xi; // MeV
143  //double energyLoss = step->GetDeltaEnergy()/MeV; should we use this??
144 
145  G4ThreeVector globalPosPre = step->GetPreStepPoint()->GetPosition();
146  G4ThreeVector globalPosPost = step->GetPostStepPoint()->GetPosition();
147  GlobalPoint globalPositionIn( globalPosPre.x() / cm, globalPosPre.y() / cm, globalPosPre.z() / cm ); // mm -> cm
148  GlobalPoint globalPositionOut( globalPosPost.x() / cm, globalPosPost.y() / cm, globalPosPost.z() / cm ); // mm -> cm
149 
150  // check for a sensitive detector
151  bool enter_sensitive = false;
152  bool leave_sensitive = false;
153  double cosThetaPre = 0.0;
154  double cosThetaPost = 0.0;
155  int level = 0;
156  const G4VPhysicalVolume* sensitive = 0;
158  boost::tuples::tie(sensitive, level) = GetSensitiveVolume(touchable);
159  if (sensitive) {
160  const G4VSolid & solid = *touchable->GetSolid( level );
161  const G4AffineTransform & transform = GetTransform( touchable, level );
162  G4ThreeVector pos = transform.Inverse().TransformPoint( G4ThreeVector( 0., 0., 0. ) );
163  position = GlobalPoint( pos.x() / cm, pos.y() / cm, pos.z() / cm ); // mm -> cm
164 
165  G4ThreeVector localPosPre = transform.TransformPoint( globalPosPre );
166  EInside statusPre = solid.Inside( localPosPre );
167  if (statusPre == kSurface) {
168  enter_sensitive = true;
169  G4ThreeVector globalDirPre = step->GetPreStepPoint()->GetMomentumDirection();
170  G4ThreeVector localDirPre = transform.TransformAxis( globalDirPre );
171  G4ThreeVector normalPre = solid.SurfaceNormal( localPosPre );
172  cosThetaPre = normalPre.cosTheta( -localDirPre );
173  }
174 
175  G4ThreeVector localPosPost = transform.TransformPoint( globalPosPost );
176  EInside statusPost = solid.Inside( localPosPost );
177  if (statusPost == kSurface) {
178  leave_sensitive = true;
179  G4ThreeVector globalDirPost = step->GetPostStepPoint()->GetMomentumDirection();
180  G4ThreeVector localDirPost = transform.TransformAxis( globalDirPost );
181  G4ThreeVector normalPost = solid.SurfaceNormal( localPosPost );
182  cosThetaPost = normalPost.cosTheta( localDirPost );
183  }
184  }
185 
186  // update track accounting
187  if (enter_sensitive)
188  m_track.enterDetector( sensitive, position, cosThetaPre );
189  m_track.step(MaterialAccountingStep( length, radiationLengths, energyLoss, globalPositionIn, globalPositionOut ));
190  if (leave_sensitive)
191  m_track.leaveDetector( sensitive, cosThetaPost );
192 
193  /*
194  for (int i = touchable->GetHistoryDepth(); i > 0; --i)
195  std::cout << touchable->GetVolume(i)->GetName() << "::";
196  std::cout << touchable->GetVolume()->GetName() << std::endl;
197  std::cout << "\tmade of " << material->GetName();
198  if (sensitive) {
199  std::cout << " (inside sensitive " << sensitive->GetName() << ")";
200  if (enter_sensitive)
201  std::cout << " (in: cos(theta) = " << cosThetaPre << ")";
202  if (leave_sensitive)
203  std::cout << " (out: cos(theta) = " << cosThetaPost << ")";
204  }
205  std::cout << std::endl;
206  std::cout << "\tStep length: " << length << " cm" << std::endl;
207  std::cout << "\tRadiation lengths: " << radiationLengths << " \t\t(X0: " << X0 << " cm)" << std::endl;
208  std::cout << "\tEnergy loss: " << energyLoss << " MeV \t(Xi: " << Xi << " MeV/cm)" << std::endl;
209  std::cout << std::endl;
210  */
211 }
212 
213 
214 //-------------------------------------------------------------------------
216 {
217  const G4Track * track = (*event)();
218  if (m_primaryTracks and track->GetParentID() != 0)
219  return;
220 
221  m_tracks->push_back(m_track);
222 
223  // LogDebug
224  std::cout << "this track took " << m_track.steps().size() << " steps, and passed through " << m_track.detectors().size() << " sensitive detectors" << std::endl;
225  std::cout << "\ttrack length: " << m_track.summary().length() << " cm" << std::endl;
226  std::cout << "\tradiation lengths: " << m_track.summary().radiationLengths() << std::endl;
227  std::cout << "\tenergy loss: " << m_track.summary().energyLoss() << " MeV" << std::endl;
228 
229  /*
230  for (unsigned int i = 0; i < m_track.detectors().size(); ++i) {
231  std::cout << m_track.detectors()[i].volume()->GetName()
232  << "\tR: " << m_track.detectors()[i].position().perp()
233  << "\tZ: " << m_track.detectors()[i].position().z() << std::endl;
234  std::cout << "\tsegment length: " << m_track.detectors()[i].material().length() << " cm" << std::endl;
235  std::cout << "\tradiation lengths: " << m_track.detectors()[i].material().radiationLengths() << std::endl;
236  std::cout << "\tenergy loss: " << m_track.detectors()[i].material().energyLoss() << " MeV" << std::endl;
237  }
238  */
239  std::cout << std::endl;
240 }
241 
242 //-------------------------------------------------------------------------
244 {
245  // transfer ownership to the Event
246  std::auto_ptr<std::vector<MaterialAccountingTrack> > tracks( m_tracks );
247  iEvent.put( tracks );
248  m_tracks = 0;
249 }
250 
251 //-------------------------------------------------------------------------
252 bool TrackingMaterialProducer::isSelected( const G4VTouchable* touchable )
253 {
254  for (size_t i = 0; i < m_selectedVolumes.size(); ++i)
255  if (m_selectedVolumes[i]->IsAncestor( touchable->GetVolume() ) or m_selectedVolumes[i] == touchable->GetVolume()->GetLogicalVolume())
256  return true;
257 
258  return false;
259 }
260 
261 //-------------------------------------------------------------------------
262 // define as a plugin
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 int position[TOTALCHAMBERS][3]
Definition: ReadPGInfo.cc:509
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:116
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.
tuple cout
Definition: gather_cfg.py:121
tuple level
Definition: testEve_cfg.py:34
static const double X0
bool isSelected(const G4VTouchable *touch)