/// @file AllPixTrackerSD.cc /// @brief Implementation of the Allpix tracker sensitive detector class. // // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // $Id: AllPixTrackerSD.cc,v 1.9 2006/06/29 17:48:27 gunter Exp $ // GEANT4 tag $Name: geant4-09-02 $ // #include "AllPixTrackerSD.hh" // GEANT4 include statements. #include "G4HCofThisEvent.hh" #include "G4Step.hh" #include "G4ThreeVector.hh" #include "G4SDManager.hh" #include "G4RunManager.hh" #include "G4ios.hh" #include "G4Track.hh" #include "G4VProcess.hh" #include "G4DecayTable.hh" #include "G4LogicalVolume.hh" // Allpix include statements. #include "AllPixGeoDsc.hh" // ROOT include statements. #include "TMath.h" #include "TString.h" // temp G4double g_temp_edep = 0.; G4int g_temp_pdgId = 0; // // AllPixTrackerSD constructor. // AllPixTrackerSD::AllPixTrackerSD( G4String name, G4ThreeVector absPosWrapper, G4ThreeVector relPosSD, AllPixGeoDsc * gD, G4RotationMatrix * rot ) : G4VSensitiveDetector(name) { // Set the Hits collection name. m_thisHitsCollectionName = name + "_HitsCollection"; collectionName.insert( m_thisHitsCollectionName ); // only one hit collection per detector for now // The absolute position of SD m_absolutePosOfWrapper = absPosWrapper; m_relativePosOfSD = relPosSD; m_rotationOfWrapper = rot; m_gD = gD; // Geo description m_thisIsAPixelDetector = true; m_globalTrackId_Dump = 0; G4cout << "INFO: Creating a sensitive detector (pixel):" << G4endl << "INFO: * Wrapper pos. (x,y,z) = (" << G4BestUnit(absPosWrapper.x(), "Length")<<", " << G4BestUnit(absPosWrapper.y(), "Length")<<", " << G4BestUnit(absPosWrapper.z(), "Length")<<")" << G4endl << "INFO: * rel. SD pos. (x,y,z) = (" << G4BestUnit(relPosSD.x(), "Length")<<", " << G4BestUnit(relPosSD.y(), "Length")<<", " << G4BestUnit(relPosSD.z(), "Length")<<")" << G4endl; }//end of the AllPixTrackerSD constructor (pixel detectors). // // AllPixTrackerSD constructor (non-pixel). // AllPixTrackerSD::AllPixTrackerSD( G4String name, G4ThreeVector absPos, G4RotationMatrix * rot) : G4VSensitiveDetector(name) { // Set the Hits collection name. m_thisHitsCollectionName = name + "_HitsCollection"; collectionName.insert( m_thisHitsCollectionName ); // only one hit collection per detector for now // reduced set of parameters for a SD which is not a pixel detector m_absolutePosOfWrapper = absPos; m_relativePosOfSD = G4ThreeVector(0,0,0); m_rotationOfWrapper = rot; m_gD = 0x0; // Geo description m_thisIsAPixelDetector = false; m_globalTrackId_Dump = 0; } // // AllPixTrackerSD destructor. // AllPixTrackerSD::~AllPixTrackerSD() {} void AllPixTrackerSD::Initialize(G4HCofThisEvent* HCE) { // // This runs once per event. The hitsCollections pointers are retrieved //I have a set of pointers to control that I get them right // Create the Hits collection. hitsCollection = new AllPixTrackerHitsCollection (SensitiveDetectorName, collectionName[0]); static G4int HCID = -1; HCID = G4SDManager::GetSDMpointer()->GetCollectionID(collectionName[0]); // Add to Hits collection of this event. HCE->AddHitsCollection( HCID, hitsCollection ); // Insert the pointer in a set to check its existence later // Normally there is only one instance of AllPixTrackerSD per sensitive volume m_hitsCollectionSet.insert(hitsCollection); }//end of AllPixTrackerSD::Initialize method. // // // G4bool AllPixTrackerSD::ProcessHits(G4Step * aStep, G4TouchableHistory *) { bool dbg = false; // Check first if we are working in a valid HitCollection // This should never happen if the user don't replicate detector Id in the macro. // A check is done in ReadGeoDescription ... I probably don't need to check this here. try { if ( m_hitsCollectionSet.find(hitsCollection) == m_hitsCollectionSet.end()) {// not found ! throw hitsCollection; } } catch (AllPixTrackerHitsCollection * h) { G4cout << "[WARNING] The following pointer to hitsCollection is invalid : " << h << G4endl; G4cout << " The available set contains " << m_hitsCollectionSet.size() << " collections." << G4endl; G4cout << " Trying to recover by ignoring this hit where this hitCollection" << G4endl; G4cout << " !!! You may have an error in your macro, bad detector ID !!!" << G4endl; G4cout << " has been given. AllPixTrackerSD::ProcessHits returns false." << G4endl; return false; } // Work with the Hit G4double edep = aStep->GetTotalEnergyDeposit(); if(edep==0.) return false; G4StepPoint * preStepPoint = aStep->GetPreStepPoint(); G4StepPoint * postStepPoint = aStep->GetPostStepPoint(); const G4TouchableHandle touchablepre = preStepPoint->GetTouchableHandle(); const G4TouchableHandle touchablepost = postStepPoint->GetTouchableHandle(); G4int copyIDy_pre = -1; G4int copyIDx_pre = -1; G4int copyIDy_post = -1; G4int copyIDx_post = -1; G4ThreeVector correctedPos(0,0,0); if (m_thisIsAPixelDetector) { // Get the absolute position of the hit in the lab frame. G4ThreeVector prePos = preStepPoint->GetPosition(); // Find the position of the hit relative to the position of the // wrapper - the object that is rotated by the detector rotation - // and then rotate it by the detector rotation. G4ThreeVector rotatedHitPos = prePos - m_absolutePosOfWrapper; rotatedHitPos = *m_rotationOfWrapper * rotatedHitPos; // Calculate pixel position relative to the centre of the sensor // from sensitive detector numbers. copyIDy_pre = touchablepre->GetCopyNumber(); // Pixel x copyIDx_pre = touchablepre->GetCopyNumber(1); // Pixel y // G4double pix_x = G4double(copyIDx_pre - m_gD->GetNPixelsX()/2) * m_gD->GetPixelX() + m_gD->GetHalfPixelX(); G4double pix_y = G4double(copyIDy_pre - m_gD->GetNPixelsY()/2) * m_gD->GetPixelY() + m_gD->GetHalfPixelY(); G4double pix_z = 0.0*um; // centre of the pixel, i.e. half way through the silicon. // G4ThreeVector pix_centre(pix_x,pix_y,pix_z); // The corrected position in then the // * Rotated hit position (relative to the centre of the wrapper); // * - the relative position of the sensor centre to the wrapper centre; // * - the relative position of the pixel centre to the sensor. // This value is then supplied to the hit for convenience. correctedPos = rotatedHitPos - m_relativePosOfSD - pix_centre; if ( (fabs(correctedPos.x()) > m_gD->GetHalfPixelX() + 1.0*nm) || (fabs(correctedPos.y()) > m_gD->GetHalfPixelY() + 1.0*nm) ) { G4cout << "WARNING: Hit is outside of pixel bounds! (" << G4BestUnit(m_gD->GetHalfPixelX(), "Length") << "," << G4BestUnit(m_gD->GetHalfPixelY(), "Length") << ")" << G4endl << "WARNING: Pixel ["<inverse() * rotatedPixelPos; if (dbg) { G4cout << "DEBUG: PROCESSING HIT:" << G4endl << "DEBUG: * wrapper position = (" << G4BestUnit(m_absolutePosOfWrapper.x(), "Length") << ", " << G4BestUnit(m_absolutePosOfWrapper.y(), "Length") << ", " << G4BestUnit(m_absolutePosOfWrapper.z(), "Length") << ")" << G4endl << "DEBUG: * relative sensor pos = (" << G4BestUnit(m_relativePosOfSD.x(), "Length") << ", " << G4BestUnit(m_relativePosOfSD.y(), "Length") << ", " << G4BestUnit(m_relativePosOfSD.z(), "Length") << ")" << G4endl << "DEBUG: * prePos = (" << G4BestUnit(prePos.x(), "Length") << ", " << G4BestUnit(prePos.y(), "Length") << ", " << G4BestUnit(prePos.z(), "Length") << ")" << G4endl << "DEBUG: * Rotated prePos wrt wrapper = (" << G4BestUnit(rotatedHitPos.x(), "Length") << ", " << G4BestUnit(rotatedHitPos.y(), "Length") << ", " << G4BestUnit(rotatedHitPos.z(), "Length") << ")" << G4endl << "DEBUG: * Pixel [" << MyWid(copyIDx_pre,3,0) << "," << MyWid(copyIDy_pre,3,0) << "] = (" << G4BestUnit(pix_x, "Length") << "," << G4BestUnit(pix_y, "Length") << "," << G4BestUnit(pix_z, "Length") << ")" << G4endl << "DEBUG: * Hit rel to pix cen. = (" << G4BestUnit(correctedPos.x(), "Length") << ", " << G4BestUnit(correctedPos.y(), "Length") << ", " << G4BestUnit(correctedPos.z(), "Length") << ")" << G4endl << "DEBUG: * Rotated pixel pos wrt wrapper = (" << G4BestUnit(rotatedPixelPos.x(), "Length") << ", " << G4BestUnit(rotatedPixelPos.y(), "Length") << ", " << G4BestUnit(rotatedPixelPos.z(), "Length") << ")" << G4endl << "DEBUG:" << G4endl; } // Tracking Dump. Simple Dump for charge drifting simulation purposes. /* m_globalTrackId_Dump; preStepPoint->GetKineticEnergy() << prePos.x() << "\t" << prePos.y() << "\t" << prePos.z() << "\t" << preStepPoint->GetKineticEnergy() << "\t" << preStepPoint->Get */ }//end of pixel detector check. // Look at the touchablepost only if in the same volume, i.e. in the sensitive Si Box // If the hit is in a different pixel, it is still the same phys volume // The problem is that if I the postStep is in a different volume, GetCopyNumber(1) // doesn't make sense anymore. G4ThreeVector postPos(0,0,0); if (preStepPoint->GetPhysicalVolume() == postStepPoint->GetPhysicalVolume()) { postPos = postStepPoint->GetPosition(); copyIDy_post = touchablepost->GetCopyNumber(); copyIDx_post = touchablepost->GetCopyNumber(1); } // process const G4VProcess * aProcessPointer = aStep->GetPostStepPoint()->GetProcessDefinedStep(); // track G4Track * aTrack = aStep->GetTrack(); // particle G4ParticleDefinition * aParticle = aTrack->GetDefinition(); // not used for now, not pretty. // I need to know where is this hit and tie it to a detector ID // G4String detId_S = touchablepre->GetSolid(2)->GetName(); // detId_S.remove(0,4); // remove the part "Box_", take the ID // create a hit instance AllPixTrackerHit * newHit = new AllPixTrackerHit(); //newHit->SetDetId(atoi(detId_S.c_str())); newHit->SetTrackID(aTrack->GetTrackID()); newHit->SetParentID(aTrack->GetParentID()); // Set the pixel x value. newHit->SetPixelNbX(copyIDx_pre); // Set the pixel y value. newHit->SetPixelNbY(copyIDy_pre); newHit->SetPostPixelNbX(copyIDx_post); newHit->SetPostPixelNbY(copyIDy_post); // Set the energy deposited in the hit. newHit->SetEdep(edep); // Set the absolute position of the hit. newHit->SetPos(aStep->GetPostStepPoint()->GetPosition()); // Set the position of the hit wrt. to the pixel centre // (see above for a detailed explanation). newHit->SetPosWithRespectToPixel( correctedPos ); newHit->SetProcessName(aProcessPointer->GetProcessName()); newHit->SetTrackPdgId(aParticle->GetPDGEncoding()); ///////////////////////////////////////////// g_temp_edep = edep; g_temp_pdgId = aParticle->GetPDGEncoding(); ///////////////////////////////////////////// newHit->SetTrackVolumeName(aTrack->GetVolume()->GetName()); newHit->SetParentVolumeName(aTrack->GetLogicalVolumeAtVertex()->GetName()); //G4cout << "hitsCollection : " << hitsCollection << G4endl; //G4cout << " entries --> " << hitsCollection->entries() << G4endl; hitsCollection->insert(newHit); //newHit->Print(); //newHit->Draw(); return true; }//end of AllPixTrackerSD::ProcessHits method. // // AllPixTrackerSD::EndOfEvent method. // void AllPixTrackerSD::EndOfEvent(G4HCofThisEvent*) { G4int NbHits = hitsCollection->entries(); // TW:: Commented out for now... // if(NbHits > 0) // G4cout << "--------> Hits Collection : " << collectionName[0] << " has " << NbHits << " hits " << G4endl; // Clear the Set of pointers to hitCollection used for verification m_hitsCollectionSet.clear(); }//end of the AllPixTrackerSD::EndOfEvent method. /* G4cout << " ----------------------------- " << G4endl; G4cout << "prePos : " << prePos.x()/mm << " " << prePos.y()/mm << " " << prePos.z()/mm << " [mm]" << G4endl; G4cout << "detectorPos : " << absCenterOfDetector.x()/mm << " " << absCenterOfDetector.y()/mm << " " << absCenterOfDetector.z()/mm << " [mm]" << G4endl; G4cout << "previous correctedPos : " << correctedPos.x()/um << " " << correctedPos.y()/um << " " << correctedPos.z()/um << " [um]" << G4endl << G4endl; */