From 3b02d62b32ed7dd636cfd92ff993c66ab29b4129 Mon Sep 17 00:00:00 2001 From: Clenain <cyril.lenain1@gmail.com> Date: Thu, 7 Feb 2019 13:49:08 +0100 Subject: [PATCH] adding drift electrons and pads in MINOS + CylinderTPCScorer --- NPLib/Detectors/Minos/TMinosData.cxx | 9 +- NPLib/Detectors/Minos/TMinosData.h | 31 +++- NPSimulation/Detectors/Minos/Minos.cc | 156 ++++++++++++++++++--- NPSimulation/Detectors/Minos/Minos.hh | 87 +++++++++++- NPSimulation/Scorers/CMakeLists.txt | 2 +- NPSimulation/Scorers/CylinderTPCScorers.cc | 146 +++++++++++++++++++ NPSimulation/Scorers/CylinderTPCScorers.hh | 130 +++++++++++++++++ 7 files changed, 537 insertions(+), 24 deletions(-) create mode 100644 NPSimulation/Scorers/CylinderTPCScorers.cc create mode 100644 NPSimulation/Scorers/CylinderTPCScorers.hh diff --git a/NPLib/Detectors/Minos/TMinosData.cxx b/NPLib/Detectors/Minos/TMinosData.cxx index d59dc0eaf..1659d2e20 100644 --- a/NPLib/Detectors/Minos/TMinosData.cxx +++ b/NPLib/Detectors/Minos/TMinosData.cxx @@ -50,7 +50,14 @@ void TMinosData::Clear() { // Time fMinos_T_DetectorNbr.clear(); fMinos_Time.clear(); - + // Charge + fMinos_Charge_Pad.clear(); + fMinos_Charge_X.clear(); + fMinos_Charge_Y.clear(); + fMinos_Charge.clear(); + // DriftTime + fMinos_Drift_Pad.clear(); + fMinos_DriftTime.clear(); //From Santamaria: diff --git a/NPLib/Detectors/Minos/TMinosData.h b/NPLib/Detectors/Minos/TMinosData.h index b6773407b..85757dcf6 100644 --- a/NPLib/Detectors/Minos/TMinosData.h +++ b/NPLib/Detectors/Minos/TMinosData.h @@ -42,6 +42,16 @@ class TMinosData : public TObject { vector<UShort_t> fMinos_T_DetectorNbr; vector<Double_t> fMinos_Time; + // Charge + vector<UShort_t> fMinos_Charge_Pad; + vector<Double_t> fMinos_Charge_X; + vector<Double_t> fMinos_Charge_Y; + vector<Double_t> fMinos_Charge; + + // DriftTime + vector<UShort_t> fMinos_Drift_Pad; + vector<Double_t> fMinos_DriftTime; + // maybe directions with angle varagles have to be added? //From Santamaria: @@ -109,7 +119,23 @@ int event; fMinos_Time.push_back(Time); fMinos_T_DetectorNbr.push_back(DetNbr); };//! - // + + // Charge + inline void SetCharge(const UShort_t& Pad,const Double_t& Charge, const Double_t& X,const Double_t& Y ){ + fMinos_Charge_Pad.push_back(Pad); + fMinos_Charge_X.push_back(X); + fMinos_Charge_Y.push_back(Y); + fMinos_Charge.push_back(Charge); + };//! + + // DriftTime + inline void SetDriftTime(const UShort_t& Pad,const Double_t& DriftTime){ + fMinos_Drift_Pad.push_back(Pad); + fMinos_DriftTime.push_back(DriftTime); + };//! + + +// @@ -170,6 +196,9 @@ int event; inline Double_t GetD_min() const {return MINOS_D_min[0] ; }//! + // Charge + + ////////////////////////////////////////////////////////////// // Required for ROOT dictionnary ClassDef(TMinosData,1) // MinosData structure diff --git a/NPSimulation/Detectors/Minos/Minos.cc b/NPSimulation/Detectors/Minos/Minos.cc index 66675805e..d46687afe 100644 --- a/NPSimulation/Detectors/Minos/Minos.cc +++ b/NPSimulation/Detectors/Minos/Minos.cc @@ -32,23 +32,40 @@ #include "G4MultiFunctionalDetector.hh" //G4 various object -#include "G4Material.hh" +#include "G4Material.hh" #include "G4Transform3D.hh" #include "G4PVPlacement.hh" #include "G4VisAttributes.hh" #include "G4Colour.hh" +#include "G4PVReplica.hh" +#include "G4PVParameterised.hh" +#include "G4VPVParameterisation.hh" + +// G4 Field +#include "G4FieldManager.hh" +#include "G4ElectricField.hh" +#include "G4UniformElectricField.hh" +#include "G4TransportationManager.hh" +#include "G4EqMagElectricField.hh" +#include "G4MagIntegratorStepper.hh" +#include "G4ClassicalRK4.hh" +#include "G4MagIntegratorDriver.hh" +#include "G4ChordFinder.hh" +#include "G4MaterialPropertiesTable.hh" // NPTool header #include "Minos.hh" #include "CalorimeterScorers.hh" #include "InteractionScorers.hh" #include "TPCScorers.hh" +#include "CylinderTPCScorers.hh" #include "RootOutput.h" #include "MaterialManager.hh" #include "NPSDetectorFactory.hh" #include "NPOptionManager.h" #include "NPSHitsMap.hh" + // CLHEP header #include "CLHEP/Random/RandGauss.h" @@ -76,6 +93,7 @@ Minos::Minos(){ m_Event = new TMinosData() ; m_MinosTargetScorer = 0; m_MinosTPCScorer = 0; + m_MinosPadScorer = 0; m_SquareDetector = 0; m_CylindricalDetector = 0; m_ReactionRegion=NULL; @@ -101,7 +119,6 @@ Minos::Minos(){ logicOuterRohacell=0; solidKapton=0; logicKapton=0; - } Minos::~Minos(){ @@ -123,6 +140,7 @@ void Minos::AddDetector(double R, double Theta, double Phi, double TargetLeng m_TargetLength.push_back(TargetLength); } + //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... // G4LogicalVolume* Minos::BuildSquareDetector(){ // if(!m_SquareDetector){ @@ -191,6 +209,17 @@ void Minos::DefineMaterials() // overwrite computed meanExcitationEnergy with ICRU recommended value mix->GetIonisation()->SetMeanExcitationEnergy(25.0*eV); + ///////// Drift properties + + G4MaterialPropertiesTable* MPT = new G4MaterialPropertiesTable(); + MPT->AddConstProperty("DE_PAIRENERGY",30*eV); + MPT->AddConstProperty("DE_ABSLENGTH",10*pc); + MPT->AddConstProperty("DE_DRIFTSPEED",11*cm/microsecond); + MPT->AddConstProperty("DE_TRANSVERSALSPREAD",50e-5*mm2/ns); + MPT->AddConstProperty("DE_LONGITUDINALSPREAD",50e-5*mm2/ns); + mix->SetMaterialPropertiesTable(MPT); + + G4Material* Ar_CF4_95_5 = new G4Material("Ar_CF4_95_5", density= 0.0017611*g/cm3, ncomponents=2); Ar_CF4_95_5->AddMaterial(CF4, fractionmass=5.*perCent); @@ -336,9 +365,6 @@ G4LogicalVolume* Minos::BuildCylindricalDetector(){ return m_CylindricalDetector; } - - - //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... // Below are vis attributes that permits someone to test / play @@ -512,13 +538,15 @@ G4LogicalVolume* Minos::BuildTPC(){ "TPC"); //name - {G4VisAttributes* atb= new G4VisAttributes(G4Colour(1.,1.,0.6)); + {G4VisAttributes* atb= new G4VisAttributes(G4Colour(1.,1.,0.6,0.7)); logicTPC->SetVisAttributes(atb);} logicTPC->SetSensitiveDetector(m_MinosTPCScorer); } return logicTPC; } + + //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... // // windows @@ -577,6 +605,7 @@ G4LogicalVolume* Minos::BuildWindow2(){ } return logicWindow2; } + //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... // Virtual Method of NPS::VDetector class @@ -597,7 +626,7 @@ void Minos::ReadConfiguration(NPL::InputParser parser){ cout << endl << "//// Minos " << i+1 << endl; G4ThreeVector Pos = NPS::ConvertVector(blocks[i]->GetTVector3("POS","mm")); - double TargetLength = blocks[i]->GetDouble("TargetLength","mm"); + TargetLength = blocks[i]->GetDouble("TargetLength","mm"); AddDetector(Pos,TargetLength); } else if(blocks[i]->HasTokenList(sphe)){ @@ -606,7 +635,7 @@ void Minos::ReadConfiguration(NPL::InputParser parser){ double R = blocks[i]->GetDouble("R","mm"); double Theta = blocks[i]->GetDouble("Theta","deg"); double Phi = blocks[i]->GetDouble("Phi","deg"); - double TargetLength = blocks[i]->GetDouble("TargetLength","mm"); + TargetLength = blocks[i]->GetDouble("TargetLength","mm"); AddDetector(R,Theta,Phi,TargetLength); } else{ @@ -618,7 +647,6 @@ void Minos::ReadConfiguration(NPL::InputParser parser){ //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... - // Construct detector and inialise sensitive part. // Called After DetecorConstruction::AddDetector Method void Minos::ConstructDetector(G4LogicalVolume* world){ @@ -634,6 +662,8 @@ void Minos::ConstructDetector(G4LogicalVolume* world){ WindowThickness = 0.150/2.*mm; + AnodeThickness = 10*mm; + DefineMaterials(); SetTargetMaterial("LH2"); @@ -661,7 +691,7 @@ void Minos::ConstructDetector(G4LogicalVolume* world){ v = v.unit(); u = u.unit(); - G4RotationMatrix* Rot = new G4RotationMatrix(u,v,w); + /* G4RotationMatrix* Rot = new G4RotationMatrix(u,v,w); */ // if(m_Shape[i] == "Cylindrical"){ // // new G4PVPlacement(G4Transform3D(*Rot,Det_pos), @@ -681,11 +711,79 @@ void Minos::ConstructDetector(G4LogicalVolume* world){ false, //no boolean operation 0); //copy number + +//////// ELECTRIC FIELD + + G4ElectricField* field = new G4UniformElectricField(G4ThreeVector(0.0,0.0,200*volt/cm)); + // Create an equation of motion for this field + G4EqMagElectricField* Equation = new G4EqMagElectricField(field); + G4MagIntegratorStepper* Stepper = new G4ClassicalRK4( Equation, 8 ); + + // Get the global field manager + G4FieldManager* FieldManager= new G4FieldManager(); + // Set this field to the global field manager + FieldManager->SetDetectorField(field ); + BuildTPC()->SetFieldManager(FieldManager,true); + + G4MagInt_Driver* IntgrDriver = new G4MagInt_Driver(0.1*mm, + Stepper, + Stepper->GetNumberOfVariables() ); + + G4ChordFinder* ChordFinder = new G4ChordFinder(IntgrDriver); + FieldManager->SetChordFinder( ChordFinder ); + + +///////// CONSTRUCT ANODE w/ PADS + + G4double InnerRadius = 45*mm; + G4double OuterRadius = 88.46*mm; + // Volume where Pads are placed + G4Tubs* solidAnode = new G4Tubs("Anode", + InnerRadius, OuterRadius, 1.2*mm,0,360*deg); + G4LogicalVolume* logicAnode = new G4LogicalVolume(solidAnode, + TPCMaterial, + "Anode"); + new G4PVPlacement(0, + G4ThreeVector(0,0,-ChamberLength+2*mm), + logicAnode, //its logical volume + "Anode", //its name + logicTPC, //its mother volume + false, //no boolean operation + 0); //copy number + {G4VisAttributes* atb= new G4VisAttributes(G4Colour(1., 1., 0.,0.1)); + logicAnode->SetVisAttributes(atb);} + + G4Material* Cu + = MaterialManager::getInstance()->GetMaterialFromLibrary("Cu"); + + G4Box* solidPad = new G4Box("Pad", 1.05*mm,1.05*mm,1.05*mm); + G4LogicalVolume* logicPad = new G4LogicalVolume(solidPad, Cu,"Pad"); + + {G4VisAttributes* atb= new G4VisAttributes(G4Colour(0.8, 0.4, 0.,0.8)); + logicPad->SetVisAttributes(atb);} + logicPad->SetSensitiveDetector(m_MinosPadScorer); + + G4int NbOfPads = 3604; + + G4VPVParameterisation* PadParam = + new PadParameterisation( + ); + + new G4PVParameterised("Pad", // their name + logicPad, // their logical volume + logicAnode, // Mother logical volume + kZAxis, // Are placed along this axis + NbOfPads, // Number of Pads + PadParam, // The parametrisation + false); // checking overlaps + +////////////////////////////////////// + new G4PVPlacement(0, //its name - G4ThreeVector(0,0,0/*ChamberLength*/), //at (0,0,0) + G4ThreeVector(0,0,0), //at (0,0,0) BuildOuterRohacell(), //its logical volume - "Rohacell"/*"OuterRohacell"*/, //its name - logicTPC/*world*/, //its mother volume + "Rohacell", //its name + logicTPC, //its mother volume false, //no boolean operation 0); //copy number @@ -771,7 +869,6 @@ void Minos::ConstructDetector(G4LogicalVolume* world){ //G4ProductionCuts* pcut = new G4ProductionCuts(); if(!m_ReactionRegion){ - // ecut->SetProductionCut(1000,"e-"); // pcut->SetProductionCut(1,"p"); @@ -812,6 +909,7 @@ void Minos::ConstructDetector(G4LogicalVolume* world){ world->SetVisAttributes (G4VisAttributes::Invisible); } + //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... // Add Detector branch to the EventTree. // Called After DetecorConstruction::AddDetector Method @@ -834,7 +932,6 @@ void Minos::ReadSensitive(const G4Event* ){ // Calorimeter scorer CalorimeterScorers::PS_Calorimeter* Scorer= (CalorimeterScorers::PS_Calorimeter*) m_MinosTargetScorer->GetPrimitive(0); - unsigned int size = Scorer->GetMult(); for(unsigned int i = 0 ; i < size ; i++){ vector<unsigned int> level = Scorer->GetLevel(i); @@ -846,6 +943,21 @@ void Minos::ReadSensitive(const G4Event* ){ m_Event->SetTime(DetectorNbr,Time); } } + + /////////// + // DriftElectron scorer + CylinderTPCScorers::PS_TPCAnode* Scorer2= (CylinderTPCScorers::PS_TPCAnode*) m_MinosPadScorer->GetPrimitive(0); + + unsigned int size2 = Scorer2->GetMult(); + for(unsigned int i = 0 ; i < size2 ; i++){ + int Pad = Scorer2->GetPad(i); + double Charge = Scorer2->GetCharge(i); + double X = Scorer2->GetX(i); + double Y = Scorer2->GetY(i); + double DriftTime = RandGauss::shoot(Scorer2->GetDriftTime(i),Minos_NS::ResoTime); + m_Event->SetCharge(Pad,Charge,X,Y); + m_Event->SetDriftTime(Pad,DriftTime); + } } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... @@ -854,34 +966,42 @@ void Minos::InitializeScorers() { // This check is necessary in case the geometry is reloaded bool already_exist = false; bool already_exist2 = false; - + bool already_exist3 = false; m_MinosTargetScorer = CheckScorer("MinosTargetScorer",already_exist) ; m_MinosTPCScorer = CheckScorer("MinosTPCScorer",already_exist2) ; + m_MinosPadScorer = CheckScorer("MinosPadScorer",already_exist3) ; - if(already_exist && already_exist2 ) + if(already_exist && already_exist2 && already_exist3 ) return ; // Otherwise the scorer is initialised vector<int> level; level.push_back(0); G4VPrimitiveScorer* CalorimeterMinosTargetScorer= new CalorimeterScorers::PS_Calorimeter("CalorimeterMinosTargetScore",level, 0) ; G4VPrimitiveScorer* InteractionMinosTargetScorer= new InteractionScorers::PS_Interactions("InteractionMinosTargetScore",ms_InterCoord, 0) ; + G4VPrimitiveScorer* DriftElectronMinosTPCScorer= new CylinderTPCScorers::PS_TPCAnode("DriftElectronsScore",level, 0) ; + //and register it to the multifunctionnal detector m_MinosTargetScorer->RegisterPrimitive(CalorimeterMinosTargetScorer); m_MinosTargetScorer->RegisterPrimitive(InteractionMinosTargetScorer); + m_MinosPadScorer->RegisterPrimitive(DriftElectronMinosTPCScorer); G4VPrimitiveScorer* TPCScorer= new TPCScorers::PS_TPCCathode("MinosTPC", 0); - //G4VPrimitiveScorer* TPCCalScorer= new CalorimeterScorers::PS_Calorimeter("TPCCalScorer",level, 0); + G4VPrimitiveScorer* TPCInterScorer= new InteractionScorers::PS_Interactions("TPCInterScorer",ms_InterCoord, 0); + G4VPrimitiveScorer* PadScorer= new CylinderTPCScorers::PS_TPCAnode("MinosTPCAnode",level, 0); + m_MinosTPCScorer->RegisterPrimitive(TPCScorer); // m_MinosTPCScorer->RegisterPrimitive(TPCCalScorer); m_MinosTPCScorer->RegisterPrimitive(TPCInterScorer); + m_MinosPadScorer->RegisterPrimitive(PadScorer); G4SDManager::GetSDMpointer()->AddNewDetector(m_MinosTPCScorer) ; G4SDManager::GetSDMpointer()->AddNewDetector(m_MinosTargetScorer) ; + G4SDManager::GetSDMpointer()->AddNewDetector(m_MinosPadScorer) ; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... diff --git a/NPSimulation/Detectors/Minos/Minos.hh b/NPSimulation/Detectors/Minos/Minos.hh index ed9652b69..eb01a0ec7 100644 --- a/NPSimulation/Detectors/Minos/Minos.hh +++ b/NPSimulation/Detectors/Minos/Minos.hh @@ -90,8 +90,8 @@ class Minos : public NPS::VDetector{ G4LogicalVolume* BuildWindow0(); G4LogicalVolume* BuildWindow1(); G4LogicalVolume* BuildWindow2(); - - public: + + public: G4double GetTargetLength() {return TargetLength*2.;}; G4Material* GetTargetMaterial() {return TargetMaterial;}; @@ -140,6 +140,7 @@ class Minos : public NPS::VDetector{ G4double WorldSizeXY; G4double WorldSizeZ; + G4double AnodeThickness; G4LogicalVolume* m_SquareDetector; G4LogicalVolume* m_CylindricalDetector; @@ -159,7 +160,8 @@ class Minos : public NPS::VDetector{ G4Tubs* solidTPC; G4LogicalVolume* logicTPC; // G4VPhysicalVolume* physiTPC; - + + //////////////// G4Tubs* solidWindow0; G4LogicalVolume* logicWindow0; // G4VPhysicalVolume* physiWindow0; @@ -214,6 +216,7 @@ class Minos : public NPS::VDetector{ // Associated Scorer G4MultiFunctionalDetector* m_MinosTargetScorer ; G4MultiFunctionalDetector* m_MinosTPCScorer ; + G4MultiFunctionalDetector* m_MinosPadScorer ; //////////////////////////////////////////////////// ///////////Event class to store Data//////////////// @@ -248,4 +251,82 @@ class Minos : public NPS::VDetector{ public: static NPS::VDetector* Construct(); }; + +class PadParameterisation : public G4VPVParameterisation +{ + public: + PadParameterisation(){}; + ~PadParameterisation(){}; + void ComputeTransformation(const G4int copyNo, G4VPhysicalVolume* physVol) const{ + // Note: copyNo will start with zero! + int PadsPerRing[18]={144,152,156,164,172,176,184,192,196,204,212,216,224,228,236,244,248,256}; + G4int Ring = 0; + if (copyNo<144){ + Ring = 0;} + else if (144<=copyNo && copyNo<296){ + Ring = 1;} + else if (296<=copyNo && copyNo<452){ + Ring = 2;} + else if (452<=copyNo && copyNo<616){ + Ring = 3;} + else if (616<=copyNo && copyNo<788){ + Ring = 4;} + else if (788<=copyNo && copyNo<964){ + Ring = 5;} + else if (964<=copyNo && copyNo<1148){ + Ring = 6;} + else if (1148<=copyNo && copyNo<1340){ + Ring = 7;} + else if (1340<=copyNo && copyNo<1536){ + Ring = 8;} + else if (1536<=copyNo && copyNo<1740){ + Ring = 9;} + else if (1740<=copyNo && copyNo<1952){ + Ring = 10;} + else if (1952<=copyNo && copyNo<2168){ + Ring = 11;} + else if (2168<=copyNo && copyNo<2392){ + Ring = 12;} + else if (2392<=copyNo && copyNo<2620){ + Ring = 13;} + else if (2620<=copyNo && copyNo<2856){ + Ring = 14;} + else if (2856<=copyNo && copyNo<3100){ + Ring = 15;} + else if (3100<=copyNo && copyNo<3348){ + Ring = 16;} + else if (3348<=copyNo && copyNo<3604){ + Ring = 17;} + + G4double R = (50.+ Ring*2.2)*mm; + G4double dPhi= (2*M_PI/PadsPerRing[Ring]); + G4double Phi = copyNo*dPhi; + G4double Xposition = R*cos(Phi); + G4double Yposition = R*sin(Phi); + G4ThreeVector origin(Xposition,Yposition,0); + physVol->SetTranslation(origin); + G4RotationMatrix* Rot = new G4RotationMatrix(); + Rot->rotateZ(-Phi); + physVol->SetRotation(Rot); + } + +}; + + + +/* class PadParameterisation : public G4VPVParameterisation */ +/* { */ + +/* public: */ + +/* PadParameterisation();//G4int NoPads, G4double StartZ, G4double Spacing); */ + +/* ~PadParameterisation(); */ + +/* void ComputeTransformation(const G4int copyNo, */ +/* G4VPhysicalVolume *physVol) const; */ + +/* }; */ + + #endif diff --git a/NPSimulation/Scorers/CMakeLists.txt b/NPSimulation/Scorers/CMakeLists.txt index 0e285e53a..2e6f09e58 100644 --- a/NPSimulation/Scorers/CMakeLists.txt +++ b/NPSimulation/Scorers/CMakeLists.txt @@ -1,2 +1,2 @@ -add_library(NPSScorers SHARED DriftChamberScorers.cc NPSHitsMap.hh CalorimeterScorers.cc InteractionScorers.cc DSSDScorers.cc SiliconScorers.cc PhotoDiodeScorers.cc ObsoleteGeneralScorers.cc DriftElectronScorers.cc TPCScorers.cc MDMScorer.cc NeutronDetectorScorers.cc ) +add_library(NPSScorers SHARED CylinderTPCScorers.cc DriftChamberScorers.cc NPSHitsMap.hh CalorimeterScorers.cc InteractionScorers.cc DSSDScorers.cc SiliconScorers.cc PhotoDiodeScorers.cc ObsoleteGeneralScorers.cc DriftElectronScorers.cc TPCScorers.cc MDMScorer.cc NeutronDetectorScorers.cc ) target_link_libraries(NPSScorers ${ROOT_LIBRARIES} ${Geant4_LIBRARIES} ${NPLib_LIBRARIES} -lNPInitialConditions -lNPInteractionCoordinates) diff --git a/NPSimulation/Scorers/CylinderTPCScorers.cc b/NPSimulation/Scorers/CylinderTPCScorers.cc new file mode 100644 index 000000000..3df49e923 --- /dev/null +++ b/NPSimulation/Scorers/CylinderTPCScorers.cc @@ -0,0 +1,146 @@ +/***************************************************************************** + * Copyright (C) 2009-2016 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: Pierre MORFOUACE contact address: morfouace@ganil.fr * + * * + * Creation Date : June 2018 * + * Last update : * + *---------------------------------------------------------------------------* + * Decription: * + * Scorer for TPC Drift Electron collector * + * * + *---------------------------------------------------------------------------* + * Comment: * + * This new type of scorer to count drift electron in the cathode * + * * + *****************************************************************************/ +#include "CylinderTPCScorers.hh" +#include "G4UnitsTable.hh" +using namespace CylinderTPCScorers; + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +vector<AnodeData>::iterator AnodeDataVector::find(const unsigned int& Pad){ + for(vector<AnodeData>::iterator it= m_Data.begin() ; it !=m_Data.end() ; it++){ + if((*it).GetPad()==Pad) + return it; + } + return m_Data.end(); +} + + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +PS_TPCAnode::PS_TPCAnode(G4String name,vector<G4int> NestingLevel,G4int depth) +:G4VPrimitiveScorer(name, depth){ + m_NestingLevel = NestingLevel; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +PS_TPCAnode::~PS_TPCAnode(){ +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +G4bool PS_TPCAnode::ProcessHits(G4Step* aStep, G4TouchableHistory*){ + + /* unsigned int mysize = m_NestingLevel.size(); */ + /* for (unsigned int i =0; i < mysize ; i++){ */ + /* t_Level.push_back(aStep->GetPreStepPoint()->GetTouchableHandle()->GetCopyNumber(m_NestingLevel[i])); */ + /* } */ + + G4String PID = aStep->GetTrack()->GetDefinition()->GetParticleName(); + + if(PID!="driftelectron"){ + return false; + } + + G4int Pad = aStep->GetPreStepPoint()->GetTouchableHandle()->GetCopyNumber(0); + + + // contain Enegy Time, DetNbr, StripFront and StripBack + t_Charge = aStep->GetTrack()->GetWeight(); + t_DriftTime = aStep->GetPreStepPoint()->GetProperTime(); + + int PadsPerRing[18]={144,152,156,164,172,176,184,192,196,204,212,216,224,228,236,244,248,256}; + G4int Ring = 0; + if (Pad<144){ + Ring = 0;} + else if (144<=Pad && Pad<296){ + Ring = 1;} + else if (296<=Pad && Pad<452){ + Ring = 2;} + else if (452<=Pad && Pad<616){ + Ring = 3;} + else if (616<=Pad && Pad<788){ + Ring = 4;} + else if (788<=Pad && Pad<964){ + Ring = 5;} + else if (964<=Pad && Pad<1148){ + Ring = 6;} + else if (1148<=Pad && Pad<1340){ + Ring = 7;} + else if (1340<=Pad && Pad<1536){ + Ring = 8;} + else if (1536<=Pad && Pad<1740){ + Ring = 9;} + else if (1740<=Pad && Pad<1952){ + Ring = 10;} + else if (1952<=Pad && Pad<2168){ + Ring = 11;} + else if (2168<=Pad && Pad<2392){ + Ring = 12;} + else if (2392<=Pad && Pad<2620){ + Ring = 13;} + else if (2620<=Pad && Pad<2856){ + Ring = 14;} + else if (2856<=Pad && Pad<3100){ + Ring = 15;} + else if (3100<=Pad && Pad<3348){ + Ring = 16;} + else if (3348<=Pad && Pad<3604){ + Ring = 17;} + + G4double R = (50.+ Ring*2.2)*mm; + G4double dPhi= (2*M_PI/PadsPerRing[Ring]); + G4double Phi = Pad*dPhi; + + t_X = R*cos(Phi); + t_Y = R*sin(Phi); + + t_Pad = Pad; + + vector<AnodeData>::iterator it; + it = m_Data.find(t_Pad); + if(it!= m_Data.end()) + it->Add(t_Charge); + else + m_Data.Set(t_Charge,t_DriftTime,t_Pad,t_X,t_Y); + + return TRUE; +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_TPCAnode::Initialize(G4HCofThisEvent*){ + m_Data.clear(); +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_TPCAnode::EndOfEvent(G4HCofThisEvent*){ +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_TPCAnode::clear(){ + m_Data.clear(); +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_TPCAnode::DrawAll(){ + +} + +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... +void PS_TPCAnode::PrintAll(){ +} +//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... diff --git a/NPSimulation/Scorers/CylinderTPCScorers.hh b/NPSimulation/Scorers/CylinderTPCScorers.hh new file mode 100644 index 000000000..c98cff32e --- /dev/null +++ b/NPSimulation/Scorers/CylinderTPCScorers.hh @@ -0,0 +1,130 @@ +#ifndef DEAnodeScorers_h +/***************************************************************************** + * Copyright (C) 2009-2016 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: Pierre MORFOUACE contact address: morfouace@ganil.fr * + * * + * Creation Date : July 2018 * + * Last update : * + *---------------------------------------------------------------------------* + * Decription: * + * File old the scorer specific to the Silicon Detector * + * * + *---------------------------------------------------------------------------* + * Comment: * + * This new style of scorer is aim to become the standard way of doing scorer* + * in NPTool. * + *The index is build using the TrackID, Detector Number and Strip Number. * + *The scorer Hold Energy and time together * + *Only one scorer is needed for a detector * + *****************************************************************************/ +#include "G4VPrimitiveScorer.hh" +#include "NPSHitsMap.hh" + +#include <map> +using namespace std; +using namespace CLHEP; + +namespace CylinderTPCScorers{ + + //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... + class AnodeData{ + public: + AnodeData(){}; + AnodeData(const double& Charge, const double& DriftTime, const unsigned int& Pad, const double& X, const double& Y){ + m_Charge = Charge; + m_DriftTime = DriftTime; + m_Pad = Pad; + m_X = X; + m_Y = Y; + } + ~AnodeData(){}; + + private: + double m_Charge; + double m_DriftTime; + double m_X; + double m_Y; + unsigned int m_Pad; + + public: + inline double GetCharge() const {return m_Charge;}; + inline double GetDriftTime() const {return m_DriftTime;}; + inline double GetX() const {return m_X;}; + inline double GetY() const {return m_Y;}; + inline unsigned int GetPad() const {return m_Pad;}; + void Add(const double& Charge){m_Charge+=Charge;}; + }; + + //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... + // Manage a vector of Anode hit + class AnodeDataVector{ + public: + AnodeDataVector(){}; + ~AnodeDataVector(){}; + + private: + vector<AnodeData> m_Data; + + public: + vector<AnodeData>::iterator find(const unsigned int& Pad) ; + void clear(){m_Data.clear();} ; + vector<AnodeData>::iterator end() {return m_Data.end();}; + vector<AnodeData>::iterator begin() {return m_Data.begin();}; + unsigned int size() {return m_Data.size();}; + void Add(const unsigned int& Pad,const double& Charge) {find(Pad)->Add(Charge);}; + void Set(const double& Charge, const double& DriftTime, const unsigned int& Pad, const double& X, const double& Y) {m_Data.push_back(AnodeData(Charge,DriftTime,Pad,X,Y));}; + AnodeData* operator[](const unsigned int& i){return &m_Data[i];}; + }; + + + + //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... + class PS_TPCAnode : public G4VPrimitiveScorer{ + + public: // with description + PS_TPCAnode(G4String name, vector<G4int>, G4int depth=0); + ~PS_TPCAnode(); + + protected: // with description + G4bool ProcessHits(G4Step*, G4TouchableHistory*); + + public: + void Initialize(G4HCofThisEvent*); + void EndOfEvent(G4HCofThisEvent*); + void clear(); + void DrawAll(); + void PrintAll(); + + private: + AnodeDataVector m_Data; + + private: // Needed for intermediate calculation (avoid multiple instantiation in Processing Hit) + + vector<G4int> m_NestingLevel; + unsigned int m_Level; + double t_Charge; + double t_DriftTime; + unsigned int t_Pad; + double t_X; + double t_Y; + + public: + unsigned int GetMult(){return m_Data.size();}; + double GetCharge(const double& i) {return m_Data[i]->GetCharge();}; + double GetDriftTime(const double& i) {return m_Data[i]->GetDriftTime();}; + double GetX(const double& i) {return m_Data[i]->GetX();}; + double GetY(const double& i) {return m_Data[i]->GetY();}; + unsigned int GetPad(const unsigned int& i) {return m_Data[i]->GetPad();}; + + + }; + +} + +#endif -- GitLab