/* 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 #include "Geant4/G4NistManager.hh" #include "gtest/gtest.h" #include "src/common_cpp/Utils/JsonWrapper.hh" #include "src/common_cpp/Recon/Global/GlobalTools.hh" #include "src/legacy/BeamTools/BTFieldConstructor.hh" #include "src/common_cpp/Globals/GlobalsManager.hh" #include "src/common_cpp/Utils/Globals.hh" #include "src/common_cpp/Simulation/MAUSGeant4Manager.hh" #include "src/common_cpp/Simulation/DetectorConstruction.hh" namespace MAUS { class GlobalToolsTest : public ::testing::Test { protected: GlobalToolsTest() {} virtual ~GlobalToolsTest() {} virtual void SetUp() {} virtual void TearDown() {} }; TEST_F(GlobalToolsTest, GetReconDetectors) { GlobalEvent* global_event = new GlobalEvent; DataStructure::Global::SpacePoint sp; TLorentzVector position(0.0, 0.0, 0.0, 0.0); sp.set_position(position); DataStructure::Global::TrackPoint tp(&sp); DataStructure::Global::SpacePoint* tof1_sp = sp.Clone(); tof1_sp->set_detector(DataStructure::Global::kTOF1); global_event->add_space_point(tof1_sp); DataStructure::Global::SpacePoint* tof2_sp = sp.Clone(); tof2_sp->set_detector(DataStructure::Global::kTOF2); global_event->add_space_point(tof2_sp); DataStructure::Global::SpacePoint* kl_sp = sp.Clone(); kl_sp->set_detector(DataStructure::Global::kCalorimeter); global_event->add_space_point(kl_sp); DataStructure::Global::TrackPoint* tr0_tp = tp.Clone(); tr0_tp->set_detector(DataStructure::Global::kTracker0); DataStructure::Global::TrackPoint* tr1_2_tp = tp.Clone(); tr1_2_tp->set_detector(DataStructure::Global::kTracker1_2); DataStructure::Global::TrackPoint* emr_tp = tp.Clone(); emr_tp->set_detector(DataStructure::Global::kEMR); DataStructure::Global::Track* track = new DataStructure::Global::Track; track->AddTrackPoint(tr0_tp); track->AddTrackPoint(tr1_2_tp); track->AddTrackPoint(emr_tp); global_event->add_track(track); std::map recon_detectors = GlobalTools::GetReconDetectors(global_event); int num_exist = 0; for (auto detector_iter = recon_detectors.begin(); detector_iter != recon_detectors.end(); detector_iter++) { if (detector_iter->second) { num_exist++; } } EXPECT_EQ(num_exist, 6); EXPECT_TRUE(recon_detectors.at(DataStructure::Global::kTOF1)); EXPECT_TRUE(recon_detectors.at(DataStructure::Global::kTracker0)); EXPECT_TRUE(recon_detectors.at(DataStructure::Global::kTracker1_2)); EXPECT_TRUE(recon_detectors.at(DataStructure::Global::kTOF2)); EXPECT_TRUE(recon_detectors.at(DataStructure::Global::kCalorimeter)); EXPECT_TRUE(recon_detectors.at(DataStructure::Global::kEMR)); delete global_event; } TEST_F(GlobalToolsTest, GetSpillDetectorTracks) { Spill* spill = new Spill; ReconEvent* recon_event = new ReconEvent; GlobalEvent* global_event = new GlobalEvent; DataStructure::Global::Track* track = new DataStructure::Global::Track; track->set_mapper_name("GetSpillDetectorTracksTest"); // Use PIDs to uniquely identify tracks later DataStructure::Global::Track* tr0_track1 = track->Clone(); tr0_track1->set_pid(DataStructure::Global::kEMinus); tr0_track1->SetDetector(DataStructure::Global::kTracker0); global_event->add_track(tr0_track1); DataStructure::Global::Track* tr0_track2 = track->Clone(); tr0_track2->set_pid(DataStructure::Global::kEPlus); tr0_track2->SetDetector(DataStructure::Global::kTracker0); global_event->add_track(tr0_track2); DataStructure::Global::Track* tr1_track = track->Clone(); tr1_track->set_pid(DataStructure::Global::kMuMinus); tr1_track->SetDetector(DataStructure::Global::kTracker1); global_event->add_track(tr1_track); DataStructure::Global::Track* tr1_track_wrong_mn = track->Clone(); tr1_track_wrong_mn->set_mapper_name("TEST"); tr1_track_wrong_mn->SetDetector(DataStructure::Global::kTracker1); global_event->add_track(tr1_track_wrong_mn); DataStructure::Global::Track* emr_prim = track->Clone(); emr_prim->set_pid(DataStructure::Global::kPiPlus); emr_prim->SetDetector(DataStructure::Global::kEMR); global_event->add_track(emr_prim); DataStructure::Global::Track* emr_sec = track->Clone(); emr_sec->set_pid(DataStructure::Global::kPiMinus); emr_sec->set_emr_range_secondary(10.0); emr_sec->SetDetector(DataStructure::Global::kEMR); global_event->add_track(emr_sec); DataStructure::Global::Track* mix_track = track->Clone(); mix_track->set_pid(DataStructure::Global::kPhoton); mix_track->SetDetector(DataStructure::Global::kTracker1); mix_track->SetDetector(DataStructure::Global::kEMR); global_event->add_track(mix_track); recon_event->SetGlobalEvent(global_event); std::vector* recon_events = new std::vector; recon_events->push_back(recon_event); spill->SetReconEvents(recon_events); auto tracker0_tracks = GlobalTools::GetSpillDetectorTracks(spill, DataStructure::Global::kTracker0, "GetSpillDetectorTracksTest"); EXPECT_EQ(tracker0_tracks->size(), 2); if (tracker0_tracks->size() > 1) { EXPECT_EQ(tracker0_tracks->at(0)->get_pid(), DataStructure::Global::kEMinus); EXPECT_EQ(tracker0_tracks->at(1)->get_pid(), DataStructure::Global::kEPlus); } auto tracker1_tracks = GlobalTools::GetSpillDetectorTracks(spill, DataStructure::Global::kTracker1, "GetSpillDetectorTracksTest"); EXPECT_EQ(tracker1_tracks->size(), 2); if (tracker1_tracks->size() > 1) { EXPECT_EQ(tracker1_tracks->at(0)->get_pid(), DataStructure::Global::kMuMinus); EXPECT_EQ(tracker1_tracks->at(1)->get_pid(), DataStructure::Global::kPhoton); } auto emr_tracks = GlobalTools::GetSpillDetectorTracks(spill, DataStructure::Global::kEMR, "GetSpillDetectorTracksTest"); EXPECT_EQ(emr_tracks->size(), 2); if (emr_tracks->size() > 1) { EXPECT_EQ(emr_tracks->at(0)->get_pid(), DataStructure::Global::kPiPlus); EXPECT_EQ(emr_tracks->at(1)->get_pid(), DataStructure::Global::kPhoton); } delete spill; } TEST_F(GlobalToolsTest, GetSpillSpacePoints) { Spill* spill = new Spill; ReconEvent* recon_event = new ReconEvent; GlobalEvent* global_event = new GlobalEvent; DataStructure::Global::SpacePoint* tof1_sp1 = new DataStructure::Global::SpacePoint(); tof1_sp1->set_detector(DataStructure::Global::kTOF1); DataStructure::Global::SpacePoint* tof1_sp2 = new DataStructure::Global::SpacePoint(); tof1_sp2->set_detector(DataStructure::Global::kTOF1); DataStructure::Global::SpacePoint* tof2_sp = new DataStructure::Global::SpacePoint(); tof2_sp->set_detector(DataStructure::Global::kTOF2); DataStructure::Global::SpacePoint* kl_sp = new DataStructure::Global::SpacePoint(); kl_sp->set_detector(DataStructure::Global::kCalorimeter); global_event->add_space_point(tof1_sp1); global_event->add_space_point(tof1_sp2); global_event->add_space_point(tof2_sp); global_event->add_space_point(kl_sp); recon_event->SetGlobalEvent(global_event); std::vector* recon_events = new std::vector; recon_events->push_back(recon_event); spill->SetReconEvents(recon_events); auto tof0_sps = GlobalTools::GetSpillSpacePoints(spill, DataStructure::Global::kTOF0); EXPECT_FALSE(tof0_sps); auto tof1_sps = GlobalTools::GetSpillSpacePoints(spill, DataStructure::Global::kTOF1); EXPECT_EQ(tof1_sps->size(), 2); if (tof1_sps->size() > 1) { EXPECT_EQ(tof1_sps->at(0)->get_detector(), DataStructure::Global::kTOF1); EXPECT_EQ(tof1_sps->at(1)->get_detector(), DataStructure::Global::kTOF1); } auto tof2_sps = GlobalTools::GetSpillSpacePoints(spill, DataStructure::Global::kTOF2); EXPECT_EQ(tof2_sps->size(), 1); if (tof2_sps->size() > 0) { EXPECT_EQ(tof2_sps->at(0)->get_detector(), DataStructure::Global::kTOF2); } auto kl_sps = GlobalTools::GetSpillSpacePoints(spill, DataStructure::Global::kCalorimeter); EXPECT_EQ(kl_sps->size(), 1); if (kl_sps->size() > 0) { EXPECT_EQ(kl_sps->at(0)->get_detector(), DataStructure::Global::kCalorimeter); } delete spill; } TEST_F(GlobalToolsTest, GetTracksByMapperName) { GlobalEvent* global_event = new GlobalEvent; DataStructure::Global::Track* track1 = new DataStructure::Global::Track; track1->set_mapper_name("GetTracksByMapperNameTest"); DataStructure::Global::Track* track2 = new DataStructure::Global::Track; track2->set_mapper_name("GetTracksByMapperNameTest"); DataStructure::Global::Track* track3 = new DataStructure::Global::Track; track3->set_mapper_name("WrongMapperName"); global_event->add_track(track1); global_event->add_track(track2); global_event->add_track(track3); auto tracks = GlobalTools::GetTracksByMapperName(global_event, "GetTracksByMapperNameTest"); EXPECT_EQ(tracks->size(), 2); delete global_event; } TEST_F(GlobalToolsTest, GetTrackerPlane) { std::vector z_positions = GlobalTools::GetTrackerPlaneZPositions("Stage4.dat"); DataStructure::Global::SpacePoint* sp = new DataStructure::Global::SpacePoint(); TLorentzVector position(0, 0, 12106.2, 0); sp->set_position(position); const DataStructure::Global::TrackPoint* tp1 = new const DataStructure::Global::TrackPoint(sp); position.SetZ(16773.0); sp->set_position(position); const DataStructure::Global::TrackPoint* tp2 = new const DataStructure::Global::TrackPoint(sp); position.SetZ(19000.0); sp->set_position(position); const DataStructure::Global::TrackPoint* tp3 = new const DataStructure::Global::TrackPoint(sp); std::vector plane1 = GlobalTools::GetTrackerPlane(tp1, z_positions); std::vector plane2 = GlobalTools::GetTrackerPlane(tp2, z_positions); std::vector plane3 = GlobalTools::GetTrackerPlane(tp3, z_positions); delete sp; delete tp1; delete tp2; delete tp3; EXPECT_EQ(plane1[0], 0); EXPECT_EQ(plane1[1], 2); EXPECT_EQ(plane1[2], 1); EXPECT_EQ(plane2[0], 1); EXPECT_EQ(plane2[1], 4); EXPECT_EQ(plane2[2], 2); EXPECT_EQ(plane3[0], 99); EXPECT_EQ(plane3[1], 0); EXPECT_EQ(plane3[2], 0); } TEST_F(GlobalToolsTest, GetTrackerPlaneZPositions) { std::vector z_positions = GlobalTools::GetTrackerPlaneZPositions("Stage4.dat"); ASSERT_EQ(z_positions.size(), 30); double z_reference[] = {11205.7, 11206.3, 11207, 11555.6, 11556.3, 11556.9, 11855.6, 11856.3, 11856.9, 12105.5, 12106.1, 12106.8, 12305.5, 12306.1, 12306.8, 16021.6, 16022.3, 16022.9, 16221.6, 16222.3, 16222.9, 16471.6, 16472.3, 16472.9, 16771.6, 16772.3, 16772.9, 17121.6, 17122.3, 17122.9}; double epsilon = 0.1; for (size_t i = 0; i < z_positions.size(); i++) { EXPECT_NEAR(z_positions.at(i), z_reference[i], epsilon); } } TEST_F(GlobalToolsTest, approx) { EXPECT_PRED3(GlobalTools::approx, 1.1, 1.0, 0.15); EXPECT_PRED3(GlobalTools::approx, 10.05, 10.06, 0.02); // Predicate assertions always expect true EXPECT_FALSE(GlobalTools::approx(1.1, 1.0, 0.05)); } TEST_F(GlobalToolsTest, GetNearestZTrackPoint) { DataStructure::Global::SpacePoint sp; DataStructure::Global::TrackPoint tp(&sp); TLorentzVector position(0.0, 0.0, 0.0, 0.0); DataStructure::Global::TrackPoint* tp1 = tp.Clone(); position.SetZ(100.0); tp1->set_position(position); DataStructure::Global::TrackPoint* tp2 = tp.Clone(); position.SetZ(200.0); tp2->set_position(position); DataStructure::Global::TrackPoint* tp3 = tp.Clone(); position.SetZ(300.0); tp3->set_position(position); DataStructure::Global::TrackPoint* tp4 = tp.Clone(); position.SetZ(400.0); tp4->set_position(position); DataStructure::Global::Track track; track.AddTrackPoint(tp1); track.AddTrackPoint(tp2); track.AddTrackPoint(tp3); track.AddTrackPoint(tp4); const DataStructure::Global::Track* track_ptr = &track; auto neartp1 = GlobalTools::GetNearestZTrackPoint(track_ptr, 240.0); EXPECT_FLOAT_EQ(neartp1->get_position().Z(), 200.0); auto neartp2 = GlobalTools::GetNearestZTrackPoint(track_ptr, 0.0); EXPECT_FLOAT_EQ(neartp2->get_position().Z(), 100.0); auto neartp3 = GlobalTools::GetNearestZTrackPoint(track_ptr, 100000.0); EXPECT_FLOAT_EQ(neartp3->get_position().Z(), 400.0); } TEST_F(GlobalToolsTest, dEdx) { G4NistManager* manager = G4NistManager::Instance(); G4Material* galactic = manager->FindOrBuildMaterial("G4_Galactic"); G4Material* hydrogen = manager->FindOrBuildMaterial("G4_H"); G4Material* polystyrene = manager->FindOrBuildMaterial("G4_POLYSTYRENE"); G4Material* lead = manager->FindOrBuildMaterial("G4_Pb"); double mass = 105.65837; EXPECT_NEAR(GlobalTools::dEdx(galactic, 130.0, mass), -8.746e-26, 1.0e-28); EXPECT_NEAR(GlobalTools::dEdx(galactic, 230.0, mass), -4.354e-26, 1.0e-28); EXPECT_NEAR(GlobalTools::dEdx(hydrogen, 130.0, mass), -7.420e-05, 1.0e-7); EXPECT_NEAR(GlobalTools::dEdx(hydrogen, 230.0, mass), -3.687e-05, 1.0e-7); EXPECT_NEAR(GlobalTools::dEdx(polystyrene, 130.0, mass), -0.4432, 0.001); EXPECT_NEAR(GlobalTools::dEdx(polystyrene, 230.0, mass), -0.2232, 0.001); EXPECT_NEAR(GlobalTools::dEdx(lead, 130.0, mass), -2.484, 0.01); EXPECT_NEAR(GlobalTools::dEdx(lead, 230.0, mass), -1.336, 0.01); } TEST_F(GlobalToolsTest, propagate) { Simulation::DetectorConstruction* dc = Globals::GetInstance()->GetGeant4Manager()->GetGeometry(); std::string mod_path = std::string(getenv("MAUS_ROOT_DIR"))+ "/tests/cpp_unit/Recon/Global/TestGeometries/"; MiceModule geometry1(mod_path+"PropagationTest.dat"); MiceModule geometry2(mod_path+"PropagationTest_NoField.dat"); DataStructure::Global::PID pid = DataStructure::Global::kMuPlus; double x1[] = {0.0, 0.0, 0.0, 0.0, 184.699, 15.0, 15.0, 150.0}; double x2[] = {0.0, 0.0, 0.0, 0.0, 184.699, 15.0, 15.0, 150.0}; double x3[] = {0.0, 0.0, 0.0, 0.0, 184.699, 15.0, 15.0, 150.0}; double x4[] = {0.0, 0.0, 0.0, 0.0, 184.699, 15.0, 15.0, 150.0}; dc->SetMiceModules(geometry1); Json::Value config = (*Globals::GetInstance()->GetConfigurationCards()); config["reconstruction_geometry_filename"] = mod_path + "PropagationTest.dat"; config["simulation_geometry_filename"] = mod_path + "PropagationTest.dat"; if (Globals::HasInstance()) { GlobalsManager::DeleteGlobals(); } MAUS::GlobalsManager::InitialiseGlobals(JsonWrapper::JsonToString(config)); BTFieldConstructor* field = Globals::GetMCFieldConstructor(); double epsilon = 0.001; double field2[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; double xfield[4] = {x1[1], x1[2], 100, x1[0]}; field->GetFieldValue(xfield, field2); // Energy Loss, Magnetic Field try { GlobalTools::propagate(x1, 2000.0, field, 10.0, pid); } catch (Exceptions::Exception exc) { std::cerr << exc.what() << std::endl; } EXPECT_NEAR(x1[1], 8.345, epsilon); EXPECT_NEAR(x1[2], -21.653, epsilon); EXPECT_NEAR(x1[4], 133.855, epsilon); EXPECT_NEAR(x1[5], -11.217, epsilon); EXPECT_NEAR(x1[6], 2.571, epsilon); EXPECT_NEAR(x1[7], 81.370, epsilon); // No Energy Loss, Magnetic Field try { GlobalTools::propagate(x2, 2000.0, field, 10.0, pid, false); } catch (Exceptions::Exception exc) { std::cerr << exc.what() << std::endl; } EXPECT_NEAR(x2[1], -1.807, epsilon); EXPECT_NEAR(x2[2], -13.779, epsilon); EXPECT_NEAR(x2[4], 184.700, epsilon); EXPECT_NEAR(x2[5], -1.896, epsilon); EXPECT_NEAR(x2[6], 21.129, epsilon); EXPECT_NEAR(x2[7], 150.000, epsilon); dc->SetMiceModules(geometry2); field = Globals::GetMCFieldConstructor(); // Energy Loss, No Magnetic Field try { GlobalTools::propagate(x3, 2000.0, field, 10.0, pid); } catch (Exceptions::Exception exc) { std::cerr << exc.what() << std::endl; } EXPECT_NEAR(x3[1], 200.000, epsilon); EXPECT_NEAR(x3[2], 200.000, epsilon); EXPECT_NEAR(x3[4], 133.855, epsilon); EXPECT_NEAR(x3[5], 8.137, epsilon); EXPECT_NEAR(x3[6], 8.137, epsilon); EXPECT_NEAR(x3[7], 81.370, epsilon); // No Energy Loss, No Magnetic Field try { GlobalTools::propagate(x4, 2000.0, field, 10.0, pid, false); } catch (Exceptions::Exception exc) { std::cerr << exc.what() << std::endl; } EXPECT_NEAR(x4[1], 200.000, epsilon); EXPECT_NEAR(x4[2], 200.000, epsilon); EXPECT_NEAR(x4[4], 184.699, epsilon); EXPECT_NEAR(x4[5], 15.000, epsilon); EXPECT_NEAR(x4[6], 15.000, epsilon); EXPECT_NEAR(x4[7], 150.000, epsilon); } TEST_F(GlobalToolsTest, changeEnergy) { double mass = 100.0; double x[] = {0.0, 0.0, 0.0, 0.0, 0.0, 20.0, 10.0, 200.0}; x[4] = ::sqrt(x[5]*x[5] + x[6]*x[6] + x[7]*x[7] + mass*mass); double deltaE = -20; GlobalTools::changeEnergy(x, deltaE, mass); double epsilon = 0.001; EXPECT_NEAR(x[4], 204.722, epsilon); EXPECT_NEAR(x[5], 17.753, epsilon); EXPECT_NEAR(x[6], 8.877, epsilon); EXPECT_NEAR(x[7], 177.531, epsilon); } TEST_F(GlobalToolsTest, TrackPointSort) { DataStructure::Global::SpacePoint* sp = new DataStructure::Global::SpacePoint(); TLorentzVector position(0, 0, 10000.0, 0); sp->set_position(position); const DataStructure::Global::TrackPoint* tp1 = new const DataStructure::Global::TrackPoint(sp); position.SetZ(10001.1); sp->set_position(position); const DataStructure::Global::TrackPoint* tp2 = new const DataStructure::Global::TrackPoint(sp); EXPECT_TRUE(GlobalTools::TrackPointSort(tp1, tp2)); EXPECT_FALSE(GlobalTools::TrackPointSort(tp2, tp1)); EXPECT_FALSE(GlobalTools::TrackPointSort(tp1, tp1)); delete sp; delete tp1; delete tp2; } TEST_F(GlobalToolsTest, ProfileTest) { // this is used for profiling the tracking int number_of_events_to_profile = 0.; std::string geometry_file = "geometry_08681/ParentGeometryFile.dat"; if (number_of_events_to_profile < 1) { return; } Json::Value config = (*Globals::GetInstance()->GetConfigurationCards()); config["reconstruction_geometry_filename"] = geometry_file; config["simulation_geometry_filename"] = geometry_file; if (Globals::HasInstance()) { GlobalsManager::DeleteGlobals(); } MAUS::GlobalsManager::InitialiseGlobals(JsonWrapper::JsonToString(config)); double energy = ::sqrt(105.658*105.658+140.*140.); BTField* field = static_cast(MAUS::Globals::GetMCFieldConstructor()); for (double i = 0; i < number_of_events_to_profile + 0.5; ++i) { std::cerr << i << " "; double xin[8] = {0., i/10., 0., 12000., energy, 0., 0., 140.}; MAUS::GlobalTools::propagate(xin, 21000., field, 20., MAUS::DataStructure::Global::kMuPlus, true); } } } // ~namespace MAUS