/* 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 .
*
*/
#ifndef _SRC_COMMON_CPP_SIMULATION_DETECTORCONSTRUCTION_HH_
#define _SRC_COMMON_CPP_SIMULATION_DETECTORCONSTRUCTION_HH_
#include
#include
#ifdef TESTS_CPP_UNIT_SIMULATION_DETECTORCONSTRUCTORTEST_CC
#include "gtest/gtest_prod.h"
#endif
#include "json/json.h"
#include "Geant4/G4VUserDetectorConstruction.hh"
#include "Geant4/G4UniformMagField.hh"
#include "Geant4/G4RotationMatrix.hh"
#include "DetModel/MAUSSD.hh"
#include "src/legacy/Interface/MiceMaterials.hh"
#include "src/legacy/Config/MiceModule.hh"
#include "src/legacy/BeamTools/BTFieldConstructor.hh"
#include "src/legacy/EngModel/MiceMagneticField.hh"
#include "src/legacy/EngModel/MiceElectroMagneticField.hh"
class G4VPhysicalVolume;
class G4PVPlacement;
class G4LogicalVolume;
class G4MagIntegratorStepper;
class G4VSolid;
class G4ChordFinder;
class G4UserLimits;
class G4VisAttributes;
class G4EquationOfMotion;
class SciFiPlane;
class KLFiber;
class KLGlue;
class CkovMirror;
class MICEEvent;
class TofSD;
namespace MAUS {
class MCEvent;
namespace Simulation {
/** DetectorConstruction handles parsing the MiceModules into Geant4
*
* DetectorConstruction is responsible for reading the MiceModules and
* interpreting the corresponding commands for Geant4 to use
*/
class DetectorConstruction : public G4VUserDetectorConstruction {
public:
/** Constructor - initialises some variables and accepts a pre-generated volume
*
* @param worldvol - description of the geometry. DetectorConstruction makes a
* deepcopy of model (caller owns memory)
* @param cards (borrowed reference) - the control variables. Caller still
* owns memory allocated to cards
*/
explicit DetectorConstruction(G4VPhysicalVolume* worldvol, const Json::Value& cards);
/** Constructor - initialises some variables but does not construct
*
* @param model - description of the geometry. DetectorConstruction makes a
* deepcopy of model (caller owns memory)
* @param cards (borrowed reference) - the control variables. Caller still
* owns memory allocated to cards
*/
explicit DetectorConstruction(const Json::Value& cards);
/** Destructor */
~DetectorConstruction();
/** Construct a dummy default geometry
*
* Overrides G4VUserDetectorConstruction and is called by Geant4 when it is
* time to reconstruct the geometry. This just generates a dummy geometry -
* the real work is done in ResetGeometry() and ResetFields() which needs to
* be called by user
*/
G4VPhysicalVolume* Construct();
/** Get sensitive detector hits from a particular sensitive detector
*
* @param int i; indexes the detector for which hits are requested
*
* Returns the sensitive detector hits or an empty object i.e. {} if the
* detector was not hit.
*/
void GetSDHits(size_t i, MCEvent* event);
/** Clear all sensitive detector hits
*/
void ClearSDHits();
/** Get the size of the SD array (should be number of sensitive detectors)
*/
int GetSDSize() { return _SDs.size(); }
/** Get the last element of the SD array added. For the purpose of adding daughters
* to sensitive detectors
*/
// std::vector GetSDList(){ return _SDs; }
/** Get the field maps
*
* Access the field maps that are seen by Geant4.
*/
BTFieldConstructor* GetField() {return _btField;}
/** Set control variables from datacards
*
* @param cards the json datacards; we use the following cards
* "check_volume_overlaps", "stepping_algorithm", "delta_one_step",
* "delta_intersection", "epsilon_min", "epsilon_max", "miss_distance"
*/
void SetDatacardVariables(const Json::Value& cards);
/** Set the mice modules
*
* Updates Geant4 geometry and MC field maps according to the new geoemtry
*
* Caller owns memory referenced by mods (makes a deep copy)
*/
void SetMiceModules(const MiceModule& mods);
/** Get the MAUS internal list of regions
*
* MAUS needs to keep this internal list so that MAUS defaults can be
* applied to regions that are not listed in the datacards. It would be nice
* if G4RegionStore let me access it's list of regions but not possible...
*/
std::vector GetRegions() {return _regions;}
std::vector GetUserLimits() {return _userLims;}
std::vector GetVisAttributes() {return _visAtts;}
void BuildSensitiveDetector(G4LogicalVolume* logic, MiceModule* module);
void SetUserLimits(G4LogicalVolume* logic, MiceModule* module);
void SetVisAttributes(G4LogicalVolume* logic, MiceModule* mod);
// Add to a G4Region if required
void AddToRegion(G4LogicalVolume* logic, MiceModule* mod);
/** Get the world volume pointer.
*
* Allows access to the geometry outside of Geant4.
*/
G4VPhysicalVolume* GetWorldVolume() const {return _rootPhysicalVolume;}
private:
void ResetGeometry();
void ResetFields();
std::vector _SDs; // G4 owns the memory - this is borrowed
void BuildG4DetectorVolume(G4PVPlacement** place,
G4LogicalVolume** logic,
G4VPhysicalVolume* moth,
MiceModule* mod);
void BuildNormalVolume(G4PVPlacement** place,
G4LogicalVolume** logic,
G4VPhysicalVolume* moth,
MiceModule* mod);
void SetMagneticField(G4LogicalVolume* logic, MiceModule* module);
void SetBTMagneticField();
void AddDaughter(MiceModule*, G4VPhysicalVolume*);
void GeometryCleanup();
// Set G4 Stepping Accuracy parameters
void SetSteppingAccuracy();
// Set G4 Stepping Algorithm
void SetSteppingAlgorithm();
// Throw an exception if Volume of all children != None
void CheckForVolumeInChildren(MiceModule* mod, MiceModule* recurse = NULL);
// Throw an exception if module is more than _maxModDepth deep
void CheckModuleDepth(MiceModule* moduel);
// Build a Q35 using Q35.hh methods
G4LogicalVolume* BuildQ35(MiceModule * mod);
MICEEvent* _event;
MiceModule* _model;
MiceMaterials* _materials;
BTFieldConstructor* _btField;
MiceMagneticField* _miceMagneticField;
MiceElectroMagneticField* _miceElectroMagneticField;
// Geant4 sloppy memory usage - I keep pointers to G4 stuff so I can
// delete it when required; valgrind should not report any leakage...
G4LogicalVolume* _rootLogicalVolume;
G4VPhysicalVolume* _rootPhysicalVolume;
G4MagIntegratorStepper* _stepper;
G4ChordFinder* _chordFinder;
std::vector _rotations;
std::vector _visAtts;
std::vector _userLims;
std::vector _sciFiPlanes;
std::vector _klGlues;
std::vector _klFibers;
std::vector _ckovMirrors;
G4VisAttributes* _rootVisAtts;
G4EquationOfMotion* _equation;
size_t _maxModDepth;
std::string _stepperType;
std::string _physicsProcesses;
bool _checkVolumes;
bool _everythingSpecialVirtual;
bool _polarisedTracking;
bool _useGDML;
G4double _deltaOneStep;
G4double _deltaIntersection;
G4double _epsilonMin;
G4double _epsilonMax;
G4double _missDistance;
G4double _keThreshold;
G4double _trackMax;
G4double _timeMax;
G4double _stepMax;
std::vector _regions;
#ifdef TESTS_CPP_UNIT_SIMULATION_DETECTORCONSTRUCTORTEST_CC
FRIEND_TEST(DetectorConstructionTest, SetDatacardVariablesTest);
FRIEND_TEST(DetectorConstructionTest, SetSteppingAlgorithmTest);
FRIEND_TEST(DetectorConstructionTest, SetSteppingAccuracyTest);
#endif
};
} // Simulation
} // MAUS
#endif // _SRC_COMMON_CPP_SIMULATION_DETECTORCONSTRUCTION_HH_