Newer
Older
Markus Frank
committed
//==========================================================================
Markus Frank
committed
//--------------------------------------------------------------------------
// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
Markus Frank
committed
// All rights reserved.
Markus Frank
committed
// For the licensing terms see $DD4hepINSTALL/LICENSE.
// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
Markus Frank
committed
// Author : M.Frank
//
//==========================================================================
// Framework include files
#include "DD4hep/Objects.h"
Markus Frank
committed
#include "DDG4/Defs.h"
#include "DDG4/Geant4SteppingAction.h"
// Forward declarations
class G4LogicalVolume;
/// Namespace for the AIDA detector description toolkit
/// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
/// Class to perform directional material scans using Geantinos.
/**
*
* \author M.Frank
* \version 1.0
* \ingroup DD4HEP_SIMULATION
*/
class Geant4MaterialScanner : public Geant4SteppingAction {
protected:
/// Structure to hold the information of one simulation step.
class StepInfo {
public:
Markus Frank
committed
/// Pre-step and Post-step position
Position pre, post;
/// Reference to the logical volue
const G4LogicalVolume* volume;
/// Initializing constructor
StepInfo(const Position& pre, const Position& post, const G4LogicalVolume* volume);
/// Copy constructor
StepInfo(const StepInfo& c);
/// Default destructor
~StepInfo() {}
/// Assignment operator
StepInfo& operator=(const StepInfo& c);
};
typedef std::vector<StepInfo*> Steps;
double m_sumX0 = 0E0;
double m_sumLambda = 0E0;
double m_sumPath = 0E0;
Steps m_steps;
public:
/// Standard constructor
Geant4MaterialScanner(Geant4Context* context, const std::string& name);
/// Default destructor
virtual ~Geant4MaterialScanner();
/// User stepping callback
virtual void operator()(const G4Step* step, G4SteppingManager* mgr);
/// Begin-of-tracking callback
virtual void begin(const G4Track* track);
/// End-of-tracking callback
virtual void end(const G4Track* track);
/// Registered callback on Begin-event
void beginEvent(const G4Event* event);
};
}
}
//====================================================================
//--------------------------------------------------------------------
//
// Author : M.Frank
//
//====================================================================
// Framework include files
#include "DD4hep/InstanceCount.h"
#include "DD4hep/Printout.h"
#include "DDG4/Geant4TouchableHandler.h"
#include "DDG4/Geant4StepHandler.h"
#include "DDG4/Geant4EventAction.h"
#include "DDG4/Geant4TrackingAction.h"
#include "CLHEP/Units/SystemOfUnits.h"
#include "G4LogicalVolume.hh"
#include "G4Material.hh"
using namespace std;
Markus Frank
committed
#include "DDG4/Factories.h"
DECLARE_GEANT4ACTION(Geant4MaterialScanner)
/// Initializing constructor
Geant4MaterialScanner::StepInfo::StepInfo(const Position& prePos, const Position& postPos, const G4LogicalVolume* vol)
: pre(prePos), post(postPos), volume(vol)
{
}
/// Copy constructor
Geant4MaterialScanner::StepInfo::StepInfo(const StepInfo& c)
: pre(c.pre), post(c.post), volume(c.volume)
{
}
/// Assignment operator
Geant4MaterialScanner::StepInfo& Geant4MaterialScanner::StepInfo::operator=(const StepInfo& c) {
pre = c.pre;
post = c.post;
volume = c.volume;
return *this;
}
/// Standard constructor
Markus Frank
committed
Geant4MaterialScanner::Geant4MaterialScanner(Geant4Context* ctxt, const string& nam)
{
m_needsControl = true;
eventAction().callAtBegin(this,&Geant4MaterialScanner::beginEvent);
trackingAction().callAtEnd(this,&Geant4MaterialScanner::end);
trackingAction().callAtBegin(this,&Geant4MaterialScanner::begin);
InstanceCount::increment(this);
}
/// Default destructor
Geant4MaterialScanner::~Geant4MaterialScanner() {
InstanceCount::decrement(this);
}
/// User stepping callback
void Geant4MaterialScanner::operator()(const G4Step* step, G4SteppingManager*) {
Geant4StepHandler h(step);
#if 0
Geant4TouchableHandler pre_handler(step);
string prePath = pre_handler.path();
Geant4TouchableHandler post_handler(step);
string postPath = post_handler.path();
#endif
G4LogicalVolume* logVol = h.logvol(h.pre);
m_steps.emplace_back(new StepInfo(h.prePos(), h.postPos(), logVol));
}
/// Registered callback on Begin-event
void Geant4MaterialScanner::beginEvent(const G4Event* /* event */) {
for_each(m_steps.begin(),m_steps.end(),detail::DestroyObject<StepInfo*>());
m_steps.clear();
m_sumX0 = 0;
m_sumLambda = 0;
m_sumPath = 0;
}
/// Begin-of-tracking callback
void Geant4MaterialScanner::begin(const G4Track* track) {
printP2("Starting tracking action for track ID=%d",track->GetTrackID());
for_each(m_steps.begin(),m_steps.end(),detail::DestroyObject<StepInfo*>());
m_steps.clear();
m_sumX0 = 0;
m_sumLambda = 0;
m_sumPath = 0;
}
/// End-of-tracking callback
void Geant4MaterialScanner::end(const G4Track* track) {
if ( !m_steps.empty() ) {
constexpr const char* line = " +--------------------------------------------------------------------------------------------------------------------------------------------------\n";
constexpr const char* fmt1 = " | %5d %-20s %3.0f %8.3f %8.4f %11.4f %11.4f %10.3f %8.2f %11.6f %11.6f (%7.2f,%7.2f,%7.2f)\n";
constexpr const char* fmt2 = " | %5d %-20s %3.0f %8.3f %8.4f %11.6g %11.6g %10.3f %8.2f %11.6f %11.6f (%7.2f,%7.2f,%7.2f)\n";
const Position& pre = m_steps[0]->pre;
const Position& post = m_steps[m_steps.size()-1]->post;
::printf("%s + Material scan between: x_0 = (%7.2f,%7.2f,%7.2f) [cm] and x_1 = (%7.2f,%7.2f,%7.2f) [cm] TrackID:%d: \n%s",
line,pre.X()/CLHEP::cm,pre.Y()/CLHEP::cm,pre.Z()/CLHEP::cm,post.X()/CLHEP::cm,post.Y()/CLHEP::cm,post.Z()/CLHEP::cm,track->GetTrackID(),line);
::printf(" | \\ %-11s Atomic Radiation Interaction Path Integrated Integrated Material\n","Material");
::printf(" | Num. \\ %-11s Number/Z Mass/A Density Length Length Thickness Length X0 Lambda Endpoint \n","Name");
::printf(" | Layer \\ %-11s [g/mole] [g/cm3] [cm] [cm] [cm] [cm] [cm] [cm] ( cm, cm, cm)\n","");
::printf("%s",line);
int count = 1;
for(Steps::const_iterator i=m_steps.begin(); i!=m_steps.end(); ++i, ++count) {
const G4LogicalVolume* logVol = (*i)->volume;
Markus Frank
committed
G4Material* material = logVol->GetMaterial();
const Position& prePos = (*i)->pre;
const Position& postPos = (*i)->post;
Position direction = postPos - prePos;
double length = direction.R()/CLHEP::cm;
double intLen = material->GetNuclearInterLength()/CLHEP::cm;
double radLen = material->GetRadlen()/CLHEP::cm;
double density = material->GetDensity()/(CLHEP::gram/CLHEP::cm3);
double nLambda = length / intLen;
double nx0 = length / radLen;
double Aeff = 0.0;
double Zeff = 0.0;
const char* fmt = radLen >= 1e5 ? fmt2 : fmt1;
Markus Frank
committed
const double* fractions = material->GetFractionVector();
for(size_t j=0; j<material->GetNumberOfElements(); ++j) {
Zeff += fractions[j]*(material->GetElement(j)->GetZ());
Aeff += fractions[j]*(material->GetElement(j)->GetA())/CLHEP::gram;
}
m_sumX0 += nx0;
m_sumLambda += nLambda;
m_sumPath += length;
Markus Frank
committed
::printf(fmt,count,material->GetName().c_str(),
Markus Frank
committed
Zeff, Aeff, density, radLen, intLen, length,
m_sumPath,m_sumX0,m_sumLambda,
postPos.X()/CLHEP::cm,postPos.Y()/CLHEP::cm,postPos.Z()/CLHEP::cm);
//cout << *m << endl;
}
for_each(m_steps.begin(),m_steps.end(),detail::DestroyObject<StepInfo*>());
m_steps.clear();
}
}