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