//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//
//             LOW ENERGY MUON SPIN RELAXATION, ROTATION, RADIATION 
//
//  ID    : LEMuSRDetectorConstruction.hh , v 1.0
//  AUTHOR: Taofiq PARAISO
//  DATE  : 2004-06-24 16:24
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//
//
//  &           &&&&&&&&&&                            &&&&&&&         &&&&&&&&
//  &           &                                   &&      &&       &       &&
//  &           &                   &      &       &                &       &&
//  &           &&&&&&&            &      &         &&&&&&         &&&&&&&&  
//  &           &                 &      &&                &      &      &&
//  &           &                &&     &  &     &&      &&      &        &
//  &&&&&&&&&&  &&&&&&&&&&      &  &&&&&    &&    &&&&&&&       &        &&   
//                             &
//                            &
//                           &
//                         &  
//                           DETECTOR CONSTRUCTION.HH
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//

/*! In this class the detector geometry is defined according to the following hierarchy:
 * - Solid Volume
 *   -# The solid shape of the detector element. For example tube, sphere, box etc. 
 *   -# It can be defined as a boolean combination of solids.
 * - Logical Volume
 *   -# The solid volume plus a material, a color, and all other specific parameters.
 *   -# One can define different kind of attributes: visualization attributes, step size limitation, minimal kinetic enery to pursue the tracking of a particle etc. They are called UserAttributes or UserLimits. For more precision please refer to the G4UserLimits class.
 *   -# The sensitive detection is also set in the logical volume: the user should first define a sensitive detector, and then assign it to the logical volume (cf. source code of LEMuSRDetectorConstruction.cc)
 * - Physical Volume
 *   -# The logical volume and its position inside a mother logical volume.
 *   -# One can also define space transformations (rotation, translation etc.) to position the physical volume in the mother volume.
 *   -# Only the World volume does not need to be given a mother volume.
 * .
 * The main method is the virtual method Construct.
 * For clarity and compilation reasons the implementation code has been shared in the following files:
 * -# LEMuSRDetectorConstruction.cc
 * -# LEMuSRMaterials.cc where the materials table is built as well as the different attribute
 * -# LEMuSRdummydets.cc, which build the dummy detectors. This file should be removed in the future since we notice that the introduction of dummy detectors could influence the results.
*/
#ifndef LEMuSRDetectorConstruction_H
#define LEMuSRDetectorConstruction_H 1


#include "globals.hh"
#include "G4VUserDetectorConstruction.hh"


// G4 CLASSES FOR MATERIAL DEFINITION
#include "G4Material.hh"
#include "G4MaterialTable.hh"
#include "G4Element.hh"
#include "G4ElementTable.hh"
#include "G4Isotope.hh"
#include "G4UnitsTable.hh"
#include "G4Transform3D.hh"

// G4 ATTRIBUTES CLASSES
#include "G4UserLimits.hh"
#include "G4VisAttributes.hh"
#include "G4Colour.hh"

// G4 SENSITIVE DETECTOR
#include "G4SDManager.hh"
#include "LEMuSRScintSD.hh"
#include "LEMuSROScintSD.hh"
#include "LEMuSRMcpSD.hh"
#include "LEMuSRCryoSD.hh"

// G4 FIELD MANAGER
#include "G4UniformMagField.hh"
#include "G4UniformElectricField.hh"
#include "G4FieldManager.hh"
#include "LEMuSRRNDMAGField.hh"


class LEMuSRDetectorMessenger; // modif

class G4Box;
class G4Tubs;
class G4Cons;
class G4SubtractionSolid;
class G4UnionSolid;

class G4LogicalVolume;
class G4VPhysicalVolume;
class G4Material;


class LEMuSRDetectorConstruction : public G4VUserDetectorConstruction
{
    
public:
  // Constructeur et destructeur

  /*! The pointer to the detector instance.*/
  static LEMuSRDetectorConstruction* theDetector; // un pointeur a l'instance
  //! Return the detector pointer.
  /*! This method returns a pointer to the detector instance.*/
  static LEMuSRDetectorConstruction* GetInstance();
   
  /*! In the constructor, the detector messenger is instanciated and the pointer to the detector instance is given to the detector messenger.
   *
   * The materials table is also defined in the constructor by calling the   MaterialsDefinition method.
   *
   * Finally, the constructor contains the default initialization of the modifiable variables like the carbon foil thickness, the voltages, the layout of the detector (mcp, cryo, guards on/off etc.). Those parameters can be changed interactively during the simulation via the detector messenger (cf. LEMuSDetectorMessenger).
   *
*/
  //! Constructor.
  LEMuSRDetectorConstruction();
  //! Destructor.
  ~LEMuSRDetectorConstruction();

  

  // construction
  //! Main method.
  /*! The Construct method contains the implementation of the detector construction. It calls different methods which are in charge of building the different parts of the detector. For example
 * - lemuMCP2
 * - lemuCRYO
 * - lemuAnode
 * - lemuMCPdet
 * - lemuSCINT
 * - lemuLinse3
 * - lemuTrigger_Detector
 *.
 * Some other methods are called to create the different fields 
 * ( anode, electric/magnetic field at the sample etc.).
 *
 * As it is a virtual method, its name <I>must not</I> be changed.
 *
 * In the source code LEMuSRDetectorContruction.cc, one would notice that the Construct() method returns the result of the lemuDetector() method, where all the implementation is actually done.
*/
  G4VPhysicalVolume* Construct();

  //! Implementation of the detector construction procedure (cf. Construct).
  /*! In this method the Wold volume or Labo is defined as a 2x2x2 m³ room. Then the different contruction methods are called and the sensitive detection for the scintillators, the MCP2 and the sample plate are defined (cf. Construct).
*/  
  G4VPhysicalVolume* lemuDetector();
 

  // messenger  
  /*! The pointer to the detector messenger.*/
  LEMuSRDetectorMessenger* Messenger;

  

  //declaration of all the volumes


private:
 
  //=======LABORATORY::WORLD=================
  
  // solid
  G4Box* LABO_box;

  // logical
  G4LogicalVolume* lv_LABO;
 
  // physical
  G4VPhysicalVolume* pv_LABO;
  
  // materials
  G4Material* LABO_material;
 


  //======= MPC2 =================
  //! MCP2 chamber.
  /*! This method contructs the MCP2 chamber.*/
  void lemuMCP2();

  //solids 
  G4Tubs* MCPV_tube;
  G4Tubs* MCPS_tube;
  G4Tubs* F160_tube;
  G4Tubs* F100_tube;
  G4Tubs* F200_tube;
  G4Tubs* GATV_tube;
  G4Tubs* GATS_tube; 
  G4UnionSolid* MCPV_vtube;

 
  // logicals volumes
  G4LogicalVolume* lv_MCPV;
  G4LogicalVolume* lv_MCPS ;
  G4LogicalVolume* lv_F160 ;
  G4LogicalVolume* lv_F100 ;
  G4LogicalVolume* lv_F200 ;
  G4LogicalVolume* lv_GATV;
  G4LogicalVolume* lv_GATS ;

  // physical volumes
  G4VPhysicalVolume* pv_MCPV;
  G4VPhysicalVolume* pv_MCPS;
  G4VPhysicalVolume* pv_F160 ;
  G4VPhysicalVolume* pv_F100 ;
  G4VPhysicalVolume* pv_F200 ; 
  G4VPhysicalVolume* pv_GATV;
  G4VPhysicalVolume* pv_GATS ;

  /*! This method contructs the field of the ring anode.*/
  void buildAnodeField();


  // parameter
public:
  G4double mcpv_z;
  G4int Grid, Guards;



//===================  ANODE  =======================
private:
  //! Ring Anode
  /*! This method contructs the ring anode. The electric field is defined by a field map.*/
 void lemuANODE();

  // solids
  G4Cons* RA_E_cone;
  G4Cons* RA_M_cone;
  G4Box *RA_Ebox, *RA_Mbox;
  G4SubtractionSolid* RA_E, *RA_M;
  G4Tubs* RA_G_tube, *RAV_tube;

  // logical
  G4LogicalVolume* lv_RA_E ;
  G4LogicalVolume* lv_RA_M ;
  G4LogicalVolume* lv_RA_G ;
  G4LogicalVolume* lv_RAV  ;

  // physical
  G4VPhysicalVolume* pv_RA_E ;
  G4VPhysicalVolume* pv_RA_M ;
  G4VPhysicalVolume* pv_RA_G ;
  G4VPhysicalVolume* pv_RAV  ;





//================ MCP DETECTOR  =====================
private:
  //! MCP detector.
  /*! This method contructs the MCP detector. It is attached to a sensitive detector in the lemuDetector method.*/
 void lemuMCPdet();

  // solids
  G4Tubs* DMCP_tube;
  G4Tubs* MCPM_tube;
  G4Box* MCPA_box;
  G4Tubs* ANVA_tube;
  G4Box*  MCSR_box;
  G4Tubs* MCVR_tube;
  G4Tubs* MCSS_tube;

  // logical volumes
  G4LogicalVolume* lv_DMCP ;
  G4LogicalVolume* lv_MCPA ;
  G4LogicalVolume* lv_MCPM ;
  G4LogicalVolume* lv_ANVA ;
  G4LogicalVolume* lv_MCSR ;
  G4LogicalVolume* lv_MCVR ;
  G4LogicalVolume* lv_MCSS ;

  // physical volumes
  G4VPhysicalVolume* pv_DMCP ;
  G4VPhysicalVolume* pv_MCPA ;
  G4VPhysicalVolume* pv_MCPM ;  
  G4VPhysicalVolume* pv_MCPM2;  
  G4VPhysicalVolume* pv_ANVA ;
  G4VPhysicalVolume* pv_ANVA2;
  G4VPhysicalVolume* pv_MCSR ;
  G4VPhysicalVolume* pv_MCVR ;
  G4VPhysicalVolume* pv_MCSS ;

  // parameters
public:
  G4double B; // magnetic field default unit gauss

//================   CRYOSTAT   ======================
private:
  //! Cryostat.
  /*! This method contructs the sample cryostat. It is attached to a sensitive detector in the lemuDetector method.*/
  void lemuCRYO();

  // solids
  G4Tubs* SAH1_tube;
  G4Tubs* SAH2_tube;
  G4Tubs* SAH3_tube;
  G4Tubs* SAPH_tube;
  G4Tubs* COFI_tube;
  G4Tubs* CRY1_tube;
  G4Tubs* CRY2_tube;
  G4Tubs* CRY3_tube;
  G4Tubs* CRY4_tube;
  G4Tubs* CRSH_tube;
  G4Tubs* cryoField_tube;
  G4Tubs* CRSH2_tube;
  G4Tubs* Guard_Rings;

  // logical volumes
  G4LogicalVolume* lv_SAH1 ;
  G4LogicalVolume* lv_SAH2 ;
  G4LogicalVolume* lv_SAH3;
  G4LogicalVolume* lv_SAPH ;
  G4LogicalVolume* lv_COFI ;
  G4LogicalVolume* lv_CRY1 ;
  G4LogicalVolume* lv_CRY2 ;
  G4LogicalVolume* lv_CRY3 ;
  G4LogicalVolume* lv_CRY4 ;
  G4LogicalVolume* lv_CRSH ;
  G4LogicalVolume* lv_CRSH2 ;
  G4LogicalVolume* lv_Guards ;
  G4LogicalVolume* lv_cryoField ;


  // physical volumes
  G4VPhysicalVolume* pv_SAH1 ;
  G4VPhysicalVolume* pv_SAH2 ;
  G4VPhysicalVolume* pv_SAH3 ;
  G4VPhysicalVolume* pv_SAPH ;
  G4VPhysicalVolume* pv_COFI ;
  G4VPhysicalVolume* pv_CRY1 ;
  G4VPhysicalVolume* pv_CRY2 ;
  G4VPhysicalVolume* pv_CRY3 ;
  G4VPhysicalVolume* pv_CRY4 ; 
  G4VPhysicalVolume* pv_CRSH ;
  G4VPhysicalVolume* pv_CRSH2 ;
  G4VPhysicalVolume* pv_Guard1 ;
  G4VPhysicalVolume* pv_Guard2 ;
  G4VPhysicalVolume* pv_cryoField;

  // Cryo electric field manager
  G4FieldManager* cryoFieldMgr;
  G4ElectricField* cryoField;

  G4FieldManager* sampleFieldMgr;
  G4MagneticField*   sampleField;


  //! Electromagnetic fields in the gate valve chamber and the MCP2 chamber.
  /*! This method defines the field in the sample region.*/
  void buildCryoField();

  //! Get new field maps.
  /*! This method can be enabled via an environment variable in case new field maps are built*/
  void NEWMAPS();

public:
  // Parameters
  G4double cryoFieldLength,cryoVoltage;
  G4String  Material_SAH;


 //================ LINSE three  ======================
private:
  //! Third Lense.
  /*! This method contructs the third einzel lense. The electric field is defined by a field map.*/
  void lemuLinse3(); 

  // solids
  G4Tubs* L3VA_tube; 
  G4Tubs* L3ST_tube;
  G4Tubs* L3F_tube; // flange
  
  G4SubtractionSolid* L3GP_tube; 
  G4Tubs* L3GP1, *L3GP2, *L3GP3; // L3GV_tube is a boolean


  G4SubtractionSolid* L3HP_tube;

  G4Tubs* L3HP1, *L3HP2 , *L3HP3, *L3HP4, *L3HP5;
  
  // logical volumes
  G4LogicalVolume* lv_L3VA ;
  G4LogicalVolume* lv_L3ST ;
  G4LogicalVolume* lv_L3F;//flange
  
  // Ground potential
  G4LogicalVolume* lv_L3GP1, *lv_L3GP2 , *lv_L3GP3; 

  // High potential
  G4LogicalVolume* lv_L3HP, *lv_L3HP3, *lv_L3HP4, *lv_L3HP5 ;



  // physical volumes
  G4double L3z;
  G4VPhysicalVolume* pv_L3VA ;
  G4VPhysicalVolume* pv_L3ST ;
  G4VPhysicalVolume* pv_L3F1, *pv_L3F2 ;// flanges


  G4VPhysicalVolume* pv_L3GP1, *pv_L3GP2, *pv_L3GP3, *pv_L3GP4, *pv_L3GP5, *pv_L3GP6, *pv_L3GP7, *pv_L3GP8 ;

  G4VPhysicalVolume* pv_L3HP, *pv_L3HP3, *pv_L3HP4, *pv_L3HP5 , *pv_L3HP6, *pv_L3HP7, *pv_L3HP8;
  G4VPhysicalVolume* pv_L3GV2 ;

    

 //================ TRIGGER DETECTOR ====================
private:
  //! Trigger detector.
  /*! This method contructs the trigger detector:
   * - The carbon foil
   * - The electric fields
*/
  void lemuTrigger_Detector();

  // solids
  G4Tubs* Trigger_tube; 
  G4Tubs* TriggerV_tube;
  G4Tubs* TriggerF_tube; // flange

  G4Box* Trigger_box, *Trigger_box2, *Trigger_box3;  
 
 // magnetic field manager
  G4FieldManager* T1FieldMgr;
  G4UniformElectricField* T1Field;
 // magnetic field manager
  G4FieldManager* T2FieldMgr;
  G4UniformElectricField* T2Field;
 // magnetic field manager
  G4FieldManager* T3FieldMgr;
  G4UniformElectricField* T3Field;


  // logical
  G4LogicalVolume *lv_Trigger, *lv_TriggerF, *lv_TriggerV, *lv_TriggerB, *lv_TriggerB2, *lv_TriggerB3, *lv_CFOIL;
  // physica.l
  G4VPhysicalVolume *pv_Trigger, *pv_TriggerF1, *pv_TriggerF2,*pv_TriggerV, *pv_TriggerB, *pv_TriggerB2, *pv_TriggerB3, *pv_CFOIL;


 //================ COMPENSATION GATE ====================
private:
  //! Compensation gate.
  /*! This method contructs the compensation gate.*/
  void lemuCGate();

  // solids
  G4Tubs* CGate_tube; 
  G4Tubs* CGateV_tube;
  G4Tubs* CGateF_tube; // flange
  // logical
  G4LogicalVolume *lv_CGate, *lv_CGateF, *lv_CGateV;
  // physica.l
  G4VPhysicalVolume *pv_CGate, *pv_CGateF1, *pv_CGateF2,*pv_CGateV;


  //======= INNER/OUTER SCINTILLATOR  =================
private:  
  //! Scintillators.
  /*! This method contructs the inner and outer scintillators as four quarter of cynlinders around the MCP2 chamber. The sensitive detection is set in the lemuDetector() method.*/
  void lemuSCINT();
  
  
  //solids 
  G4Tubs* SCIS_tube;
  G4Tubs* SCOS_tube;
  
  // logicals volumes
  G4LogicalVolume* lv_SCIS;
  G4LogicalVolume* lv_SCOS ;
  
  // physical volumes
  G4VPhysicalVolume* pv_SCISl;
  G4VPhysicalVolume* pv_SCOSl;

  G4VPhysicalVolume* pv_SCISr;
  G4VPhysicalVolume* pv_SCOSr;
  
  G4VPhysicalVolume* pv_SCISb;
  G4VPhysicalVolume* pv_SCOSb;
  
  G4VPhysicalVolume* pv_SCISt;
  G4VPhysicalVolume* pv_SCOSt;
  G4Transform3D rotation1;  
  G4Transform3D rotation2;  
  G4Transform3D rotation3;  




 //================ ASYMMETRY TEST VOLUMES ================
private:
  //! Test of asymmetry
  void lemuAsym();

  // solids
  G4Tubs* Asym_tube; 
 // logical
  G4LogicalVolume *lv_Asym, *lv_AsymL, *lv_AsymR;
  // physica.l
  G4VPhysicalVolume *pv_Asym, *pv_Asym2,  *pv_AsymL,  *pv_AsymR;
  G4Transform3D Asym_rotation;  



 //========= ELECTRIC FIELD  TEST VOLUMES ================
private:
  //! Test of electric fields
  void lemuFieldCheck();
  // solids
  G4Tubs* fchk_tube;
  // logical
  G4LogicalVolume* lv_fchk, *lv_fchk2,*lv_fchk3;
  // physical
  G4VPhysicalVolume* pv_fchk,*pv_fchk2,*pv_fchk3,*pv_fchk4,*pv_fchk5,*pv_fchk6,*pv_fchk7,*pv_fchk8,*pv_fchk9,*pv_fchk1,*pv_fchk10,*pv_fchk11,*pv_fchk12,*pv_fchk13,*pv_fchk14,*pv_fchk15,*pv_fchk16,*pv_fchk17,*pv_fchk18,*pv_fchk19,*pv_fchk20,*pv_fchk21,*pv_fchk22,*pv_fchk23,*pv_fchk24,*pv_fchk25,*pv_fchk26,*pv_fchk27,*pv_fchk28,*pv_fchk29,*pv_fchk30,*pv_fchk31,*pv_fchk32,*pv_fchk33,*pv_fchk34,*pv_fchk35,*pv_fchk36,*pv_fchk37,*pv_fchk38,*pv_fchk39,*pv_fchk40,*pv_fchk41,*pv_fchk42,*pv_fchk43,*pv_fchk44,*pv_fchk45,*pv_fchk46,*pv_fchk47,*pv_fchk48,*pv_fchk49,*pv_fchk50,*pv_fchk51,*pv_fchk52,*pv_fchk53,*pv_fchk54,*pv_fchk55,*pv_fchk56,*pv_fchk57,*pv_fchk58,*pv_fchk59,*pv_fchk60,*pv_fchk61,*pv_fchk62,*pv_fchk63,*pv_fchk64,*pv_fchk65,*pv_fchk66,*pv_fchk67,*pv_fchk68,*pv_fchk69,*pv_fchk70,*pv_fchk71,*pv_fchk72;


  //====== SENSITIVE DETECTORS  ==========================
public:
  LEMuSRCryoSD *CryoSD;
  LEMuSRMcpSD *McpSD;
  LEMuSRScintSD *iScintSD;
  LEMuSROScintSD *oScintSD;
  G4int scint, mcp, cryo;


  //====== MATERIAL DECLARATION  =========================
private:
  //! Declaration of materials
  /*! This method contains the definition of all elements and materials and builds the materials table. It is important to call this method in the contructor because the materials table should be built only once. If this method was called in the Construct method, each modification of the detector would lead to an additional materials table. The consequence is a severe conflict causing a segmentation fault.*/
  void MaterialsDefinition();
  
  //materials
  G4Material* SC_material;
  G4Material* SAH_material;
  G4Material* SAPH_material;
  G4Material* Scint_material;
  G4Material* DMCP_material;
  G4Material* Vacuum       ;
  G4Material* SSteel       ;
  G4Material* Copper       ;
  G4Material* Macor       ;
  G4Material* Carbon       ;


  //====== ATTRIBUTES SETTING =========================
  void LoadAttributes();
  
  G4VisAttributes* Blue_style, *Red_style, *Purple_style, *Green_style, *Yellow_style, *dRed_style , *dYellow_style, *lBlue_style,*fBlue_style, *dBlue_style, *oxsteel;
  G4VisAttributes* VTBB_style,*MCP_style, *MACOR_style, *SCINT_style, *dSCINT_style;
  G4VisAttributes* White_style;


  G4UserLimits* VTBB_lim;


 //====== ARGUMENTS AND PARAMETERS======================

public:
  G4double  dSPhi;  // starting angle for  detector
  G4double  dEPhi;  // ending angle for detector

  G4double  sSPhi;  // starting angle for  detector
  G4double  sEPhi;  // ending angle for detector

  G4int magfield, elfield, anode_elfield, trigger_field;
  G4double  L3FieldVal,AnodeFieldVal,RALval,RARval, FieldStepLim, cfthk;
  G4FieldManager* L3FieldMgr, *GFieldMgr;
  G4double offset, mcdetector, halfview;
  G4double AsymCheck;
  G4double RA_Ez, RA_Mz, RA_Gz, GATVz;
  inline G4double GetParamMC(){return mcdetector;}

 //======= TEMPLATE Volume To Be Built =================

  void lemuVTBB();

  //solids 
  G4Tubs* VTBB_tube;

  // logicals volumes
 G4LogicalVolume* lv_VTBB;


  // physical volumes
  G4VPhysicalVolume* pv_VTBB;



  //materials
  G4Material* VTBB_material;





  // print STATUS
  void PrintStatus();
};

#endif

