6 #include <boost/tuple/tuple.hpp>
23 #include "G4VSolid.hh"
24 #include "G4LogicalVolumeStore.hh"
25 #include "G4TouchableHistory.hh"
26 #include "G4VPhysicalVolume.hh"
27 #include "G4AffineTransform.hh"
31 using namespace CLHEP;
36 const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
38 for (G4LogicalVolumeStore::const_iterator volume = lvs->begin(); volume != lvs->end(); ++volume) {
48 const G4AffineTransform&
GetTransform(
const G4TouchableHistory* touchable,
int depth)
50 return touchable->GetHistory()->GetTransform( touchable->GetHistory()->GetDepth() - depth );
61 int depth = touchable->GetHistoryDepth();
63 const G4VPhysicalVolume* volume = touchable->GetVolume(
level);
64 if (volume->GetLogicalVolume()->GetSensitiveDetector() != 0) {
65 return boost::make_tuple(volume,
level);
68 return boost::tuple<const G4VPhysicalVolume*, int>(0, 0);
75 m_selectedNames = config.
getParameter< std::vector<std::string> >(
"SelectedVolumes");
76 m_primaryTracks = config.
getParameter<
bool>(
"PrimaryTracksOnly");
79 produces< std::vector<MaterialAccountingTrack> >();
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);
95 std::cout <<
'\t' << *volume_name << std::endl;
96 m_selectedVolumes.push_back( volume );
99 std::cerr <<
"TrackingMaterialProducer::update(const BeginOfJob*): WARNING: selected volume \"" << *volume_name <<
"\" not found in geometry " << std::endl;
109 m_tracks =
new std::vector<MaterialAccountingTrack>();
119 G4Track* track =
const_cast<G4Track*
>((*event)());
120 if (m_primaryTracks and track->GetParentID() != 0) {
121 track->SetTrackStatus(fStopAndKill);
129 const G4TouchableHistory* touchable = (G4TouchableHistory*)(step->GetTrack()->GetTouchable());
130 if (not isSelected( touchable )) {
136 const G4Material* material = touchable->GetVolume()->GetLogicalVolume()->GetMaterial();
137 double length = step->GetStepLength() / cm;
138 double X0 = material->GetRadlen() / cm;
139 double Ne = material->GetElectronDensity() * cm3;
140 double Xi = Ne / 6.0221415e23 * 0.307075 / 2.;
141 double radiationLengths = length /
X0;
142 double energyLoss = length * Xi;
145 G4ThreeVector globalPosPre = step->GetPreStepPoint()->GetPosition();
146 G4ThreeVector globalPosPost = step->GetPostStepPoint()->GetPosition();
147 GlobalPoint globalPositionIn( globalPosPre.x() / cm, globalPosPre.y() / cm, globalPosPre.z() / cm );
148 GlobalPoint globalPositionOut( globalPosPost.x() / cm, globalPosPost.y() / cm, globalPosPost.z() / cm );
151 bool enter_sensitive =
false;
152 bool leave_sensitive =
false;
153 double cosThetaPre = 0.0;
154 double cosThetaPost = 0.0;
156 const G4VPhysicalVolume* sensitive = 0;
160 const G4VSolid & solid = *touchable->GetSolid( level );
162 G4ThreeVector pos = transform.Inverse().TransformPoint( G4ThreeVector( 0., 0., 0. ) );
163 position =
GlobalPoint( pos.x() / cm, pos.y() / cm, pos.z() / cm );
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 );
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 );
188 m_track.enterDetector( sensitive, position, cosThetaPre );
189 m_track.step(
MaterialAccountingStep( length, radiationLengths, energyLoss, globalPositionIn, globalPositionOut ));
191 m_track.leaveDetector( sensitive, cosThetaPost );
217 const G4Track * track = (*event)();
218 if (m_primaryTracks and track->GetParentID() != 0)
221 m_tracks->push_back(m_track);
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;
246 std::auto_ptr<std::vector<MaterialAccountingTrack> >
tracks( m_tracks );
247 iEvent.
put( tracks );
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())
T getParameter(std::string const &) const
#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
void produce(edm::Event &, const edm::EventSetup &)
Global3DPoint GlobalPoint
TrackingMaterialProducer(const edm::ParameterSet &)
static const G4AffineTransform & GetTransform(const G4TouchableHistory *touchable, int depth)
OrphanHandle< PROD > put(std::auto_ptr< PROD > product)
Put a new product.
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)
virtual ~TrackingMaterialProducer()
void update(const BeginOfJob *)
This routine will be called when the appropriate signal arrives.
static int position[264][3]
bool isSelected(const G4VTouchable *touch)