-
Robert Shearman authoredRobert Shearman authored
Nana.cc 19.07 KiB
/*****************************************************************************
* Copyright (C) 2009-2014 this file is part of the NPTool Project *
* *
* For the licensing terms see $NPTOOL/Licence/NPTool_Licence *
* For the list of contributors see $NPTOOL/Licence/Contributors *
*****************************************************************************/
/*****************************************************************************
* Original Author: M. Labiche contact address: marc.labiche@stfc.ac.uk *
* *
* Creation Date : December 2009 *
* Last update : December 2014 *
*---------------------------------------------------------------------------*
* Decription: *
* This class describe the Nana scintillator array *
* *
*---------------------------------------------------------------------------*
* Comment: *
* *
*****************************************************************************/
// C++ headers
#include <sstream>
#include <cmath>
#include <limits>
using namespace std;
//Geant4
#include "G4VSolid.hh"
#include "G4Box.hh"
#include "G4Tubs.hh"
#include "G4UnionSolid.hh"
#include "G4SubtractionSolid.hh"
#include "G4SDManager.hh"
#include "G4Transform3D.hh"
#include "G4PVPlacement.hh"
#include "G4Colour.hh"
// NPS
#include "Nana.hh"
using namespace NANA;
#include "CalorimeterScorers.hh"
#include "MaterialManager.hh"
#include "NPSDetectorFactory.hh"
// NPL
#include "NPOptionManager.h"
#include "RootOutput.h"
// CLHEP header
#include "CLHEP/Random/RandGauss.h"
using namespace CLHEP;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// Nana Specific Method
Nana::Nana(){
m_Event = new TNanaData();
// Blue
m_LaBr3VisAtt = new G4VisAttributes(G4Colour(0.5, 0.5, .0));
// Dark Grey
m_PMTVisAtt = new G4VisAttributes(G4Colour(0.1, 0.3, 0.5));
// Grey wireframe
m_DetectorCasingVisAtt = new G4VisAttributes(G4Colour(0.125, 0.125, 0.125, 0.4));
m_LogicalDetector = 0;
m_LaBr3Scorer = 0 ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
Nana::~Nana(){
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Nana::AddDetector(G4ThreeVector Pos1, G4ThreeVector Pos2, G4ThreeVector Pos3, G4ThreeVector Pos4){
G4ThreeVector Pos=(Pos1+Pos2+Pos3+Pos4)/4.;
G4ThreeVector u = Pos1-Pos2;
G4ThreeVector v = Pos1-Pos4;
u = u.unit(); v = v.unit();
G4ThreeVector w = Pos.unit();
Pos = Pos + w*Length*0.5;
m_Pos.push_back(Pos);
m_Rot.push_back(new G4RotationMatrix(u,v,w));
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Nana::AddDetector(G4ThreeVector Pos, double beta_u, double beta_v, double beta_w){
double Theta = Pos.theta();
double Phi = Pos.phi();
// vector parallel to one axis of silicon plane
G4double ii = cos(Theta / rad) * cos(Phi / rad);
G4double jj = cos(Theta / rad) * sin(Phi / rad);
G4double kk = -sin(Theta / rad);
G4ThreeVector Y = G4ThreeVector(ii, jj, kk);
G4ThreeVector w = Pos.unit();
G4ThreeVector u = w.cross(Y);
G4ThreeVector v = w.cross(u);
v = v.unit();
u = u.unit();
G4RotationMatrix* r = new G4RotationMatrix(u,v,w);
r->rotate(beta_u,u);
r->rotate(beta_v,v);
r->rotate(beta_w,w);
m_Pos.push_back(Pos);
m_Rot.push_back(r);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// Virtual Method of NPS::VDetector class
// Read stream at Configfile to pick-up parameters of detector (Position,...)
// Called in DetecorConstruction::ReadDetextorConfiguration Method
void Nana::ReadConfiguration(string Path){
ifstream ConfigFile;
ConfigFile.open(Path.c_str());
string LineBuffer, DataBuffer;
// A,B,C,D are the four corner of the detector
G4double Ax , Bx , Cx , Dx , Ay , By , Cy , Dy , Az , Bz , Cz , Dz ;
G4ThreeVector A , B , C , D ;
G4double Theta = 0 , Phi = 0 , R = 0 , beta_u = 0 , beta_v = 0 , beta_w = 0 ;
bool ReadingStatus = false;
bool check_A = false;
bool check_C = false;
bool check_B = false;
bool check_D = false;
bool check_Theta = false;
bool check_Phi = false;
bool check_R = false;
while (!ConfigFile.eof()) {
getline(ConfigFile, LineBuffer);
if (LineBuffer.compare(0, 12, "NanaDetector") == 0) {
G4cout << "///" << G4endl ;
G4cout << "Detector found: " << G4endl ;
ReadingStatus = true ;
}
while (ReadingStatus) {
ConfigFile >> DataBuffer;
// Comment Line
if (DataBuffer.compare(0, 1, "%") == 0) {/*do nothing */;}
// Position method
else if (DataBuffer == "A=") {
check_A = true;
ConfigFile >> DataBuffer ;
Ax = atof(DataBuffer.c_str()) ;
Ax = Ax * mm ;
ConfigFile >> DataBuffer ;
Ay = atof(DataBuffer.c_str()) ;
Ay = Ay * mm ;
ConfigFile >> DataBuffer ;
Az = atof(DataBuffer.c_str()) ;
Az = Az * mm ;
A = G4ThreeVector(Ax, Ay, Az);
G4cout << "Corner A position : " << A << G4endl;
}
else if (DataBuffer == "B=") {
check_B = true;
ConfigFile >> DataBuffer ;
Bx = atof(DataBuffer.c_str()) ;
Bx = Bx * mm ;
ConfigFile >> DataBuffer ;
By = atof(DataBuffer.c_str()) ;
By = By * mm ;
ConfigFile >> DataBuffer ;
Bz = atof(DataBuffer.c_str()) ;
Bz = Bz * mm ;
B = G4ThreeVector(Bx, By, Bz);
G4cout << "Corner B position : " << B << G4endl;
}
else if (DataBuffer == "C=") {
check_C = true;
ConfigFile >> DataBuffer ;
Cx = atof(DataBuffer.c_str()) ;
Cx = Cx * mm ;
ConfigFile >> DataBuffer ;
Cy = atof(DataBuffer.c_str()) ;
Cy = Cy * mm ;
ConfigFile >> DataBuffer ;
Cz = atof(DataBuffer.c_str()) ;
Cz = Cz * mm ;
C = G4ThreeVector(Cx, Cy, Cz);
G4cout << "Corner C position : " << C << G4endl;
}
else if (DataBuffer == "D=") {
check_D = true;
ConfigFile >> DataBuffer ;
Dx = atof(DataBuffer.c_str()) ;
Dx = Dx * mm ;
ConfigFile >> DataBuffer ;
Dy = atof(DataBuffer.c_str()) ;
Dy = Dy * mm ;
ConfigFile >> DataBuffer ;
Dz = atof(DataBuffer.c_str()) ;
Dz = Dz * mm ;
D = G4ThreeVector(Dx, Dy, Dz);
G4cout << "Corner D position : " << D << G4endl;
}
// Angle method
else if (DataBuffer=="Theta=") {
check_Theta = true;
ConfigFile >> DataBuffer ;
Theta = atof(DataBuffer.c_str()) ;
Theta = Theta * deg;
G4cout << "Theta: " << Theta / deg << G4endl;
}
else if (DataBuffer=="Phi=") {
check_Phi = true;
ConfigFile >> DataBuffer ;
Phi = atof(DataBuffer.c_str()) ;
Phi = Phi * deg;
G4cout << "Phi: " << Phi / deg << G4endl;
}
else if (DataBuffer=="R=") {
check_R = true;
ConfigFile >> DataBuffer ;
R = atof(DataBuffer.c_str()) ;
R = R * mm;
G4cout << "R: " << R / mm << G4endl;
}
else if (DataBuffer=="Beta=") {
ConfigFile >> DataBuffer ;
beta_u = atof(DataBuffer.c_str()) ;
beta_u = beta_u * deg ;
ConfigFile >> DataBuffer ;
beta_v = atof(DataBuffer.c_str()) ;
beta_v = beta_v * deg ;
ConfigFile >> DataBuffer ;
beta_w = atof(DataBuffer.c_str()) ;
beta_w = beta_w * deg ;
G4cout << "Beta: " << beta_u / deg << " " << beta_v / deg << " " << beta_w / deg << G4endl ;
}
else G4cout << "WARNING: Wrong Token, Nana: Dector not added" << G4endl;
// Add The previously define telescope
// With position method
if ((check_A && check_B && check_C && check_D) &&
!(check_Theta && check_Phi && check_R)) {
ReadingStatus = false;
check_A = false;
check_C = false;
check_B = false;
check_D = false;
AddDetector(A, B, C, D);
}
// With angle method
if ((check_Theta && check_Phi && check_R ) &&
!(check_A && check_B && check_C && check_D)) {
ReadingStatus = false;
check_Theta = false;
check_Phi = false;
check_R = false;
R = R + 0.5*Length;
G4ThreeVector Pos(R*sin(Theta)*cos(Phi),R*sin(Theta)*sin(Phi),R*cos(Theta));
AddDetector(Pos, beta_u, beta_v, beta_w);
}
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// Construct detector and inialise sensitive part.
// Called After DetecorConstruction::AddDetector Method
void Nana::ConstructDetector(G4LogicalVolume* world){
unsigned int mysize = m_Pos.size();
for(unsigned int i = 0 ; i < mysize ; i++){
new G4PVPlacement(G4Transform3D(*m_Rot[i], m_Pos[i]), ConstructDetector(), "NanaDetector", world, false, i+1);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4LogicalVolume* Nana::ConstructDetector(){
if(!m_LogicalDetector){
G4Material* Vacuum = MaterialManager::getInstance()->GetMaterialFromLibrary("Vacuum");
G4Material* Alu = MaterialManager::getInstance()->GetMaterialFromLibrary("Al");
G4Material* Lead = MaterialManager::getInstance()->GetMaterialFromLibrary("Pb");
G4Material* LaBr3 = MaterialManager::getInstance()->GetMaterialFromLibrary("LaBr3");
// Mother Volume
G4Tubs* solidNanaDetector =
new G4Tubs("Nana",0, 0.5*FaceFront, 0.5*Length, 0.*deg, 360.*deg);
m_LogicalDetector =
new G4LogicalVolume(solidNanaDetector, Vacuum, "Nana", 0, 0, 0);
m_LogicalDetector->SetVisAttributes(G4VisAttributes::Invisible);
// Detector construction
// LaBr3
G4ThreeVector positionLaBr3 = G4ThreeVector(0, 0, LaBr3_PosZ);
G4Tubs* solidLaBr3 = new G4Tubs("solidLaBr3", 0., 0.5*LaBr3Face, 0.5*LaBr3Thickness, 0.*deg, 360.*deg);
G4LogicalVolume* logicLaBr3 = new G4LogicalVolume(solidLaBr3, LaBr3, "logicLaBr3", 0, 0, 0);
new G4PVPlacement(0,
positionLaBr3,
logicLaBr3,
"Nana_LaBr3",
m_LogicalDetector,
false,
0);
// Set LaBr3 sensible
logicLaBr3->SetSensitiveDetector(m_LaBr3Scorer);
// Visualisation of LaBr3 Strip
logicLaBr3->SetVisAttributes(m_LaBr3VisAtt);
// Aluminium can around LaBr3
// LaBr3 Can
G4ThreeVector positionLaBr3Can = G4ThreeVector(0, 0, LaBr3Can_PosZ);
G4Tubs* solidLaBr3Can = new G4Tubs("solidLaBr3Can", 0.5*CanInnerDiameter, 0.5*CanOuterDiameter, 0.5*CanLength, 0.*deg, 360.*deg);
G4LogicalVolume* logicLaBr3Can = new G4LogicalVolume(solidLaBr3Can, Alu, "logicLaBr3Can", 0, 0, 0);
new G4PVPlacement(0,
positionLaBr3Can,
logicLaBr3Can,
"Nana_LaBr3Can",
m_LogicalDetector,
false,
0);
// Visualisation of LaBr3Can
logicLaBr3Can->SetVisAttributes(m_DetectorCasingVisAtt);
// Aluminium window in front of LaBr3
// LaBr3 Window
G4ThreeVector positionLaBr3Win = G4ThreeVector(0, 0, LaBr3Win_PosZ);
G4Tubs* solidLaBr3Win = new G4Tubs("solidLaBr3Win", 0.5*WinInnerDiameter, 0.5*WinOuterDiameter, 0.5*WinLength, 0.*deg, 360.*deg);
G4LogicalVolume* logicLaBr3Win = new G4LogicalVolume(solidLaBr3Win, Alu, "logicLaBr3Win", 0, 0, 0);
new G4PVPlacement(0,
positionLaBr3Win,
logicLaBr3Win,
"Nana_LaBr3Win",
m_LogicalDetector,
false,
0);
// Visualisation of LaBr3Win
logicLaBr3Win->SetVisAttributes(m_DetectorCasingVisAtt);
// PMT
G4ThreeVector positionPMT = G4ThreeVector(0, 0, PMT_PosZ);
G4Tubs* solidPMout = new G4Tubs("solidPMOut", 0.5*LaBr3Face, 0.5*PMTFace, 0.5*PMTThickness, 0.*deg, 360.*deg);
G4Tubs* solidPMin = new G4Tubs("solidPMIn", 0.5*LaBr3Face-0.1*cm, 0.5*PMTFace-0.5*cm, 0.5*(PMTThickness-2.*cm)-0.1*cm, 0.*deg, 360.*deg);
G4RotationMatrix* RotMat=NULL;
const G4ThreeVector &Trans= G4ThreeVector(0.,0.,1.*cm);
G4SubtractionSolid* solidPMT = new G4SubtractionSolid("solidPMT", solidPMout,solidPMin, RotMat, Trans);
G4LogicalVolume* logicPMT = new G4LogicalVolume(solidPMT, Alu, "logicPMT", 0, 0, 0);
new G4PVPlacement(0,
positionPMT,
logicPMT,
"Nana_PMT",
m_LogicalDetector,
false,
0);
// Visualisation of PMT Strip
logicPMT->SetVisAttributes(m_PMTVisAtt);
/*
// Plastic Lead shielding
//plastic definition
// LaBr3
G4int ncomponents, natoms;
G4double z, density;
G4double percent = .5;
G4Element* C = new G4Element("Carbon","C" , z= 6., 12.0107*g/mole);
G4Element* H = new G4Element("Hydrogen","H" , z= 1.,1.00794*g/mole );
G4Element* O = new G4Element("Oxygen","O" , z= 8., 15.999*g/mole);
G4Element* W = new G4Element("Tungsten","W" , z= 74., 183.84*g/mole);
density = percent * 4.5*g/cm3;
G4Material* PCA = new G4Material("PCA", density, ncomponents=4);
PCA->AddElement(C, natoms=6);
PCA->AddElement(H, natoms=8);
PCA->AddElement(O, natoms=4);
PCA->AddElement(W, natoms=1);
// A
G4ThreeVector positionLeadAShield = G4ThreeVector(0, 0, LeadAShield_PosZ);
G4Tubs* solidLeadA = new G4Tubs("solidLead", 0.5*LeadAMinR, 0.5*LeadAMaxR, 0.5*LeadALength, 0.*deg, 360.*deg);
G4LogicalVolume* logicLeadAShield = new G4LogicalVolume(solidLeadA, PCA, "logicLeadAShield", 0, 0, 0);
new G4PVPlacement(0,
positionLeadAShield,
logicLeadAShield,
"Nana_LeadAShield",
m_LogicalDetector,
false,
0);
// B
G4ThreeVector positionLeadBShield = G4ThreeVector(0, 0, LeadBShield_PosZ);
G4Tubs* solidLeadB = new G4Tubs("solidLead", 0.5*LeadBMinR, 0.5*LeadBMaxR, 0.5*LeadBLength, 0.*deg, 360.*deg);
G4LogicalVolume* logicLeadBShield = new G4LogicalVolume(solidLeadB, PCA, "logicLeadBShield", 0, 0, 0);
new G4PVPlacement(0,
positionLeadBShield,
logicLeadBShield,
"Nana_LeadBShield",
m_LogicalDetector,
false,
0);
// Visualisation of PMT Strip
G4VisAttributes* LeadVisAtt = new G4VisAttributes(G4Colour(1., 1., 1.));
logicLeadAShield->SetVisAttributes(LeadVisAtt);
logicLeadBShield->SetVisAttributes(LeadVisAtt);
*/
// Lead shielding
// A
G4ThreeVector positionLeadAShield = G4ThreeVector(0, 0, LeadAShield_PosZ);
G4Tubs* solidLeadA = new G4Tubs("solidLead", 0.5*LeadAMinR, 0.5*LeadAMaxR, 0.5*LeadALength, 0.*deg, 360.*deg);
G4LogicalVolume* logicLeadAShield = new G4LogicalVolume(solidLeadA, Lead, "logicLeadAShield", 0, 0, 0);
new G4PVPlacement(0,
positionLeadAShield,
logicLeadAShield,
"Nana_LeadAShield",
m_LogicalDetector,
false,
0);
// B
G4ThreeVector positionLeadBShield = G4ThreeVector(0, 0, LeadBShield_PosZ);
G4Tubs* solidLeadB = new G4Tubs("solidLead", 0.5*LeadBMinR, 0.5*LeadBMaxR, 0.5*LeadBLength, 0.*deg, 360.*deg);
G4LogicalVolume* logicLeadBShield = new G4LogicalVolume(solidLeadB, Lead, "logicLeadBShield", 0, 0, 0);
new G4PVPlacement(0,
positionLeadBShield,
logicLeadBShield,
"Nana_LeadBShield",
m_LogicalDetector,
false,
0);
// Visualisation of PMT Strip
G4VisAttributes* LeadVisAtt = new G4VisAttributes(G4Colour(.66, .66, .66));
logicLeadAShield->SetVisAttributes(LeadVisAtt);
logicLeadBShield->SetVisAttributes(LeadVisAtt);
}
return m_LogicalDetector;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// Add Detector branch to the EventTree.
// Called After DetecorConstruction::AddDetector Method
void Nana::InitializeRootOutput(){
RootOutput *pAnalysis = RootOutput::getInstance();
TTree *pTree = pAnalysis->GetTree();
pTree->Branch("Nana", "TNanaData", &m_Event) ;
pTree->SetBranchAddress("Nana", &m_Event) ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
// Read sensitive part and fill the Root tree.
// Called at in the EventAction::EndOfEventAvtion
void Nana::ReadSensitive(const G4Event* event){
m_Event->Clear();
///////////
// LaBr3
G4THitsMap<G4double*>* LaBr3HitMap;
std::map<G4int, G4double**>::iterator LaBr3_itr;
G4int LaBr3CollectionID = G4SDManager::GetSDMpointer()->GetCollectionID("Nana_LaBr3Scorer/NanaLaBr3");
LaBr3HitMap = (G4THitsMap<G4double*>*)(event->GetHCofThisEvent()->GetHC(LaBr3CollectionID));
// Loop on the LaBr3 map
for (LaBr3_itr = LaBr3HitMap->GetMap()->begin() ; LaBr3_itr != LaBr3HitMap->GetMap()->end() ; LaBr3_itr++){
G4double* Info = *(LaBr3_itr->second);
//(Info[0]/2.35)*((Info[0]*1.02)*pow((Info[0]*1.8),.5))
// double Energy = RandGauss::shoot(Info[0],((Info[0]*1000*1.02/2.35)*pow((Info[0]*1000*1.8),.5)) );
double Energy = RandGauss::shoot(Info[0],(Info[0]*0.0325637)/(2.35*pow(Info[0]-0.00975335,0.475759)));
if(Energy>EnergyThreshold){
double Time = Info[1];
int DetectorNbr = (int) Info[2];
m_Event->SetNanaLaBr3(DetectorNbr,Energy,Energy,(unsigned short) Time,0,0);
}
}
// clear map for next event
LaBr3HitMap->clear();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void Nana::InitializeScorers(){
vector<G4int> NestingLevel;
NestingLevel.push_back(1);
// LaBr3 Associate Scorer
bool already_exist = false;
m_LaBr3Scorer = CheckScorer("Nana_LaBr3Scorer",already_exist);
// if the scorer were created previously nothing else need to be made
if(already_exist) return;
G4VPrimitiveScorer* LaBr3Scorer =
new CALORIMETERSCORERS::PS_Calorimeter("NanaLaBr3",NestingLevel);
//and register it to the multifunctionnal detector
m_LaBr3Scorer->RegisterPrimitive(LaBr3Scorer);
// Add All Scorer to the Global Scorer Manager
G4SDManager::GetSDMpointer()->AddNewDetector(m_LaBr3Scorer) ;
}
////////////////////////////////////////////////////////////////////////////////
// Construct Method to be pass to the DetectorFactory //
////////////////////////////////////////////////////////////////////////////////
NPS::VDetector* Nana::Construct(){
return (NPS::VDetector*) new Nana();
}
////////////////////////////////////////////////////////////////////////////////
// Registering the construct method to the factory //
////////////////////////////////////////////////////////////////////////////////
extern"C" {
class proxy_nps_nana{
public:
proxy_nps_nana(){
NPS::DetectorFactory::getInstance()->AddToken("Nana","Nana");
NPS::DetectorFactory::getInstance()->AddDetector("Nana",Nana::Construct);
}
};
proxy_nps_nana p_nps_nana;
}