geant events for multiple scattering

This commit is contained in:
AndreaRigoni
2026-03-14 23:33:31 +00:00
parent 692cdf7ae3
commit c63a1ae047
18 changed files with 681 additions and 90 deletions

View File

@@ -0,0 +1,140 @@
/*//////////////////////////////////////////////////////////////////////////////
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
All rights reserved
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
//////////////////////////////////////////////////////////////////////////////*/
#include "Geant/Solid.h"
#include "HEP/Geant/GeantEvent.h"
#include "HEP/Geant/Scene.h"
#include "HEP/Geant/EmitterPrimary.hh"
#include "Math/ContainerBox.h"
#include "Math/Dense.h"
#include "Vtk/uLibVtkViewer.h"
#include "Vtk/HEP/Geant/vtkGeantEvent.h"
#include "Vtk/vtkContainerBox.h"
#include <vtkSmartPointer.h>
#include <vtkCallbackCommand.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <Geant4/Randomize.hh>
#include <Geant4/G4ParticleGun.hh>
#include <Geant4/G4SystemOfUnits.hh>
#include <iostream>
using namespace uLib;
// Custom emitter to fire random muons towards the cube
class RandomEmitter : public Geant::EmitterPrimary {
public:
virtual void GeneratePrimaries(G4Event* anEvent) override {
// Start from a random point in a square at z = 5m
// Note: unit in Geant4 is mm by default if not specified,
// but here we use the constants from G4SystemOfUnits.h
double x = (G4UniformRand() - 0.5) * 2000; // -1m to 1m
double y = (G4UniformRand() - 0.5) * 2000; // -1m to 1m
double z = 5000.0; // 5m above origin
fParticleGun->SetParticlePosition(G4ThreeVector(x, y, z));
// Aim at a random point within the cube (which is at origin, size 1m)
double tx = (G4UniformRand() - 0.5) * 1000;
double ty = (G4UniformRand() - 0.5) * 1000;
double tz = (G4UniformRand() - 0.5) * 1000;
G4ThreeVector dir(tx - x, ty - y, tz - z);
dir = dir.unit();
fParticleGun->SetParticleMomentumDirection(dir);
fParticleGun->GeneratePrimaryVertex(anEvent);
}
};
struct AppState {
Geant::Scene* scene;
Vtk::Viewer* viewer;
Vector<Geant::GeantEvent> results;
};
void KeyPressCallbackFunction(vtkObject* caller, long unsigned int eventId, void* clientData, void* callData) {
auto* interactor = static_cast<vtkRenderWindowInteractor*>(caller);
auto* state = static_cast<AppState*>(clientData);
std::string key = interactor->GetKeySym();
if (key == "Return") {
std::cout << "--> Firing random muon..." << std::endl;
// Run one event
state->scene->RunSimulation(1, state->results);
if (!state->results.empty()) {
// Get the last event
Geant::GeantEvent* lastEvent = &state->results.back();
std::cout << " Collected event " << lastEvent->GetEventID()
<< " with " << lastEvent->Path().size() << " steps." << std::endl;
// Wrap it for VTK
Vtk::vtkGeantEvent* vtkEvent = new Vtk::vtkGeantEvent(lastEvent);
state->viewer->AddPuppet(*vtkEvent);
// Re-render
state->viewer->GetRenderer()->Render();
state->viewer->GetRenderWindow()->Render();
}
}
}
int main(int argc, char** argv) {
// 1. Setup Geant4 Scene
ContainerBox world_box(Vector3f(30000, 30000, 30000));
Geant::Scene scene;
scene.ConstructWorldBox(&world_box, "G4_AIR");
ContainerBox iron_box(Vector3f(1000, 1000, 1000));
Geant::BoxSolid* iron_cube = new Geant::BoxSolid("IronCube", &iron_box);
iron_cube->SetNistMaterial("G4_Fe");
iron_cube->Update();
scene.AddSolid(iron_cube);
RandomEmitter* emitter = new RandomEmitter();
scene.SetEmitter(emitter);
scene.Initialize();
// 2. Setup VTK Viewer
Vtk::Viewer viewer;
viewer.GetRenderer()->SetBackground(0.05, 0.05, 0.1);
// Visualize iron cube
Vtk::vtkContainerBox* vtkIron = new Vtk::vtkContainerBox(&iron_box);
viewer.AddPuppet(*vtkIron);
// 3. Event Handling
AppState state = { &scene, &viewer, {} };
vtkSmartPointer<vtkCallbackCommand> keyCallback = vtkSmartPointer<vtkCallbackCommand>::New();
keyCallback->SetCallback(KeyPressCallbackFunction);
keyCallback->SetClientData(&state);
viewer.GetInteractor()->AddObserver(vtkCommand::KeyPressEvent, keyCallback);
std::cout << "=================================================" << std::endl;
std::cout << " Geant Muon Simulation Viewer" << std::endl;
std::cout << " Press [ENTER] to fire a new random muon" << std::endl;
std::cout << " Press [q] to exit" << std::endl;
std::cout << "=================================================" << std::endl;
viewer.ZoomAuto();
viewer.Start();
return 0;
}