24 #include "G4VSolid.hh"
25 #include "G4LogicalVolumeStore.hh"
26 #include "G4TouchableHistory.hh"
27 #include "G4VPhysicalVolume.hh"
28 #include "G4AffineTransform.hh"
35 #define DEBUG_G4_VOLUMES
37 using namespace CLHEP;
42 const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
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()
50 for (G4LogicalVolumeStore::const_iterator volume = lvs->begin(); volume != lvs->end(); ++volume) {
58 static inline const G4AffineTransform&
GetTransform(
const G4TouchableHistory* touchable,
int depth) {
59 return touchable->GetHistory()->GetTransform(touchable->GetHistory()->GetDepth() -
depth);
69 int depth = touchable->GetHistoryDepth();
71 const G4VPhysicalVolume* volume = touchable->GetVolume(
level);
72 if (volume->GetLogicalVolume()->GetSensitiveDetector() !=
nullptr) {
73 return std::make_tuple(volume,
level);
76 return std::tuple<const G4VPhysicalVolume*, int>(
nullptr, 0);
82 m_selectedNames = config.
getParameter<std::vector<std::string> >(
"SelectedVolumes");
83 m_primaryTracks = config.
getParameter<
bool>(
"PrimaryTracksOnly");
85 m_hgcalzfront = config.
getParameter<
double>(
"hgcalzfront");
87 m_track_volume =
nullptr;
89 produces<std::vector<MaterialAccountingTrack> >();
90 output_file_ =
new TFile(
"radLen_vs_eta_fromProducer.root",
"RECREATE");
92 radLen_vs_eta_ =
new TProfile(
"radLen",
"radLen", 250., -5., 5., 0, 10.);
97 if (
std::find(m_selectedNames.begin(), m_selectedNames.end(),
"HGCal") != m_selectedNames.end()) {
102 if (
std::find(m_selectedNames.begin(), m_selectedNames.end(),
"HFNose") != m_selectedNames.end()) {
105 if (isHGCal
or isHFNose) {
106 outVolumeZpositionTxt.open(m_txtOutFile.c_str(),
std::ios::out);
115 radLen_vs_eta_->Write();
116 output_file_->Close();
121 LogInfo(
"TrackingMaterialProducer") <<
"TrackingMaterialProducer: List of the selected volumes: " << std::endl;
122 for (std::vector<std::string>::const_iterator volume_name = m_selectedNames.begin();
123 volume_name != m_selectedNames.end();
125 const G4LogicalVolume* volume =
GetVolume(*volume_name);
127 LogInfo(
"TrackingMaterialProducer") <<
"TrackingMaterialProducer: " << *volume_name << std::endl;
128 m_selectedVolumes.push_back(volume);
131 std::cerr <<
"TrackingMaterialProducer::update(const BeginOfJob*): WARNING: selected volume \"" << *volume_name
132 <<
"\" not found in geometry " << std::endl;
139 m_tracks =
new std::vector<MaterialAccountingTrack>();
145 m_track_volume =
nullptr;
148 G4Track*
track =
const_cast<G4Track*
>((*event)());
149 if (m_primaryTracks and track->GetParentID() != 0) {
150 track->SetTrackStatus(fStopAndKill);
165 if (isHGCal && track->GetTrackStatus() != fStopAndKill && fabs(track->GetMomentum().eta()) > outerHGCalEta &&
166 fabs(track->GetMomentum().eta()) < innerHGCalEta) {
167 if (track->GetMomentum().eta() > 0.) {
168 outVolumeZpositionTxt <<
"Air " << m_hgcalzfront <<
" " << 0 <<
" " << 0 <<
" " << 0 <<
" " << 0 << std::endl;
169 }
else if (track->GetMomentum().eta() <= 0.) {
170 outVolumeZpositionTxt <<
"Air " << -m_hgcalzfront <<
" " << 0 <<
" " << 0 <<
" " << 0 <<
" " << 0 << std::endl;
178 if (isHFNose && track->GetTrackStatus() != fStopAndKill && fabs(track->GetMomentum().eta()) > outerHFnoseEta &&
179 fabs(track->GetMomentum().eta()) < innerHFnoseEta) {
180 if (track->GetMomentum().eta() > 0.) {
181 outVolumeZpositionTxt <<
"Polyethylene " << m_hgcalzfront <<
" " << 0 <<
" " << 0 <<
" " << 0 <<
" " << 0
183 }
else if (track->GetMomentum().eta() <= 0.) {
184 outVolumeZpositionTxt <<
"Polyethylene " << -m_hgcalzfront <<
" " << 0 <<
" " << 0 <<
" " << 0 <<
" " << 0
191 for (
int d = touchable->GetHistoryDepth() - 1;
d >= 0; --
d) {
192 if (
std::find(m_selectedNames.begin(), m_selectedNames.end(), touchable->GetVolume(
d)->GetName()) !=
193 m_selectedNames.end())
201 const G4TouchableHistory* touchable =
static_cast<const G4TouchableHistory*
>(step->GetTrack()->GetTouchable());
202 if (not isSelectedFast(touchable)) {
203 LogInfo(
"TrackingMaterialProducer") <<
"TrackingMaterialProducer:\t[...] skipping "
204 << touchable->GetVolume()->GetName() << std::endl;
209 const G4Material* material = touchable->GetVolume()->GetLogicalVolume()->GetMaterial();
210 double length = step->GetStepLength() / cm;
211 double X0 = material->GetRadlen() / cm;
212 double Ne = material->GetElectronDensity() * cm3;
213 double Xi = Ne / 6.0221415e23 * 0.307075 / 2;
214 double radiationLengths = length /
X0;
215 double energyLoss = length * Xi / 1000.;
218 G4ThreeVector globalPosPre = step->GetPreStepPoint()->GetPosition();
219 G4ThreeVector globalPosPost = step->GetPostStepPoint()->GetPosition();
220 GlobalPoint globalPositionIn(globalPosPre.x() / cm, globalPosPre.y() / cm, globalPosPre.z() / cm);
221 GlobalPoint globalPositionOut(globalPosPost.x() / cm, globalPosPost.y() / cm, globalPosPost.z() / cm);
223 G4StepPoint* prePoint = step->GetPreStepPoint();
224 G4StepPoint* postPoint = step->GetPostStepPoint();
225 const CLHEP::Hep3Vector& postPos = postPoint->GetPosition();
227 if (isHGCal
or isHFNose) {
231 if (postPoint->GetStepStatus() == fGeomBoundary && fabs(postPoint->GetMomentum().eta()) > outerHGCalEta &&
232 fabs(postPoint->GetMomentum().eta()) < innerHGCalEta) {
237 outVolumeZpositionTxt << prePoint->GetMaterial()->GetName() <<
" " << postPos.
z() <<
" "
238 << postPoint->GetMomentum().eta() <<
" "
239 <<
sqrt(postPos.x() * postPos.x() + postPos.y() * postPos.y()) <<
" " << 0 <<
" " << 0
243 if (postPoint->GetStepStatus() == fGeomBoundary && fabs(postPoint->GetMomentum().eta()) > outerHFnoseEta &&
244 fabs(postPoint->GetMomentum().eta()) < innerHFnoseEta) {
245 outVolumeZpositionTxt << prePoint->GetMaterial()->GetName() <<
" " << postPos.z() <<
" "
246 << postPoint->GetMomentum().eta() <<
" "
247 <<
sqrt(postPos.x() * postPos.x() + postPos.y() * postPos.y()) <<
" " << 0 <<
" " << 0
254 bool enter_sensitive =
false;
255 bool leave_sensitive =
false;
256 double cosThetaPre = 0.0;
257 double cosThetaPost = 0.0;
259 const G4VPhysicalVolume* sensitive =
nullptr;
263 const G4VSolid& solid = *touchable->GetSolid(level);
265 G4ThreeVector pos = transform.Inverse().TransformPoint(G4ThreeVector(0., 0., 0.));
266 position =
GlobalPoint(pos.x() / cm, pos.y() / cm, pos.z() / cm);
268 G4ThreeVector localPosPre = transform.TransformPoint(globalPosPre);
269 EInside statusPre = solid.Inside(localPosPre);
270 if (statusPre == kSurface) {
271 enter_sensitive =
true;
272 G4ThreeVector globalDirPre = step->GetPreStepPoint()->GetMomentumDirection();
273 G4ThreeVector localDirPre = transform.TransformAxis(globalDirPre);
274 G4ThreeVector normalPre = solid.SurfaceNormal(localPosPre);
275 cosThetaPre = normalPre.cosTheta(-localDirPre);
278 G4ThreeVector localPosPost = transform.TransformPoint(globalPosPost);
279 EInside statusPost = solid.Inside(localPosPost);
280 if (statusPost == kSurface) {
281 leave_sensitive =
true;
282 G4ThreeVector globalDirPost = step->GetPostStepPoint()->GetMomentumDirection();
283 G4ThreeVector localDirPost = transform.TransformAxis(globalDirPost);
284 G4ThreeVector normalPost = solid.SurfaceNormal(localPosPost);
285 cosThetaPost = normalPost.cosTheta(localDirPost);
290 if (enter_sensitive) {
291 if (m_track_volume !=
nullptr) {
292 edm::LogWarning(
"TrackingMaterialProducer") <<
"Entering volume " << sensitive <<
" while inside volume "
293 << m_track_volume <<
". Something is inconsistent";
296 m_track_volume = sensitive;
297 m_track.enterDetector(position, cosThetaPre);
299 m_track.step(
MaterialAccountingStep(length, radiationLengths, energyLoss, globalPositionIn, globalPositionOut));
300 if (leave_sensitive) {
301 if (m_track_volume != sensitive) {
302 edm::LogWarning(
"TrackingMaterialProducer") <<
"Leaving volume " << sensitive <<
" while inside volume "
303 << m_track_volume <<
". Something is inconsistent";
306 m_track.leaveDetector(cosThetaPost);
307 m_track_volume =
nullptr;
310 LogInfo(
"TrackingMaterialProducer") <<
"Track was near sensitive volume " << sensitive->GetName() << std::endl;
312 LogInfo(
"TrackingMaterialProducer") <<
"Track was near non-sensitive volume " << touchable->GetVolume()->GetName()
314 LogInfo(
"TrackingMaterialProducer") <<
"Step length: " << length <<
" cm\n"
315 <<
"globalPreStep(r,z): (" << globalPositionIn.perp() <<
", "
316 << globalPositionIn.z() <<
") cm\n"
317 <<
"globalPostStep(r,z): (" << globalPositionOut.perp() <<
", "
318 << globalPositionOut.z() <<
") cm\n"
319 <<
"position(r,z): (" << position.
perp() <<
", " << position.
z() <<
") cm\n"
320 <<
"Radiation lengths: " << radiationLengths <<
" \t\t(X0: " << X0
322 <<
"Energy loss: " << energyLoss <<
" MeV \t(Xi: " << Xi
324 <<
"Track was " << (enter_sensitive ?
"entering " :
"in none ")
325 <<
"sensitive volume\n"
326 <<
"Track was " << (leave_sensitive ?
"leaving " :
"in none ")
327 <<
"sensitive volume\n";
332 const G4Track*
track = (*event)();
333 if (m_primaryTracks and track->GetParentID() != 0)
336 radLen_vs_eta_->Fill(track->GetMomentum().eta(), m_track.summary().radiationLengths());
337 m_tracks->push_back(m_track);
340 LogInfo(
"TrackingMaterialProducer") <<
"TrackingMaterialProducer: this track took " << m_track.steps().size()
341 <<
" steps, and passed through " << m_track.detectors().size()
342 <<
" sensitive detectors" << std::endl;
343 LogInfo(
"TrackingMaterialProducer") <<
"TrackingMaterialProducer: track length: " << m_track.summary().length()
344 <<
" cm" << std::endl;
345 LogInfo(
"TrackingMaterialProducer") <<
"TrackingMaterialProducer: radiation lengths: "
346 << m_track.summary().radiationLengths() << std::endl;
347 LogInfo(
"TrackingMaterialProducer") <<
"TrackingMaterialProducer: energy loss: "
348 << m_track.summary().energyLoss() <<
" MeV" << std::endl;
354 std::unique_ptr<std::vector<MaterialAccountingTrack> >
tracks(m_tracks);
361 for (
size_t i = 0;
i < m_selectedVolumes.size(); ++
i)
362 if (m_selectedVolumes[
i]->IsAncestor(touchable->GetVolume())
or
363 m_selectedVolumes[
i] == touchable->GetVolume()->GetLogicalVolume())
T getUntrackedParameter(std::string const &, T const &) const
#define DEFINE_SIMWATCHER(type)
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
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
Global3DPoint GlobalPoint
auto const & tracks
cannot be loose
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
TrackingMaterialProducer(const edm::ParameterSet &)
static const G4AffineTransform & GetTransform(const G4TouchableHistory *touchable, int depth)
~TrackingMaterialProducer() override
Log< level::Info, false > LogInfo
static const G4LogicalVolume * GetVolume(const std::string &name)
T getParameter(std::string const &) const
tuple config
parse the configuration file
static int position[264][3]
Log< level::Warning, false > LogWarning
void produce(edm::Event &, const edm::EventSetup &) override
void update(const BeginOfJob *) override
This routine will be called when the appropriate signal arrives.
bool isSelected(const G4VTouchable *touch)
bool isSelectedFast(const G4TouchableHistory *touch)
std::tuple< const G4VPhysicalVolume *, int > GetSensitiveVolume(const G4VTouchable *touchable)