Session 5 : Enoncé

Code for download: session5_start.tar.gz

Exercise:

  • Implement hit and sensitive detector classes for the Drift chamber (EDChamberHit, EDChamberSD) to account the following information when a charged track passed through the detector:
    • the chamber layer number
    • the time when a particle hits chamber
    • the hit local position (the position in the chamber volume frame)
  • Implement hit and sensitive detector classes for the EM calorimeter (EDEmCalorimeterHit, EDEmCalorimeterSD) to account the following information:
    • the layer number
    • the total energy deposit in the layer (= the accumulated deposit from all particles).
      See example basic/B4/B4c.
  • Add printing of the hit collections at the end of each event (in the SD::EndOfEvent() function).
  • Replace EDEmCalorimeterSD with a suitable Geant4 scorer.
    See example basic/B4/B4d.

    • Do not remove already implemented EDEmCalorimeter* classes, but only comment out the SD setting in EDDetectorConstruction class.
    • Add printing of hits accounted in the scorer in EDEventAction::EndOfEventAction.
    • Check that the results obtained with the scorer are identical with thoseobtained with the sensitive detector.

Solution:

Solution step by step:

Accounting hits in drift chamber:

  1. Connect the EDChamberSD class with Chamber logical volume in EDDetectorConstruction::Construct() (in src/EDDetectorConstruction.cc):
    // Define sensitive detectors
    EDChamberSD* chamber1SD 
      = new EDChamberSD("Chamber1SD", "Chamber1HitsCollection");
    G4SDManager::GetSDMpointer()->AddNewDetector(chamber1SD);
    wirePlane1LV->SetSensitiveDetector(chamber1SD);
  2. Update EDChamberHit class so that it can hold requested data. For each information we have to add a corresponding data member and « setter and « getter » member functions. (See the example of MyHit class in the presentation.):
    For accounting the time when a particle hits the chamber, add in include/EDChamberHit.hh:

    // add setter/getter methods
    void      SetTime(G4double time) { fTime = time; }
    G4double  GetTime() const        { return fTime; }
    // data members
    G4double  fTime;

    Then add printing of the added value in EDChamberHit::Print()(in src/EDChamberHit.cc).

    G4cout << "Chamber hit time [s]: " << fTime/s << G4endl;
  3. Update  EDChamberSD::ProcessHits() function (in src/EDChamberSD.cc) to create a hit object of  EDChamberHit class, retrieve the requested information from G4Step and set it to a newly created hit object (see the example of this function in the presentation.)
    // Create a new hit object of EDChamberHit type
    EDChamberHit* newHit = new EDChamberHit();
    // Get time from G4Step object 
    G4StepPoint* preStepPoint = step->GetPreStepPoint();
    G4double time = preStepPoint->GetGlobalTime();
    newHit->SetTime(time);
    // Add hit in the collection
    fHitsCollection->insert(newHit);
    return true;
  4. Update EDChamberSD::EndOfEvent()(in src/EDChamberSD.cc) and add printing hits collection (according to the example in the presentation):
    G4cout << "\n-------->" <<  fHitsCollection->GetName() 
           << ": in this event: " << G4endl;     
    G4int nofHits = fHitsCollection->entries();
    for ( G4int i=0; i<nofHits; i++ ) {
      (*fHitsCollection)[i]->Print();
    }
  5. At this stage, the program prints the time accounted in chamber volumes. It remains to complete the EDChamberHit, EDChamberSD classes with two more data members:
    // data members
    G4int     fLayerNumber;
    G4ThreeVector  fPosition;

    and their setter/getter methods and update also the remaining code for these new data.The complete code can be found in the provided solution.

Accounting hits in calorimeter:

  1. Connect the EDEmCalorimeterSD class with EmLayer logical volume in the same way as for EDChamberSD.
  2. Update EDEmCalorimeterHit class in an analogous way as in case of EDChamberHit, the only difference will be The function for accumulation energy deposit:
    // add setter/getter methods
    void AddEdep(G4double edep) { fEdep += edep; }
    // data members
    G4double  fEdep;
  3. In difference from tracker detector type, we create only one hit per each calorimeter layer during an event which is updated with each particle energy deposit in the cell. That’s why we create all hits already in EDEmCalorimeterSD::Initialize() (in src/EDEmCalorimeterSD.cc):
    for (G4int i=0; i<10; ++i) { 
      EDEmCalorimeterHit* newHit = new EDEmCalorimeterHit(); 
      newHit->SetLayerNumber(i);
      fHitsCollection->insert(newHit);
    }

    Then, in EDEmCalorimeterSD::ProcessHits() we need to update the hit of the calorimeter layer where accounting of energy is processed:

    G4bool EDEmCalorimeterSD::ProcessHits(G4Step* step,
                                 G4TouchableHistory* /*history*/)
    {
      // Get energy deposit
      G4double edep = step->GetTotalEnergyDeposit();
      if ( edep==0. ) return false;     
    
      // Get layer number (using touchable)
      G4TouchableHistory* touchable
        = (G4TouchableHistory*)(step->GetPreStepPoint()
          ->GetTouchable());
      G4VPhysicalVolume* layerPV = touchable->GetVolume();
      G4int layerNumber = layerPV->GetCopyNo();
    
      // Get hit accounting data for this layer  
      EDEmCalorimeterHit* hit = (*fHitsCollection)[layerNumber];
      if ( ! hit ) {
        G4cerr << "Cannot access hit " << layerNumber << G4endl;
        exit(1);
      }         
    
       // Add energy deposit value   
      hit->AddEdep(edep);
    
      return true;
    }

Exercise ++:

The exercises marked as ++ are optional; they are recommended for participants who have already some experience with Geant4 and get some time left for practicing more than the basic exercise proposed above.

        • Choose another suitable Geant4 scorer and add it to the previous one.