diff --git a/FullSimLight/Plugins/CMakeLists.txt b/FullSimLight/Plugins/CMakeLists.txt index 3fccb0bd3e167bd82d77bf22b9a1f7a5401eecfe..e38a1393a11848b7d8ff4e4f9a787b48df323b93 100644 --- a/FullSimLight/Plugins/CMakeLists.txt +++ b/FullSimLight/Plugins/CMakeLists.txt @@ -42,7 +42,8 @@ include( GNUInstallDirs ) # Set up the build of the libraries of the project. add_subdirectory(HitsPlugin) add_subdirectory(Examples/UserActionPlugins) -add_subdirectory(TracksPlugin) +add_subdirectory(GenerateTracksPluginROOT) +#add_subdirectory(TracksPlugin) add_subdirectory(Examples/PhysicsListPlugins/FSLTestPhysListPlugins) add_subdirectory(Examples/EventGeneratorPlugins/FSLExamplePrimaryGeneratorPlugin) add_subdirectory(Examples/SensitiveDetectorPlugins/SDPlugin) diff --git a/FullSimLight/Plugins/GenerateTracksPluginROOT/TracksPlugin.cc b/FullSimLight/Plugins/GenerateTracksPluginROOT/TracksPlugin.cc index 30a125eb12c1506081a74143c6471e81ab1d56b3..7ece2aef48788d13668741e01f46e0d40feae181 100644 --- a/FullSimLight/Plugins/GenerateTracksPluginROOT/TracksPlugin.cc +++ b/FullSimLight/Plugins/GenerateTracksPluginROOT/TracksPlugin.cc @@ -44,7 +44,7 @@ G4UserSteppingAction* TracksPlugin::getSteppingAction() const return new TrksSteppingAction; } -extern "C" TracksPlugin *createGenerateTracksPlugin() { +extern "C" TracksPlugin *createGenerateTracksPluginROOT() { return new TracksPlugin(); } diff --git a/FullSimLight/Plugins/GenerateTracksPluginROOT/include/TrksEventAction.h b/FullSimLight/Plugins/GenerateTracksPluginROOT/include/TrksEventAction.h index 97a250afe4e97576092cec60645d8c57368612e0..7ef236f7b666f26eb934c4e3b90a725903b4e86b 100644 --- a/FullSimLight/Plugins/GenerateTracksPluginROOT/include/TrksEventAction.h +++ b/FullSimLight/Plugins/GenerateTracksPluginROOT/include/TrksEventAction.h @@ -9,9 +9,9 @@ struct stepData { - float x; - float y; - float z; + float x, y, z; // Position + float px, py, pz; // Momentum components + float energy; // Kinetic energy }; class TrksEventAction: public G4UserEventAction diff --git a/FullSimLight/Plugins/GenerateTracksPluginROOT/include/TrksROOTFactory.h b/FullSimLight/Plugins/GenerateTracksPluginROOT/include/TrksROOTFactory.h index cd4d69edb092932315bf45f29d945fbf67c3e7b3..e083e474936bfe762e8297669ec0597e544eb376 100644 --- a/FullSimLight/Plugins/GenerateTracksPluginROOT/include/TrksROOTFactory.h +++ b/FullSimLight/Plugins/GenerateTracksPluginROOT/include/TrksROOTFactory.h @@ -3,6 +3,8 @@ #include "TFile.h" #include "TTree.h" +#include "TH1F.h" +#include "TH2F.h" #include <mutex> #include <vector> @@ -14,15 +16,22 @@ public: static TrksROOTFactory* GetInstance(); static void OpenFile(const char* name); static void CloseFile(); - static TFile* GetFile() { return fgFile; } + static void CreateHistograms(); // Method to initialize histograms + static void FillHistograms(float x, float px); // Method to fill histograms + private: TrksROOTFactory(); ~TrksROOTFactory(); static TrksROOTFactory* fgInstance; static TFile* fgFile; + + // Static histograms for x, px, and x vs. px + static TH1F* hX; + static TH1F* hPx; + static TH2F* hXvsPx; }; #endif // __TrksROOTFactory_hh__ diff --git a/FullSimLight/Plugins/GenerateTracksPluginROOT/include/TrksSteppingAction.h b/FullSimLight/Plugins/GenerateTracksPluginROOT/include/TrksSteppingAction.h index c39d1cdec49c8d4b8f82503fb55c045f69717fb0..d3cc8a650b6cfa267b334c0b7c39f373060b524e 100644 --- a/FullSimLight/Plugins/GenerateTracksPluginROOT/include/TrksSteppingAction.h +++ b/FullSimLight/Plugins/GenerateTracksPluginROOT/include/TrksSteppingAction.h @@ -4,6 +4,8 @@ #include "G4UserSteppingAction.hh" #include "G4Step.hh" +#include "TH1F.h" +#include "TH2F.h" class G4Step; diff --git a/FullSimLight/Plugins/GenerateTracksPluginROOT/src/TrksEventAction.cc b/FullSimLight/Plugins/GenerateTracksPluginROOT/src/TrksEventAction.cc index 28157566bc87e9879c83b306d10ca95f772f3e05..5926fe8fd52ba16b095925c7982be949cfbcd3bf 100644 --- a/FullSimLight/Plugins/GenerateTracksPluginROOT/src/TrksEventAction.cc +++ b/FullSimLight/Plugins/GenerateTracksPluginROOT/src/TrksEventAction.cc @@ -3,6 +3,8 @@ #include "G4Event.hh" #include "TrksRunAction.h" #include <string> +#include "TH1F.h" +#include "TH2F.h" using namespace std; @@ -14,12 +16,21 @@ G4ThreadLocal std::map<int, std::vector<stepData>> TrksEventAction::trksInfoMap; //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... -TrksEventAction::TrksEventAction() {} -TrksEventAction::~TrksEventAction() {} +TrksEventAction::TrksEventAction() { + // Ensure the ROOT file is opened at the start + TrksROOTFactory::OpenFile("output.root"); +} + +TrksEventAction::~TrksEventAction() { + // Ensure the ROOT file is saved and closed at the end + TrksROOTFactory::CloseFile(); +} //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... -void TrksEventAction::BeginOfEventAction(const G4Event*) {} +void TrksEventAction::BeginOfEventAction(const G4Event*) { + // This can be used to initialize event-specific data if needed +} //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... @@ -51,13 +62,23 @@ void TrksEventAction::EndOfEventAction(const G4Event* anEvent) gPDGsVec.push_back(el.second); // Collect track step data - std::vector<float> xCoords, yCoords, zCoords; + std::vector<float> xCoords, yCoords, zCoords; // Position + std::vector<float> pxCoords, pyCoords, pzCoords; // Momentum components + std::vector<float> energies; // Kinetic energy + for (const auto& trkInfo : trksInfoMap) { const std::vector<stepData>& steps = trkInfo.second; for (const auto& step : steps) { xCoords.push_back(step.x); yCoords.push_back(step.y); zCoords.push_back(step.z); + pxCoords.push_back(step.px); + pyCoords.push_back(step.py); + pzCoords.push_back(step.pz); + energies.push_back(step.energy); + + // Fill histograms for x and px using TrksROOTFactory + //TrksROOTFactory::FillHistograms(step.x, step.px); } } @@ -67,6 +88,10 @@ void TrksEventAction::EndOfEventAction(const G4Event* anEvent) if (!tree->GetBranch("x")) tree->Branch("x", &xCoords); if (!tree->GetBranch("y")) tree->Branch("y", &yCoords); if (!tree->GetBranch("z")) tree->Branch("z", &zCoords); + if (!tree->GetBranch("px")) tree->Branch("px", &pxCoords); + if (!tree->GetBranch("py")) tree->Branch("py", &pyCoords); + if (!tree->GetBranch("pz")) tree->Branch("pz", &pzCoords); + if (!tree->GetBranch("energy")) tree->Branch("energy", &energies); // Fill the tree with collected data tree->Fill(); diff --git a/FullSimLight/Plugins/GenerateTracksPluginROOT/src/TrksROOTFactory.cc b/FullSimLight/Plugins/GenerateTracksPluginROOT/src/TrksROOTFactory.cc index 9ca7b4f7a368899daa28df02842bc2f308c7cc9c..84bff33b01fd2910b2264bcbfa68e5ccabe4442a 100644 --- a/FullSimLight/Plugins/GenerateTracksPluginROOT/src/TrksROOTFactory.cc +++ b/FullSimLight/Plugins/GenerateTracksPluginROOT/src/TrksROOTFactory.cc @@ -1,44 +1,75 @@ #include "TrksROOTFactory.h" -#include "G4UnitsTable.hh" +#include <iostream> +#include "TH1F.h" +#include "TH2F.h" -// Singleton instance and static variables +// Static member initializations TrksROOTFactory* TrksROOTFactory::fgInstance = nullptr; TFile* TrksROOTFactory::fgFile = nullptr; std::mutex TrksROOTFactory::gWriteFileMutex; -TrksROOTFactory::TrksROOTFactory() -{ +// Static histogram pointers +TH1F* TrksROOTFactory::hX = nullptr; +TH1F* TrksROOTFactory::hPx = nullptr; +TH2F* TrksROOTFactory::hXvsPx = nullptr; + +TrksROOTFactory::TrksROOTFactory() { fgInstance = this; } -TrksROOTFactory::~TrksROOTFactory() -{ - // Close and delete the ROOT file if open +TrksROOTFactory::~TrksROOTFactory() { CloseFile(); fgInstance = nullptr; } -TrksROOTFactory* TrksROOTFactory::GetInstance() -{ - if (!fgInstance) - fgInstance = new TrksROOTFactory; +TrksROOTFactory* TrksROOTFactory::GetInstance() { + if (!fgInstance) { + fgInstance = new TrksROOTFactory(); + } return fgInstance; } -void TrksROOTFactory::OpenFile(const char* name) -{ +void TrksROOTFactory::OpenFile(const char* name) { + gWriteFileMutex.lock(); fgFile = new TFile(name, "RECREATE"); - G4cout << "ROOT file " << name << " opened for writing." << G4endl; + if (fgFile && !fgFile->IsZombie()) { + std::cout << "ROOT file " << name << " opened for writing." << std::endl; + CreateHistograms(); // Initialize histograms when file is opened + } else { + std::cerr << "Error opening ROOT file " << name << std::endl; + } + gWriteFileMutex.unlock(); } -void TrksROOTFactory::CloseFile() -{ - if (fgFile) - { +void TrksROOTFactory::CloseFile() { + gWriteFileMutex.lock(); + if (fgFile) { fgFile->Write(); // Write all data to the file before closing fgFile->Close(); delete fgFile; fgFile = nullptr; - G4cout << "ROOT file closed successfully." << G4endl; + std::cout << "ROOT file closed successfully." << std::endl; + } + gWriteFileMutex.unlock(); +} + +void TrksROOTFactory::CreateHistograms() { + // Initialize histograms only if they haven't been created yet + if (!hX && !hPx && !hXvsPx) { + hX = new TH1F("hX", "X Position Distribution; X [units]; Counts", 100, -10, 10); + hPx = new TH1F("hPx", "Px Momentum Distribution; Px [units]; Counts", 100, -5, 5); + hXvsPx = new TH2F("hXvsPx", "X vs Px; X [units]; Px [units]", 100, -10, 10, 100, -5, 5); + } +} + +void TrksROOTFactory::FillHistograms(float x, float px) { + std::lock_guard<std::mutex> lock(gWriteFileMutex); + + if (hX && hPx && hXvsPx) { + hX->Fill(x); + hPx->Fill(px); + hXvsPx->Fill(x, px); + } else { + std::cerr << "Histograms not initialized. Call OpenFile() first." << std::endl; } } diff --git a/FullSimLight/Plugins/GenerateTracksPluginROOT/src/TrksSteppingAction.cc b/FullSimLight/Plugins/GenerateTracksPluginROOT/src/TrksSteppingAction.cc index bee5fb190fc4f95b999f97abef1eecc04bc5ba75..2d92bc83708d90c10678b508f807846764f2886e 100644 --- a/FullSimLight/Plugins/GenerateTracksPluginROOT/src/TrksSteppingAction.cc +++ b/FullSimLight/Plugins/GenerateTracksPluginROOT/src/TrksSteppingAction.cc @@ -30,9 +30,15 @@ void TrksSteppingAction::UserSteppingAction(const G4Step * aStep) tmpStepData.x = aStep->GetPostStepPoint()->GetPosition().getX(); tmpStepData.y = aStep->GetPostStepPoint()->GetPosition().getY(); tmpStepData.z = aStep->GetPostStepPoint()->GetPosition().getZ(); + + // Add momentum and energy information + tmpStepData.px = aStep->GetPostStepPoint()->GetMomentum().getX(); + tmpStepData.py = aStep->GetPostStepPoint()->GetMomentum().getY(); + tmpStepData.pz = aStep->GetPostStepPoint()->GetMomentum().getZ(); + tmpStepData.energy = aStep->GetPostStepPoint()->GetKineticEnergy(); std::map<int, std::vector<stepData>> &trksInfoMap = TrksEventAction::trksInfoMap; trksInfoMap[trkNum].push_back(tmpStepData); -} \ No newline at end of file +} diff --git a/FullSimLight/Plugins/GenerateTracksPluginROOT/src/TrksTrackingAction.cc b/FullSimLight/Plugins/GenerateTracksPluginROOT/src/TrksTrackingAction.cc index 589bffb584ebf3a11e44fb1f3ea96c773054354c..f1c68aa679d2f95b24d7eaef24435b664a3819ab 100644 --- a/FullSimLight/Plugins/GenerateTracksPluginROOT/src/TrksTrackingAction.cc +++ b/FullSimLight/Plugins/GenerateTracksPluginROOT/src/TrksTrackingAction.cc @@ -38,6 +38,12 @@ void TrksTrackingAction::PreUserTrackingAction(const G4Track* aTrack) tmpStepData.x = aTrack->GetPosition().getX(); tmpStepData.y = aTrack->GetPosition().getY(); tmpStepData.z = aTrack->GetPosition().getZ(); + + // Add momentum and kinetic energy to the step data + tmpStepData.px = aTrack->GetMomentum().getX(); + tmpStepData.py = aTrack->GetMomentum().getY(); + tmpStepData.pz = aTrack->GetMomentum().getZ(); + tmpStepData.energy = aTrack->GetKineticEnergy(); if (trksInfoMap.find(trkNum) != trksInfoMap.end()) //track ID already in the map { @@ -60,4 +66,4 @@ void TrksTrackingAction::PreUserTrackingAction(const G4Track* aTrack) void TrksTrackingAction::PostUserTrackingAction(const G4Track* /*aTrack*/) { -} \ No newline at end of file +}