WCSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
WCSimWCSD.cc
Go to the documentation of this file.
1 #include "WCSimWCSD.hh"
2 #include "G4ParticleTypes.hh"
3 #include "G4HCofThisEvent.hh"
4 #include "G4TouchableHistory.hh"
5 #include "G4Step.hh"
6 #include "G4ThreeVector.hh"
7 #include "G4SDManager.hh"
8 #include "G4RunManager.hh"
9 #include "Randomize.hh"
10 #include "G4ios.hh"
11 
12 #include "G4PhysicalConstants.hh"
13 #include "G4SystemOfUnits.hh"
14 
15 #include <sstream>
16 
18 #include "WCSimTrackInformation.hh"
19 
20 WCSimWCSD::WCSimWCSD(G4String CollectionName,
21  G4String name,
23  G4String detectorElement)
24 :G4VSensitiveDetector(name), detectorElement(detectorElement)
25 {
26  // Place the name of this collection on the list. We can have more than one
27  // in principle. CollectionName is a vector.
28 
29  // Note there is some sort of problem here. If I use the name
30  // Which has a "/" in it, I can find this collection later using
31  // GetCollectionID()
32 
33  collectionName.insert(CollectionName);
34 
35  fdet = myDet;
36 
37  HCID = -1;
38 }
39 
41 
42 void WCSimWCSD::Initialize(G4HCofThisEvent* HCE)
43 {
44  // Make a new hits collection. With the name we set in the constructor
46  (SensitiveDetectorName,collectionName[0]);
47 
48  // This is a trick. We only want to do this once. When the program
49  // starts HCID will equal -1. Then it will be set to the pointer to
50  // this collection.
51 
52 
53  // Get the Id of the "0th" collection
54  if (HCID<0){
55  HCID = GetCollectionID(0);
56  }
57  // Add it to the Hit collection of this event.
58  HCE->AddHitsCollection( HCID, hitsCollection );
59 
60  // Initialize the Hit map to all tubes not hit.
61  PMTHitMap.clear();
62  // Trick to access the static maxPE variable. This will go away with the
63  // variable.
64 
65  WCSimWCHit* newHit = new WCSimWCHit();
66  newHit->SetMaxPe(0);
67  delete newHit;
68 }
69 
70 G4bool WCSimWCSD::ProcessHits(G4Step* aStep, G4TouchableHistory*)
71 {
72  G4StepPoint* preStepPoint = aStep->GetPreStepPoint();
73  G4TouchableHandle theTouchable = preStepPoint->GetTouchableHandle();
74  G4VPhysicalVolume* thePhysical = theTouchable->GetVolume();
75 
76 
77  //XQ 3/30/11 try to get the local position try to add the position and direction
78  G4ThreeVector worldPosition = preStepPoint->GetPosition();
79  G4ThreeVector localPosition = theTouchable->GetHistory()->GetTopTransform().TransformPoint(worldPosition);
80  G4ThreeVector worldDirection = preStepPoint->GetMomentumDirection();
81  G4ThreeVector localDirection = theTouchable->GetHistory()->GetTopTransform().TransformAxis(worldDirection);
82 
83 
84 
85  WCSimTrackInformation* trackinfo
86  = (WCSimTrackInformation*)(aStep->GetTrack()->GetUserInformation());
87  G4int primParentID;
88  if (trackinfo)
89  primParentID = trackinfo->GetPrimaryParentID();
90  else // if there is no trackinfo, then it is a primary particle!
91  primParentID = aStep->GetTrack()->GetTrackID();
92 
93  G4int trackID = aStep->GetTrack()->GetTrackID();
94  G4String volumeName = aStep->GetTrack()->GetVolume()->GetName();
95 
96  G4double energyDeposition = aStep->GetTotalEnergyDeposit();
97  G4double hitTime = aStep->GetPreStepPoint()->GetGlobalTime();
98 
99  G4ParticleDefinition *particleDefinition =
100  aStep->GetTrack()->GetDefinition();
101 
102  if ( particleDefinition != G4OpticalPhoton::OpticalPhotonDefinition()
103  && energyDeposition == 0.0)
104  return false;
105  // MF : I don't see why other particles should register hits
106  // they don't in skdetsim.
107  if ( particleDefinition != G4OpticalPhoton::OpticalPhotonDefinition())
108  return false;
109 
110  // G4String WCIDCollectionName = fdet->GetIDCollectionName();
111  G4String WCCollectionName;
112  if(detectorElement=="tank") WCCollectionName = fdet->GetIDCollectionName();
113  else if (detectorElement=="OD") WCCollectionName = fdet->GetODCollectionName();
114 
115  // M Fechner : too verbose
116  // if (aStep->GetTrack()->GetTrackStatus() == fAlive)G4cout << "status is fAlive\n";
117  if ((aStep->GetTrack()->GetTrackStatus() == fAlive )
118  &&(particleDefinition == G4OpticalPhoton::OpticalPhotonDefinition()))
119  return false;
120 
121  // if ( particleDefinition == G4OpticalPhoton::OpticalPhotonDefinition() )
122  // G4cout << volumeName << " hit by optical Photon! " << G4endl;
123 
124  // Make the tubeTag string based on the replica numbers
125  // See WCSimDetectorConstruction::DescribeAndRegisterPMT() for matching
126  // tag construction.
127 
128  std::stringstream tubeTag;
129 
130  // Start tubeTag with mother to distinguish different PMT hierarchies
131 // G4LogicalVolume *theMother = thePhysical->GetMotherLogical();
132 // if (theMother != NULL)
133 // tubeTag << theMother->GetName() << ":";
134 
135 // tubeTag << thePhysical->GetName();
136  for (G4int i = theTouchable->GetHistoryDepth()-1 ; i >= 0; i--){
137  tubeTag << ":" << theTouchable->GetVolume(i)->GetName();
138  tubeTag << "-" << theTouchable->GetCopyNumber(i);
139  }
140  // tubeTag << ":" << theTouchable->GetVolume(i)->GetCopyNo();
141 
142 // G4cout << tubeTag.str() << G4endl;
143 
144  // Get the tube ID from the tubeTag
145  // G4int replicaNumber = WCSimDetectorConstruction::GetTubeID(tubeTag.str());
146  G4int replicaNumber;
147  if(detectorElement=="tank") replicaNumber = WCSimDetectorConstruction::GetTubeID(tubeTag.str());
148  else if(detectorElement=="OD") replicaNumber = WCSimDetectorConstruction::GetODTubeID(tubeTag.str());
149  else G4cout << "detectorElement not defined..." << G4endl;
150 
151  G4double theta_angle = 0.;
152  G4double effectiveAngularEfficiency = 0.;
153 
154 
155  //XQ Add the wavelength there
156  G4double wavelength = (2.0*M_PI*197.3)/( aStep->GetTrack()->GetTotalEnergy()/eV);
157  G4double ratio = 1.;
158  G4double maxQE = 0.;
159  G4double photonQE = 0.;
160  if (fdet->GetPMT_QE_Method() == 1 || fdet->GetPMT_QE_Method() == 4){
161  photonQE = 1.1;
162  }else if (fdet->GetPMT_QE_Method()==2){
163  // maxQE = fdet->GetPMTQE(WCIDCollectionName,wavelength,0,240,660,ratio);
164  maxQE = fdet->GetPMTQE(WCCollectionName,wavelength,0,240,660,ratio);
165  photonQE = fdet->GetPMTQE(volumeName, wavelength,1,240,660,ratio);
166  photonQE = photonQE/maxQE;
167  }else if (fdet->GetPMT_QE_Method() == 3){
168  ratio = 1./(1.-0.25);
169  photonQE = fdet->GetPMTQE(volumeName, wavelength,1,240,660,ratio);
170  }
171 
172 
173 
174  if (G4UniformRand() <= photonQE){
175 
176  G4double local_x = localPosition.x();
177  G4double local_y = localPosition.y();
178  G4double local_z = localPosition.z();
179  theta_angle = acos(fabs(local_z)/sqrt(pow(local_x,2)+pow(local_y,2)+pow(local_z,2)))/3.1415926*180.;
180  effectiveAngularEfficiency = fdet->GetPMTCollectionEfficiency(theta_angle, volumeName);
181  if (G4UniformRand() <= effectiveAngularEfficiency || fdet->UsePMT_Coll_Eff()==0){
182  //Retrieve the pointer to the appropriate hit collection. Since volumeName is the same as the SD name, this works.
183  G4SDManager* SDman = G4SDManager::GetSDMpointer();
184  G4RunManager* Runman = G4RunManager::GetRunManager();
185  G4int collectionID = SDman->GetCollectionID(volumeName);
186  const G4Event* currentEvent = Runman->GetCurrentEvent();
187  G4HCofThisEvent* HCofEvent = currentEvent->GetHCofThisEvent();
188  hitsCollection = (WCSimWCHitsCollection*)(HCofEvent->GetHC(collectionID));
189 
190  // If this tube hasn't been hit add it to the collection
191  if (PMTHitMap[replicaNumber] == 0)
192  {
193  WCSimWCHit* newHit = new WCSimWCHit();
194  newHit->SetTubeID(replicaNumber);
195  newHit->SetTrackID(trackID);
196  newHit->SetEdep(energyDeposition);
197  newHit->SetLogicalVolume(thePhysical->GetLogicalVolume());
198 
199  G4AffineTransform aTrans = theTouchable->GetHistory()->GetTopTransform();
200  newHit->SetRot(aTrans.NetRotation());
201 
202  aTrans.Invert();
203  newHit->SetPos(aTrans.NetTranslation());
204 
205  // Set the hitMap value to the collection hit number
206  PMTHitMap[replicaNumber] = hitsCollection->insert( newHit );
207  (*hitsCollection)[PMTHitMap[replicaNumber]-1]->AddPe(hitTime);
208  (*hitsCollection)[PMTHitMap[replicaNumber]-1]->AddParentID(primParentID);
209 
210  // if ( particleDefinition != G4OpticalPhoton::OpticalPhotonDefinition() )
211  // newHit->Print();
212  }
213  else {
214  (*hitsCollection)[PMTHitMap[replicaNumber]-1]->AddPe(hitTime);
215  (*hitsCollection)[PMTHitMap[replicaNumber]-1]->AddParentID(primParentID);
216 
217  }
218  }
219  }
220 
221  return true;
222 }
223 
224 void WCSimWCSD::EndOfEvent(G4HCofThisEvent* HCE)
225 {
226  if (verboseLevel>0)
227  {
228 
229  //Need to specify which collection in case multiple geometries are built
230  G4String WCIDCollectionName = fdet->GetIDCollectionName();
231  G4SDManager* SDman = G4SDManager::GetSDMpointer();
232  G4int collectionID = SDman->GetCollectionID(WCIDCollectionName);
233  hitsCollection = (WCSimWCHitsCollection*)HCE->GetHC(collectionID);
234  G4int numHits = hitsCollection->entries();
235 
236  // G4cout << "There are " << numHits << " hits in the WC: " << G4endl;
237  G4cout << "There are " << numHits << " hits in the "<<detectorElement<<" : "<< G4endl;
238  for (G4int i=0; i < numHits; i++)
239  (*hitsCollection)[i]->Print();
240  }
241 }
242 
G4double GetPMTQE(G4String, G4double, G4int, G4double, G4double, G4double)
Definition: WCSimPMTQE.cc:21
G4int HCID
Definition: WCSimWCSD.hh:24
void SetMaxPe(G4int number=0)
Definition: WCSimWCHit.hh:68
void SetTubeID(G4int tube)
Definition: WCSimWCHit.hh:58
void SetRot(G4RotationMatrix rotMatrix)
Definition: WCSimWCHit.hh:62
void EndOfEvent(G4HCofThisEvent *)
Definition: WCSimWCSD.cc:224
static G4int GetODTubeID(std::string tubeTag)
void Initialize(G4HCofThisEvent *)
Definition: WCSimWCSD.cc:42
static G4int GetTubeID(std::string tubeTag)
G4THitsCollection< WCSimWCHit > WCSimWCHitsCollection
Definition: WCSimWCHit.hh:169
G4double GetPMTCollectionEfficiency(G4double theta_angle, G4String CollectionName)
void SetLogicalVolume(G4LogicalVolume *logV)
Definition: WCSimWCHit.hh:63
WCSimWCSD(G4String, G4String, WCSimDetectorConstruction *, G4String)
Definition: WCSimWCSD.cc:20
G4String detectorElement
Definition: WCSimWCSD.hh:30
void SetTrackID(G4int track)
Definition: WCSimWCHit.hh:59
void SetPos(G4ThreeVector xyz)
Definition: WCSimWCHit.hh:61
WCSimWCHitsCollection * hitsCollection
Definition: WCSimWCSD.hh:26
G4bool ProcessHits(G4Step *, G4TouchableHistory *)
Definition: WCSimWCSD.cc:70
~WCSimWCSD()
Definition: WCSimWCSD.cc:40
WCSimDetectorConstruction * fdet
Definition: WCSimWCSD.hh:25
std::map< int, int > PMTHitMap
Definition: WCSimWCSD.hh:27
void SetEdep(G4double de)
Definition: WCSimWCHit.hh:60