/* This file is part of MAUS: http:// micewww.pp.rl.ac.uk:8080/projects/maus * * MAUS is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MAUS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MAUS. If not, see . */ #include "gtest/gtest.h" #include "Geant4/G4Step.hh" #include "Geant4/G4ParticleTable.hh" #include "Geant4/G4Material.hh" #include "Geant4/G4GRSVolume.hh" #include "Geant4/G4RotationMatrix.hh" #include "Geant4/G4ThreeVector.hh" #include "Geant4/G4PVPlacement.hh" #include "src/common_cpp/Utils/JsonWrapper.hh" #include "src/common_cpp/Simulation/MAUSGeant4Manager.hh" #include "src/common_cpp/Simulation/MAUSSteppingAction.hh" #include "src/common_cpp/Simulation/VirtualPlanes.hh" #include "src/legacy/Interface/MICERun.hh" using namespace MAUS; namespace { class MAUSSteppingActionTest : public ::testing::Test { protected: MAUSSteppingActionTest() : stepping(MAUSGeant4Manager::GetInstance()->GetStepping()) { G4ParticleDefinition* pd = G4ParticleTable::GetParticleTable()->FindParticle(-13); G4DynamicParticle* dyn = new G4DynamicParticle(pd, G4ThreeVector(1., 2., 3.)); track = new G4Track(dyn, 7., G4ThreeVector(4., 5., 6.)); step = new G4Step(); // memory leak? point = new G4StepPoint(); point->SetPosition(G4ThreeVector(1., 2., 3.)); point->SetMass(pd->GetPDGMass()); point->SetMomentumDirection(G4ThreeVector(0., ::sqrt(0.5), ::sqrt(0.5))); point->SetKineticEnergy(100.); post = new G4StepPoint(); post->SetPosition(G4ThreeVector(7., 8., 9.)); post->SetMass(pd->GetPDGMass()); post->SetMomentumDirection(G4ThreeVector(::sqrt(1./3.), ::sqrt(1./3.), ::sqrt(1./3.))); post->SetKineticEnergy(110.); post->SetGlobalTime(-10.); track->SetStep(step); step->SetTrack(track); step->SetPreStepPoint(point); step->SetPostStepPoint(post); track->AddTrackLength(10.); step->SetTotalEnergyDeposit(8.); point->SetGlobalTime(1.); point->SetProperTime(2.); point->SetPosition(G4ThreeVector(2.,3.,4.)); point->SetMomentumDirection(G4ThreeVector(1.,2.,3.)); point->SetKineticEnergy(9.); } virtual ~MAUSSteppingActionTest() {} virtual void SetUp() {} virtual void TearDown() {} MAUS::MAUSSteppingAction* stepping; G4Track* track; G4Step* step; G4StepPoint* point; G4StepPoint* post; }; // test get and set work correctly TEST_F(MAUSSteppingActionTest, GetSetTest) { stepping->SetWillKeepSteps(true); EXPECT_EQ(stepping->GetWillKeepSteps(), true); stepping->SetWillKeepSteps(false); EXPECT_EQ(stepping->GetWillKeepSteps(), false); EXPECT_THROW(stepping->SetSteps(Json::Value(Json::objectValue)), MAUS::Exception); Json::Value array(Json::arrayValue); array.append(Json::Value("Hello")); EXPECT_NO_THROW(stepping->SetSteps(array)); EXPECT_EQ(array, stepping->GetSteps()); } // test that we set stop and kill if stepping goes more than max n steps TEST_F(MAUSSteppingActionTest, UserSteppingActionMaxNStepsTest) { Json::Value& conf = *MICERun::getInstance()->jsonConfiguration; int maxNSteps = JsonWrapper::GetProperty (conf, "maximum_number_of_steps", JsonWrapper::intValue).asInt(); MAUSTrackingAction* tracking = MAUSGeant4Manager::GetInstance()->GetTracking(); tracking->SetWillKeepTracks(true); tracking->SetTracks(Json::Value(Json::arrayValue)); tracking->PreUserTrackingAction(step->GetTrack()); stepping->SetSteps(Json::Value(Json::arrayValue)); stepping->UserSteppingAction(step); ASSERT_TRUE(tracking->GetTracks()[Json::Value::UInt(0)].isObject()); EXPECT_EQ(tracking->GetTracks()[Json::Value::UInt(0)]["kill_reason"].type(), Json::stringValue); for (int i = 0; i < maxNSteps+1; ++i) track->IncrementCurrentStepNumber(); stepping->UserSteppingAction(step); EXPECT_EQ(tracking->GetTracks()[Json::Value::UInt(0)]["kill_reason"].type(), Json::stringValue); EXPECT_EQ(track->GetTrackStatus(), fStopAndKill); } // test that we write steps correctly on each step (or not if flag is false) TEST_F(MAUSSteppingActionTest, UserSteppingActionWriteStepsTest) { stepping->SetSteps(Json::Value(Json::arrayValue)); stepping->SetWillKeepSteps(false); stepping->SetSteps(Json::Value(Json::arrayValue)); stepping->UserSteppingAction(step); EXPECT_EQ(stepping->GetSteps()[Json::UInt(0)].type(), Json::nullValue); stepping->SetWillKeepSteps(true); stepping->UserSteppingAction(step); stepping->UserSteppingAction(step); ASSERT_EQ(stepping->GetSteps().type(), Json::arrayValue); // we want 3 steps - 2 post steps plus the first one EXPECT_EQ(stepping->GetSteps().size(), static_cast(3)); } // test that we write to json correctly TEST_F(MAUSSteppingActionTest, StepToJsonTest) { G4Material material("material_test", 1, 1, 1.); post->SetMaterial(&material); Json::Value out = stepping->StepToJson(step, true); EXPECT_DOUBLE_EQ(out["position"]["x"].asDouble(), point->GetPosition().x()); EXPECT_DOUBLE_EQ(out["position"]["y"].asDouble(), point->GetPosition().y()); EXPECT_DOUBLE_EQ(out["position"]["z"].asDouble(), point->GetPosition().z()); EXPECT_DOUBLE_EQ(out["momentum"]["x"].asDouble(), point->GetMomentum().x()); EXPECT_DOUBLE_EQ(out["momentum"]["y"].asDouble(), point->GetMomentum().y()); EXPECT_DOUBLE_EQ(out["momentum"]["z"].asDouble(), point->GetMomentum().z()); EXPECT_DOUBLE_EQ(out["spin"]["x"].asDouble(), point->GetPolarization().x()); EXPECT_DOUBLE_EQ(out["spin"]["y"].asDouble(), point->GetPolarization().y()); EXPECT_DOUBLE_EQ(out["spin"]["z"].asDouble(), point->GetPolarization().z()); EXPECT_DOUBLE_EQ(out["b_field"]["x"].asDouble(), 0.); EXPECT_DOUBLE_EQ(out["b_field"]["y"].asDouble(), 0.); EXPECT_DOUBLE_EQ(out["b_field"]["z"].asDouble(), 0.); EXPECT_DOUBLE_EQ(out["e_field"]["x"].asDouble(), 0.); EXPECT_DOUBLE_EQ(out["e_field"]["y"].asDouble(), 0.); EXPECT_DOUBLE_EQ(out["e_field"]["z"].asDouble(), 0.); EXPECT_DOUBLE_EQ(out["energy_deposited"].asDouble(), 8.); EXPECT_DOUBLE_EQ(out["energy"].asDouble(), point->GetTotalEnergy()); EXPECT_DOUBLE_EQ(out["time"].asDouble(), point->GetGlobalTime()); EXPECT_DOUBLE_EQ(out["proper_time"].asDouble(), point->GetProperTime()); EXPECT_DOUBLE_EQ(out["path_length"].asDouble(), track->GetTrackLength()); EXPECT_EQ(out["material"].asString(), ""); EXPECT_EQ(out["volume"].asString(), ""); out = stepping->StepToJson(step, false); EXPECT_DOUBLE_EQ(out["time"].asDouble(), post->GetGlobalTime()); EXPECT_EQ(out["material"].asString(), "material_test"); } // test that we write volume to json correctly; disabled because it throws a // G4Exception /* TEST_F(MAUSSteppingActionTest, StepToJsonVolumeTest) { G4RotationMatrix rot; G4ThreeVector vec(1., 1., 1.); G4PVPlacement vol(&rot, vec, NULL, "volume_test", NULL, false, 0); G4GRSVolume touchable(&vol, rot, vec); point->SetTouchableHandle(&touchable); Json::Value out = stepping->StepToJson(step, true); EXPECT_EQ(out["volume"].asString(), "volume_test"); } */ G4Track* SetG4TrackAndStep(G4Step* step) { G4ParticleDefinition* pd = G4ParticleTable::GetParticleTable()->FindParticle(-13); G4DynamicParticle* dyn = new G4DynamicParticle(pd, G4ThreeVector(1., 2., 3.)); G4Track* track = new G4Track(dyn, 7., G4ThreeVector(4., 5., 6.)); track->SetStep(step); step->SetTrack(track); step->SetPreStepPoint(new G4StepPoint()); step->SetPostStepPoint(new G4StepPoint()); track->SetTrackID(10); step->GetPreStepPoint()->SetGlobalTime(-1.); step->GetPreStepPoint()->SetPosition(CLHEP::Hep3Vector(2., 3., 4.)); step->GetPreStepPoint()->SetMass(dyn->GetMass()); step->GetPreStepPoint()->SetKineticEnergy(100.); step->GetPreStepPoint()->SetMomentumDirection (CLHEP::Hep3Vector(0., 0.1, 1.)/::sqrt(1.01)); step->GetPostStepPoint()->SetGlobalTime(1.); step->GetPostStepPoint()->SetPosition(CLHEP::Hep3Vector(3., 4., 8.)); step->GetPostStepPoint()->SetMass(dyn->GetMass()); step->GetPostStepPoint()->SetKineticEnergy(110.); step->GetPostStepPoint()->SetMomentumDirection (CLHEP::Hep3Vector(0., 0.1, 1.)/::sqrt(1.01)); return track; } // test that we do virtual stepping correctly TEST_F(MAUSSteppingActionTest, UserSteppingActionVirtualTest) { MiceModule mod; mod.setProperty("PlaneTime", 0.); mod.setProperty("SensitiveDetector", "Virtual"); mod.setProperty("IndependentVariable", "time"); mod.setProperty("MultiplePasses", "NewStation"); VirtualPlaneManager* vpm = MAUSGeant4Manager::GetInstance()->GetVirtualPlanes(); vpm->SetVirtualHits(Json::Value(Json::arrayValue)); vpm->ConstructVirtualPlanes(&mod); vpm->ConstructVirtualPlanes(&mod); G4Step* step = new G4Step(); G4Track* track = SetG4TrackAndStep(step); if(track) {} stepping->UserSteppingAction(step); stepping->UserSteppingAction(step); EXPECT_EQ(vpm->GetVirtualHits().size(), static_cast(4)); } } //namespace end