Belle II Software development
MaterialScanRay Class Reference

MaterialScan implementation to shoot one ray along a defined direction and record the Material as a function of travel depth. More...

#include <MaterialScan.h>

Inheritance diagram for MaterialScanRay:
MaterialScanBase

Public Member Functions

 MaterialScanRay (TFile *rootFile, const G4ThreeVector &origin, const G4ThreeVector &dir, double opening, int count, double sampleDepth, double maxDepth, bool splitByMaterials, const std::vector< std::string > &ignoredMaterials)
 Construct a new instance and set all parameters.
 
int getNRays () const override
 Return the number of rays.
 
void UserSteppingAction (const G4Step *step) override
 Record the material budget for each step of the particles.
 
bool createNext (G4ThreeVector &origin, G4ThreeVector &direction) override
 Implement shooting along the ray.
 
std::string getName () const
 Return the name of the scan.
 

Protected Member Functions

bool checkStep (const G4Step *step)
 check for stuck tracks by looking at the step length
 

Protected Attributes

TFile * m_rootFile
 Pointer to the root file for the histograms.
 
std::string m_name
 Name of the scan, will be prefixed to all histogram names.
 
std::string m_axisLabel
 Labels for the coordinate axes.
 

Private Member Functions

TH1D * getHistogram (const std::string &name)
 get histogram for a given name, create if needed.
 
void fillValue (const std::string &name, double value, double steplength)
 Fill the recorded material budget into the corresponding histogram.
 

Private Attributes

std::set< std::string > m_ignoredMaterials
 Materials ignored when scanning.
 
std::map< std::string, std::unique_ptr< TH1D > > m_regions
 Map holding pointers to all created histograms.
 
G4ThreeVector m_origin
 Origin of the scan.
 
G4ThreeVector m_dir
 Direction of the ray.
 
double m_opening
 Opening angle in radian.
 
double m_sampleDepth
 The ray length after which to sample.
 
double m_maxDepth {0}
 Maximum depth for each ray after which it will be stopped.
 
double m_curDepth {0}
 Current depth of the current ray.
 
double m_scanDepth {0}
 The first ray does not record any material but just checks for the maximum useful depth to not get a plot which contains the PXD at the front and then continues for 500 more cm without any content.
 
int m_count
 Amount of rays to shoot.
 
int m_curRay { -1}
 Current Ray number: 0 = scan for maximum depth, 1..N = record materials.
 
bool m_splitByMaterials
 If true Split by materials instead of regions.
 
int m_zeroSteps {0}
 Count the number of steps with (almost) zero length.
 

Static Private Attributes

static constexpr double c_zeroTolerance = 1e-6
 maximum Step length to be considered zero
 
static constexpr int c_maxZeroStepsNudge = 10
 maximum number of consecutive zero steps before nudging the track along
 
static constexpr int c_maxZeroStepsKill = 20
 maximum number of consecutive zero steps before killing the track
 

Detailed Description

MaterialScan implementation to shoot one ray along a defined direction and record the Material as a function of travel depth.

In contrast to the other implementations this produces a 1D histogram per region (plus a cumulative one) which contains the X_0 per bin so that the integral of the histogram ( $\sum_i binwidth_i * bincontent_i$) is equal to the total number of X_0 seen.

Definition at line 239 of file MaterialScan.h.

Constructor & Destructor Documentation

◆ MaterialScanRay()

MaterialScanRay ( TFile *  rootFile,
const G4ThreeVector &  origin,
const G4ThreeVector &  dir,
double  opening,
int  count,
double  sampleDepth,
double  maxDepth,
bool  splitByMaterials,
const std::vector< std::string > &  ignoredMaterials 
)
inline

Construct a new instance and set all parameters.

Definition at line 242 of file MaterialScan.h.

244 :
245 MaterialScanBase(rootFile, "Ray", "ray length [cm]; material budget [X_0/cm]"),
246 m_ignoredMaterials(ignoredMaterials.begin(), ignoredMaterials.end()),
247 m_origin(origin), m_dir(dir), m_opening(opening), m_sampleDepth(sampleDepth),
248 m_maxDepth(maxDepth), m_count(std::max(1, count)), m_splitByMaterials(splitByMaterials)
249 {
250 if (m_opening <= 0) m_count = 1;
251 }
MaterialScanBase(TFile *rootFile, const std::string &name, const std::string &axisLabel)
This is indeed the constructor and it creates a TDirectory in the output root file and sets all varia...
Definition: MaterialScan.h:37
G4ThreeVector m_origin
Origin of the scan.
Definition: MaterialScan.h:276
bool m_splitByMaterials
If true Split by materials instead of regions.
Definition: MaterialScan.h:298
G4ThreeVector m_dir
Direction of the ray.
Definition: MaterialScan.h:278
double m_maxDepth
Maximum depth for each ray after which it will be stopped.
Definition: MaterialScan.h:284
double m_opening
Opening angle in radian.
Definition: MaterialScan.h:280
std::set< std::string > m_ignoredMaterials
Materials ignored when scanning.
Definition: MaterialScan.h:272
double m_sampleDepth
The ray length after which to sample.
Definition: MaterialScan.h:282
int m_count
Amount of rays to shoot.
Definition: MaterialScan.h:294

Member Function Documentation

◆ checkStep()

bool checkStep ( const G4Step *  step)
protectedinherited

check for stuck tracks by looking at the step length

Definition at line 44 of file MaterialScan.cc.

45{
46 double stlen = step->GetStepLength();
47 G4StepPoint* preStepPoint = step->GetPreStepPoint();
48 G4Region* region = preStepPoint->GetPhysicalVolume()->GetLogicalVolume()->GetRegion();
49 if (stlen < c_zeroTolerance) {
51 } else {
52 m_zeroSteps = 0;
53 }
56 B2ERROR("Track is stuck at " << preStepPoint->GetPosition() << " in volume '"
57 << preStepPoint->GetPhysicalVolume()->GetLogicalVolume()->GetName()
58 << " (" << region->GetName() << "): "
59 << m_zeroSteps << " consecutive steps with length less then "
60 << c_zeroTolerance << " mm, killing it");
61 step->GetTrack()->SetTrackStatus(fStopAndKill);
62 } else {
63 B2WARNING("Track is stuck at " << preStepPoint->GetPosition() << " in volume '"
64 << preStepPoint->GetPhysicalVolume()->GetLogicalVolume()->GetName()
65 << " (" << region->GetName() << "): "
66 << m_zeroSteps << " consecutive steps with length less then "
67 << c_zeroTolerance << " mm, nudging it along");
68 G4ThreeVector pos = step->GetTrack()->GetPosition();
69 G4ThreeVector dir = step->GetTrack()->GetMomentumDirection();
70 step->GetTrack()->SetPosition(pos + c_zeroTolerance * dir);
71 }
72 return false;
73 }
74 return true;
75}
int m_zeroSteps
Count the number of steps with (almost) zero length.
Definition: MaterialScan.h:73
static constexpr int c_maxZeroStepsNudge
maximum number of consecutive zero steps before nudging the track along
Definition: MaterialScan.h:69
static constexpr int c_maxZeroStepsKill
maximum number of consecutive zero steps before killing the track
Definition: MaterialScan.h:71
static constexpr double c_zeroTolerance
maximum Step length to be considered zero
Definition: MaterialScan.h:67

◆ createNext()

bool createNext ( G4ThreeVector &  origin,
G4ThreeVector &  direction 
)
overridevirtual

Implement shooting along the ray.

Implements MaterialScanBase.

Definition at line 215 of file MaterialScan.cc.

216{
217 if (m_curRay > m_count) return false;
218
219 origin = m_origin;
220 direction = m_dir;
221 ++m_curRay;
222 if (m_curRay == 0) {
223 // First ray is just to check what the maximum flight length is
224 return true;
225 } else if (m_curRay == 1) {
226 // this is the second ray, save the maximum depth for histograms
228 B2INFO("Set maximum depth to " << m_maxDepth);
229 // create summary histogram right now, not on demand, to make sure it is in the file
230 if (m_splitByMaterials) {
231 getHistogram("All_Materials_x0");
232 getHistogram("All_Materials_lambda");
233 } else {
234 getHistogram("All_Regions_x0");
235 getHistogram("All_Regions_lambda");
236 }
237 }
238 m_curDepth = 0;
239 if (m_opening > 0) {
240 // add small angle to the ray where we want the opening angle to be covered
241 // uniform by area so choose an angle uniform in cos(angle). We take half
242 // the opening angle because it can go in both sides
243 double theta = acos(gRandom->Uniform(cos(m_opening / 2.), 1));
244 double phi = gRandom->Uniform(0, 2 * M_PI);
245 auto orthogonal = direction.orthogonal();
246 orthogonal.rotate(phi, direction);
247 direction.rotate(theta, orthogonal);
248 }
249 B2DEBUG(10, "Create Ray " << m_curRay << " from " << origin << " direction " <<
250 direction << " [theta=" << (direction.theta() / M_PI * 180) << ", phi=" << (direction.phi() / M_PI * 180) << "]");
251 return true;
252}
double m_scanDepth
The first ray does not record any material but just checks for the maximum useful depth to not get a ...
Definition: MaterialScan.h:292
int m_curRay
Current Ray number: 0 = scan for maximum depth, 1..N = record materials.
Definition: MaterialScan.h:296
double m_curDepth
Current depth of the current ray.
Definition: MaterialScan.h:286
TH1D * getHistogram(const std::string &name)
get histogram for a given name, create if needed.

◆ fillValue()

void fillValue ( const std::string &  name,
double  value,
double  steplength 
)
private

Fill the recorded material budget into the corresponding histogram.

Parameters
nameName of the histogram
valueValue to store
steplengthThe Steplength which produced the value (for correct subsampling)

Definition at line 266 of file MaterialScan.cc.

267{
268 TH1D* h = getHistogram(name);
269 double x = m_curDepth;
270 //The steps are not aligned to the bin sizes so make sure we sub-sample the
271 //value and put it in the histogram in smaller steps. We choose 10 samples
272 //per bin here which should be good enough.
273 int samples = std::ceil(steplength / m_sampleDepth * 10);
274 const double dx = steplength / samples;
275 const double dv = value / samples / m_count / h->GetBinWidth(1);
276 for (int i = 0; i < samples; ++i) {
277 h->Fill(x * Unit::mm, dv);
278 x += dx;
279 }
280}
static const double mm
[millimeters]
Definition: Unit.h:70

◆ getHistogram()

TH1D * getHistogram ( const std::string &  name)
private

get histogram for a given name, create if needed.

Parameters
nameName of the histogram

Definition at line 254 of file MaterialScan.cc.

255{
256 std::unique_ptr<TH1D>& hist = m_regions[name];
257 if (!hist) {
258 //Create new histogram
259 m_rootFile->cd(m_name.c_str());
260 int bins = std::ceil(m_maxDepth / m_sampleDepth);
261 hist.reset(new TH1D(name.c_str(), (name + ";" + m_axisLabel).c_str(), bins, 0, m_maxDepth * Unit::mm));
262 }
263 return hist.get();
264}
TFile * m_rootFile
Pointer to the root file for the histograms.
Definition: MaterialScan.h:60
std::string m_axisLabel
Labels for the coordinate axes.
Definition: MaterialScan.h:64
std::string m_name
Name of the scan, will be prefixed to all histogram names.
Definition: MaterialScan.h:62
std::map< std::string, std::unique_ptr< TH1D > > m_regions
Map holding pointers to all created histograms.
Definition: MaterialScan.h:274

◆ getName()

std::string getName ( ) const
inlineinherited

Return the name of the scan.

Definition at line 43 of file MaterialScan.h.

43{ return m_name; }

◆ getNRays()

int getNRays ( ) const
inlineoverridevirtual

Return the number of rays.

We have one extra ray to scan the maximum depth

Implements MaterialScanBase.

Definition at line 254 of file MaterialScan.h.

254{ return m_count + 1; }

◆ UserSteppingAction()

void UserSteppingAction ( const G4Step *  step)
override

Record the material budget for each step of the particles.

Definition at line 282 of file MaterialScan.cc.

283{
284 //Get information about radiation and interaction length
285 G4StepPoint* preStepPoint = step->GetPreStepPoint();
286 G4Region* region = preStepPoint->GetPhysicalVolume()->GetLogicalVolume()->GetRegion();
287 G4Material* material = preStepPoint->GetMaterial();
288 const bool ignored = m_ignoredMaterials.count(material->GetName()) > 0;
289 double stlen = step->GetStepLength();
290 double x0 = stlen / (material->GetRadlen());
291 double lambda = stlen / (material->GetNuclearInterLength());
292 B2DEBUG(20, "Step in at " << preStepPoint->GetPosition() << " in volume '"
293 << preStepPoint->GetPhysicalVolume()->GetLogicalVolume()->GetName()
294 << " (" << region->GetName() << ")"
295 << " with length=" << stlen << " mm");
296 checkStep(step);
297
298 //check if the depth is limited
299 if (m_maxDepth > 0) {
300 if (m_curDepth + stlen > m_maxDepth) {
301 //Depth reached, kill track and add remaining part of the material budget
302 G4Track* track = step->GetTrack();
303 track->SetTrackStatus(fStopAndKill);
304 double remaining = m_maxDepth - m_curDepth;
305 x0 *= remaining / stlen;
306 lambda *= remaining / stlen;
307 stlen = remaining;
308 }
309 }
310
311 if (m_curRay > 0 && !ignored) {
312 //Fill x0 and lambda in a histogram for each region
313 string x0_total = "All_Regions_x0";
314 string lambda_total = "All_Regions_lambda";
315 string x0_name = region->GetName() + "_x0";
316 string lambda_name = region->GetName() + "_lambda";
317 //or for each Material
318 if (m_splitByMaterials) {
319 x0_total = "All_Materials_x0";
320 lambda_total = "All_Materials_lambda";
321 x0_name = material->GetName() + "_x0";
322 lambda_name = material->GetName() + "_lambda";
323 }
324 fillValue(x0_total, x0, stlen);
325 fillValue(lambda_total, lambda, stlen);
326 fillValue(x0_name, x0, stlen);
327 fillValue(lambda_name, lambda, stlen);
328 }
329 m_curDepth += stlen;
330 if (m_curRay == 0 && !ignored) {
331 // update max depth only for materials we do not ignore ...
333 }
334}
bool checkStep(const G4Step *step)
check for stuck tracks by looking at the step length
Definition: MaterialScan.cc:44
void fillValue(const std::string &name, double value, double steplength)
Fill the recorded material budget into the corresponding histogram.

Member Data Documentation

◆ c_maxZeroStepsKill

constexpr int c_maxZeroStepsKill = 20
staticconstexprprivateinherited

maximum number of consecutive zero steps before killing the track

Definition at line 71 of file MaterialScan.h.

◆ c_maxZeroStepsNudge

constexpr int c_maxZeroStepsNudge = 10
staticconstexprprivateinherited

maximum number of consecutive zero steps before nudging the track along

Definition at line 69 of file MaterialScan.h.

◆ c_zeroTolerance

constexpr double c_zeroTolerance = 1e-6
staticconstexprprivateinherited

maximum Step length to be considered zero

Definition at line 67 of file MaterialScan.h.

◆ m_axisLabel

std::string m_axisLabel
protectedinherited

Labels for the coordinate axes.

Definition at line 64 of file MaterialScan.h.

◆ m_count

int m_count
private

Amount of rays to shoot.

Definition at line 294 of file MaterialScan.h.

◆ m_curDepth

double m_curDepth {0}
private

Current depth of the current ray.

Definition at line 286 of file MaterialScan.h.

◆ m_curRay

int m_curRay { -1}
private

Current Ray number: 0 = scan for maximum depth, 1..N = record materials.

Definition at line 296 of file MaterialScan.h.

◆ m_dir

G4ThreeVector m_dir
private

Direction of the ray.

Definition at line 278 of file MaterialScan.h.

◆ m_ignoredMaterials

std::set<std::string> m_ignoredMaterials
private

Materials ignored when scanning.

Definition at line 272 of file MaterialScan.h.

◆ m_maxDepth

double m_maxDepth {0}
private

Maximum depth for each ray after which it will be stopped.

0=no limit.

Definition at line 284 of file MaterialScan.h.

◆ m_name

std::string m_name
protectedinherited

Name of the scan, will be prefixed to all histogram names.

Definition at line 62 of file MaterialScan.h.

◆ m_opening

double m_opening
private

Opening angle in radian.

Definition at line 280 of file MaterialScan.h.

◆ m_origin

G4ThreeVector m_origin
private

Origin of the scan.

Definition at line 276 of file MaterialScan.h.

◆ m_regions

std::map<std::string, std::unique_ptr<TH1D> > m_regions
private

Map holding pointers to all created histograms.

Definition at line 274 of file MaterialScan.h.

◆ m_rootFile

TFile* m_rootFile
protectedinherited

Pointer to the root file for the histograms.

Definition at line 60 of file MaterialScan.h.

◆ m_sampleDepth

double m_sampleDepth
private

The ray length after which to sample.

Basically the bin width of the histogram

Definition at line 282 of file MaterialScan.h.

◆ m_scanDepth

double m_scanDepth {0}
private

The first ray does not record any material but just checks for the maximum useful depth to not get a plot which contains the PXD at the front and then continues for 500 more cm without any content.

This variable stores the maximum depth seen by this ray in non-ignored matierals

Definition at line 292 of file MaterialScan.h.

◆ m_splitByMaterials

bool m_splitByMaterials
private

If true Split by materials instead of regions.

Definition at line 298 of file MaterialScan.h.

◆ m_zeroSteps

int m_zeroSteps {0}
privateinherited

Count the number of steps with (almost) zero length.

Definition at line 73 of file MaterialScan.h.


The documentation for this class was generated from the following files: