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