REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestGeant4AnalysisProcess.cxx
1/*************************************************************************
2 * This file is part of the REST software framework. *
3 * *
4 * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) *
5 * For more information see http://gifna.unizar.es/trex *
6 * *
7 * REST is free software: you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation, either version 3 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * REST is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have a copy of the GNU General Public License along with *
18 * REST in $REST_PATH/LICENSE. *
19 * If not, see http://www.gnu.org/licenses/. *
20 * For the list of contributors see $REST_PATH/CREDITS. *
21 *************************************************************************/
22
194
195#include "TRestGeant4AnalysisProcess.h"
196
197using namespace std;
198
200
205
219 Initialize();
220
221 if (LoadConfigFromFile(configFilename)) LoadDefaultConfig();
222}
223
228
232void TRestGeant4AnalysisProcess::LoadDefaultConfig() { SetTitle("Default config"); }
233
239 fG4Metadata = nullptr;
240 SetSectionName(this->ClassName());
241 SetLibraryVersion(LIBRARY_VERSION);
242
243 fInputG4Event = nullptr;
245}
246
259void TRestGeant4AnalysisProcess::LoadConfig(const string& configFilename, const string& name) {
260 if (LoadConfigFromFile(configFilename, name)) LoadDefaultConfig();
261}
262
269 fG4Metadata = GetMetadata<TRestGeant4Metadata>();
270
271 std::vector<string> fObservables;
272 fObservables = TRestEventProcess::ReadObservables();
273
274 if (fPerProcessSensitiveEnergy) {
275 fObservables.emplace_back("PerProcessPhotoelectric");
276 fObservables.emplace_back("PerProcessCompton");
277 fObservables.emplace_back("PerProcessElectronicIoni");
278 fObservables.emplace_back("PerProcessAlphaIoni");
279 fObservables.emplace_back("PerProcessIonIoni");
280 fObservables.emplace_back("PerProcessHadronicIoni");
281 fObservables.emplace_back("PerProcessProtonIoni");
282 fObservables.emplace_back("PerProcessMsc");
283 fObservables.emplace_back("PerProcessHadronElastic");
284 fObservables.emplace_back("PerProcessNeutronElastic");
285 }
286 for (unsigned int i = 0; i < fObservables.size(); i++) {
287 if (fObservables[i].find("VolumeEDep") != string::npos) {
288 TString volName = fObservables[i].substr(0, fObservables[i].length() - 10).c_str();
289
290 Int_t volId = fG4Metadata->GetActiveVolumeID(volName);
291 if (volId >= 0) {
292 fEnergyInObservables.push_back(fObservables[i]);
293 fVolumeID.push_back(volId);
294 fVolumeName.push_back(volName.Data());
295 }
296
297 if (volId == -1) {
298 cout << endl;
299 cout << "??????????????????????????????????????????????????" << endl;
300 cout << "REST warning : TRestGeant4AnalysisProcess." << endl;
301 cout << "------------------------------------------" << endl;
302 cout << endl;
303 cout << " Volume " << volName << " is not an active volume" << endl;
304 cout << endl;
305 cout << "List of active volumes : " << endl;
306 cout << "------------------------ " << endl;
307
308 for (unsigned int n = 0; n < fG4Metadata->GetNumberOfActiveVolumes(); n++)
309 cout << "Volume " << n << " : " << fG4Metadata->GetActiveVolumeName(n) << endl;
310 cout << "??????????????????????????????????????????????????" << endl;
311 cout << endl;
312 }
313 }
314
315 if (fObservables[i].find("MeanPos") != string::npos) {
316 TString volName2 = fObservables[i].substr(0, fObservables[i].length() - 8).c_str();
317 std::string dirId = fObservables[i].substr(fObservables[i].length() - 1, 1);
318
319 Int_t volId2 = fG4Metadata->GetActiveVolumeID(volName2);
320 if (volId2 >= 0) {
321 fMeanPosObservables.push_back(fObservables[i]);
322 fVolumeID2.push_back(volId2);
323 fDirID.push_back(dirId);
324 }
325
326 if (volId2 == -1) {
327 cout << endl;
328 cout << "??????????????????????????????????????????????????" << endl;
329 cout << "REST warning : TRestGeant4AnalysisProcess." << endl;
330 cout << "------------------------------------------" << endl;
331 cout << endl;
332 cout << " Volume " << volName2 << " is not an active volume" << endl;
333 cout << endl;
334 cout << "List of active volumes : " << endl;
335 cout << "------------------------ " << endl;
336
337 for (unsigned int n = 0; n < fG4Metadata->GetNumberOfActiveVolumes(); n++)
338 cout << "Volume " << n << " : " << fG4Metadata->GetActiveVolumeName(n) << endl;
339 cout << "??????????????????????????????????????????????????" << endl;
340 cout << endl;
341 }
342
343 if ((dirId != "X") && (dirId != "Y") && (dirId != "Z")) {
344 cout << endl;
345 cout << "??????????????????????????????????????????????????" << endl;
346 cout << "REST warning : TRestGeant4AnalysisProcess." << endl;
347 cout << "------------------------------------------" << endl;
348 cout << endl;
349 cout << " Direction " << dirId << " is not valid" << endl;
350 cout << " Only X, Y or Z accepted" << endl;
351 cout << endl;
352 }
353 }
354 if (fObservables[i].find("Process") != string::npos) {
355 Int_t ls = 0;
356 if (fObservables[i].find("RadiactiveDecay") != string::npos) ls = 15;
357 if (fObservables[i].find("Photoelectric") != string::npos) ls = 13;
358 if (fObservables[i].find("PhotonNuclear") != string::npos) ls = 13;
359 if (fObservables[i].find("Bremstralung") != string::npos) ls = 12;
360 if (fObservables[i].find("NInelastic") != string::npos) ls = 10;
361 if (fObservables[i].find("HadElastic") != string::npos) ls = 10;
362 if (fObservables[i].find("NCapture") != string::npos) ls = 8;
363 if (fObservables[i].find("Compton") != string::npos) ls = 7;
364 if (fObservables[i].find("Neutron") != string::npos) ls = 7;
365 if (fObservables[i].find("Alpha") != string::npos) ls = 5;
366 if (fObservables[i].find("Argon") != string::npos) ls = 5;
367 if (fObservables[i].find("Xenon") != string::npos) ls = 5;
368 if (fObservables[i].find("Neon") != string::npos) ls = 4;
369
370 TString processName = fObservables[i].substr(fObservables[i].length() - (ls + 7), ls).c_str();
371 TString volName3 = fObservables[i].substr(0, fObservables[i].length() - (ls + 7)).c_str();
372 Int_t volId3 = fG4Metadata->GetActiveVolumeID(volName3);
373
374 if (volId3 >= 0) {
375 fProcessObservables.push_back(fObservables[i]);
376 fVolumeID3.push_back(volId3);
377 fProcessName.emplace_back(processName.Data());
378 }
379 }
380 if (fObservables[i].find("TracksCounter") != string::npos) {
381 TString particleName = fObservables[i].substr(0, fObservables[i].length() - 13).c_str();
382 fTrackCounterObservables.push_back(fObservables[i]);
383 fParticleTrackCounter.emplace_back(particleName.Data());
384 }
385
386 if (fObservables[i].find("TracksEDep") != string::npos) {
387 TString particleName = fObservables[i].substr(0, fObservables[i].length() - 10).c_str();
388 fTracksEDepObservables.push_back(fObservables[i]);
389 fParticleTrackEdep.emplace_back(particleName.Data());
390 }
391 }
392}
393
398 fInputG4Event = (TRestGeant4Event*)inputEvent;
399 *fOutputG4Event = *((TRestGeant4Event*)inputEvent);
400
401 const auto sensitiveVolumeName = fG4Metadata->GetSensitiveVolume();
402
403 Double_t sensitiveVolumeEnergy = fOutputG4Event->GetEnergyInVolume(sensitiveVolumeName.Data());
404 // Get time of the first hit in the sensitive volume
405 double hitTime = std::numeric_limits<double>::infinity();
406 std::set<int> trackIdsInSensitiveVolume;
407
408 for (const auto& track : fOutputG4Event->GetTracks()) {
409 const auto& hits = track.GetHits();
410 for (size_t hitIndex = 0; hitIndex < hits.GetNumberOfHits(); hitIndex++) {
411 const auto volumeName = hits.GetVolumeName(hitIndex);
412 if (volumeName != sensitiveVolumeName) {
413 continue;
414 }
415 const double energy = hits.GetEnergy(hitIndex);
416 if (energy <= 0) {
417 continue;
418 }
419
420 const double time = hits.GetTime(hitIndex);
421 if (time < hitTime) {
422 hitTime = time;
423 }
424
425 trackIdsInSensitiveVolume.insert(track.GetTrackID());
426 }
427 }
428
429 SetObservableValue("sensitiveVolumeFirstHitTime", hitTime);
430
431 std::set<int> trackParentsOfInterest;
432 for (const auto& trackIdInSensitiveVolume : trackIdsInSensitiveVolume) {
433 const auto track = fOutputG4Event->GetTrackByID(trackIdInSensitiveVolume);
434 TRestGeant4Track* parent = track;
435 bool found = false;
436 while (parent != nullptr && !found) {
437 // iterate over hits
438 const auto& hits = parent->GetHits();
439 if (hits.GetVolumeName(0) != sensitiveVolumeName) {
440 for (size_t hitIndex = 0; hitIndex < hits.GetNumberOfHits(); hitIndex++) {
441 const auto volumeName = hits.GetVolumeName(hitIndex);
442 if (volumeName != sensitiveVolumeName) {
443 found = true;
444 trackParentsOfInterest.insert(parent->GetTrackID());
445 break;
446 }
447 }
448 }
449
450 parent = parent->GetParentTrack();
451 }
452 }
453
454 if (!trackParentsOfInterest.empty()) {
455 const auto track = fOutputG4Event->GetTrackByID(*trackParentsOfInterest.begin());
456
457 const auto position = track->GetInitialPosition();
458 SetObservableValue("firstTrackInSensitivePositionX", position.X());
459 SetObservableValue("firstTrackInSensitivePositionY", position.Y());
460 SetObservableValue("firstTrackInSensitivePositionZ", position.Z());
461
462 const auto energy = track->GetInitialKineticEnergy();
463 SetObservableValue("firstTrackInSensitiveEnergy", energy);
464
465 const string particleName = track->GetParticleName().Data();
466 SetObservableValue("firstTrackInSensitiveParticle", particleName);
467
468 string parentParticleName;
469 if (track->GetParentTrack() != nullptr) {
470 parentParticleName = track->GetParentTrack()->GetParticleName().Data();
471 }
472 SetObservableValue("firstTrackInSensitiveParentParticle", parentParticleName);
473
474 const string creatorProcess = track->GetCreatorProcess().Data();
475 SetObservableValue("firstTrackInSensitiveCreatorProcess", creatorProcess);
476
477 const string volumeName = track->GetHits().GetVolumeName(0).Data();
478 SetObservableValue("firstTrackInSensitiveVolumeName", volumeName);
479 }
480
481 SetObservableValue("firstTrackInSensitiveOk", trackParentsOfInterest.size() == 1);
482
484 cout << "----------------------------" << endl;
485 cout << "TRestGeant4Event : " << fOutputG4Event->GetID() << endl;
486 cout << "Sensitive volume Energy : " << sensitiveVolumeEnergy << endl;
487 cout << "Total energy : " << fOutputG4Event->GetTotalDepositedEnergy() << endl;
488 }
489
490 SetObservableValue("sensitiveVolumeEnergy", sensitiveVolumeEnergy);
491
492 Double_t xOrigin = fOutputG4Event->GetPrimaryEventOrigin().X();
493 SetObservableValue("xOriginPrimary", xOrigin);
494
495 Double_t yOrigin = fOutputG4Event->GetPrimaryEventOrigin().Y();
496 SetObservableValue("yOriginPrimary", yOrigin);
497
498 Double_t zOrigin = fOutputG4Event->GetPrimaryEventOrigin().Z();
499 SetObservableValue("zOriginPrimary", zOrigin);
500
501 Double_t xDirection = fOutputG4Event->GetPrimaryEventDirection(0).X();
502 SetObservableValue("xDirectionPrimary", xDirection);
503
504 Double_t yDirection = fOutputG4Event->GetPrimaryEventDirection(0).Y();
505 SetObservableValue("yDirectionPrimary", yDirection);
506
507 Double_t zDirection = fOutputG4Event->GetPrimaryEventDirection(0).Z();
508 SetObservableValue("zDirectionPrimary", zDirection);
509
510 SetObservableValue("eventPrimaryParticleName", fOutputG4Event->GetPrimaryEventParticleName(0));
511 string subEventPrimaryParticleName;
512 if (fOutputG4Event->GetSubID() != 0) {
513 subEventPrimaryParticleName = fOutputG4Event->GetSubEventPrimaryEventParticleName();
514 } else {
515 subEventPrimaryParticleName = "generator";
516 }
517 SetObservableValue("subEventPrimaryParticleName", subEventPrimaryParticleName);
518
519 TVector3 primaryDirection(xDirection, yDirection, zDirection);
520 primaryDirection = primaryDirection.Unit();
521 SetObservableValue("thetaPrimary", primaryDirection.Theta());
522 SetObservableValue("phiPrimary", primaryDirection.Phi());
523 SetObservableValue("zenithYDegrees", TMath::ACos(-1 * yDirection) * TMath::RadToDeg());
524 TVector3 sourceDirection = fG4Metadata->GetParticleSource(0)->GetDirection();
525 sourceDirection = sourceDirection.Unit();
526 SetObservableValue("zenithSourceDegrees",
527 TMath::ACos(primaryDirection.Dot(sourceDirection)) * TMath::RadToDeg());
528
529 Double_t energyPrimary = fOutputG4Event->GetPrimaryEventEnergy(0);
530 SetObservableValue("energyPrimary", energyPrimary);
531
532 Double_t energyTotal = fOutputG4Event->GetTotalDepositedEnergy();
533 SetObservableValue("totalEdep", energyTotal);
534
535 Double_t size = fOutputG4Event->GetBoundingBoxSize();
536 SetObservableValue("boundingSize", size);
537
538 // process names as named by Geant4
539 // processes present here will be added to the list of observables which can be used to see if the event
540 // contains the process of interest.
541 vector<string> processNames = {"phot", "compt"};
542 for (auto& processName : processNames) {
543 Int_t containsProcess = 0;
544 if (fOutputG4Event->ContainsProcess(fG4Metadata->GetGeant4PhysicsInfo().GetProcessID(processName))) {
545 containsProcess = 1;
546 }
547
548 if (!processName.empty()) {
549 processName[0] = toupper(processName[0]);
550 SetObservableValue("containsProcess" + processName, containsProcess);
551 }
552 }
553
554 for (unsigned int n = 0; n < fParticleTrackCounter.size(); n++) {
555 Int_t nT = fOutputG4Event->GetNumberOfTracksForParticle(fParticleTrackCounter[n]);
556 string obsName = fTrackCounterObservables[n];
557 SetObservableValue(obsName, nT);
558 }
559
560 for (unsigned int n = 0; n < fTracksEDepObservables.size(); n++) {
561 Double_t energy = fOutputG4Event->GetEnergyDepositedByParticle(fParticleTrackEdep[n]);
562 string obsName = fTracksEDepObservables[n];
563 SetObservableValue(obsName, energy);
564 }
565
566 for (unsigned int n = 0; n < fEnergyInObservables.size(); n++) {
567 Double_t en = fOutputG4Event->GetEnergyInVolume(fVolumeName[n]);
568 string obsName = fEnergyInObservables[n];
569 SetObservableValue(obsName, en);
570 }
571
572 for (unsigned int n = 0; n < fMeanPosObservables.size(); n++) {
573 string obsName = fMeanPosObservables[n];
574
575 Double_t mpos = 0;
576 if (fDirID[n] == (TString) "X")
577 mpos = fOutputG4Event->GetMeanPositionInVolume(fVolumeID2[n]).X();
578
579 else if (fDirID[n] == (TString) "Y")
580 mpos = fOutputG4Event->GetMeanPositionInVolume(fVolumeID2[n]).Y();
581
582 else if (fDirID[n] == (TString) "Z")
583 mpos = fOutputG4Event->GetMeanPositionInVolume(fVolumeID2[n]).Z();
584
585 SetObservableValue(obsName, mpos);
586 }
587
589 cout << "G4 Tracks : " << fOutputG4Event->GetNumberOfTracks() << endl;
590 cout << "----------------------------" << endl;
591 }
592
593 return fOutputG4Event;
594}
595
void SetObservableValue(const std::string &name, const T &value)
Set observable value for AnalysisTree.
A base class for any REST event.
Definition: TRestEvent.h:38
A pure analysis process to extract information from a TRestGeant4Event.
void Initialize() override
Function to initialize input/output event members and define the section name.
std::vector< std::string > fEnergyInObservables
It stores the name of observables xxxVolumeEDep related to the energy deposition in volume xxx.
std::vector< std::string > fDirID
void InitProcess() override
Process initialization. Observable names are interpreted and auxiliar observable members,...
TRestGeant4Event * fInputG4Event
A pointer to the specific TRestGeant4Event input.
void LoadConfig(const std::string &configFilename, const std::string &name="")
Function to load the configuration from an external configuration file.
TRestGeant4Metadata * fG4Metadata
A pointer to the simulation metadata information accessible to TRestRun.
~TRestGeant4AnalysisProcess()
Default destructor.
std::vector< std::string > fTracksEDepObservables
A std::vector storing the observable name xxxTracksEDep for a given xxx particle.
std::vector< std::string > fParticleTrackCounter
A std::vector storing the xxx particle name extracted from xxxTracksCounter.
std::vector< std::string > fProcessObservables
A std::vector storing the name of observables related to processes in a particular active volume.
std::vector< Int_t > fVolumeID2
A std::vector storing the active volume ids corresponding mean position observable xxxMeanPosX,...
void LoadDefaultConfig()
Function to load the default config in absence of RML input.
TRestEvent * ProcessEvent(TRestEvent *inputEvent) override
The main processing event function.
std::vector< Int_t > fVolumeID
A std::vector storing the active volume ids of observables xxxVolumeEDep.
TRestGeant4Event * fOutputG4Event
A pointer to the specific TRestGeant4Event output.
std::vector< std::string > fTrackCounterObservables
A std::vector storing the observable name xxxTracksCounter for a given xxx particle.
std::vector< Int_t > fVolumeID3
A std::vector storing the active volume ids corresponding process observable .
TRestGeant4AnalysisProcess()
Default constructor.
std::vector< std::string > fMeanPosObservables
A std::vector storing the name of active volumes.
std::vector< std::string > fProcessName
A std::vector storing the name of processes.
void EndProcess() override
Function to include required actions after all events have been processed.
std::vector< std::string > fParticleTrackEdep
A std::vector storing the xxx particle name extracted from xxxTracksEDep.
An event class to store geant4 generated event information.
Double_t GetBoundingBoxSize()
This method returns the event size as the size of the bounding box enclosing all hits.
const TRestGeant4PhysicsInfo & GetGeant4PhysicsInfo() const
Returns an immutable reference to the physics info.
TString GetSensitiveVolume(int n=0) const
Returns a std::string with the name of the sensitive volume.
Int_t GetActiveVolumeID(const TString &name)
Returns the id of an active volume giving as parameter its name.
unsigned int GetNumberOfActiveVolumes() const
Returns the number of active volumes, or geometry volumes that have been selected for data storage.
TString GetActiveVolumeName(Int_t n) const
Returns a std::string with the name of the active volume with index n.
TRestGeant4ParticleSource * GetParticleSource(size_t n=0) const
Returns the name of the particle source with index n (Geant4 based names).
Int_t LoadConfigFromFile(const std::string &configFilename, const std::string &sectionName="")
Give the file name, find out the corresponding section. Then call the main starter.
void SetLibraryVersion(TString version)
Set the library version of this metadata class.
TRestStringOutput::REST_Verbose_Level GetVerboseLevel()
returns the verboselevel in type of REST_Verbose_Level enumerator
void SetSectionName(std::string sName)
set the section name, clear the section content
@ REST_Debug
+show the defined debug messages