WCSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
WCSimConstructGeometryTables.cc
Go to the documentation of this file.
2 #include "WCSimPmtInfo.hh"
3 
4 #include "G4Material.hh"
5 #include "G4Element.hh"
6 #include "G4Box.hh"
7 #include "G4LogicalVolume.hh"
8 #include "G4VPhysicalVolume.hh"
9 #include "G4PVPlacement.hh"
10 #include "G4ThreeVector.hh"
11 #include "G4Vector3D.hh"
12 #include "globals.hh"
13 #include "G4VisAttributes.hh"
14 #include "G4Tubs.hh"
15 #include "G4Sphere.hh"
16 
17 #include "G4PhysicalConstants.hh"
18 #include "G4SystemOfUnits.hh"
19 
20 #include <sstream>
21 #include <iomanip>
22 
23 using std::setw;
24 // These routines are object registration routines that you can pass
25 // to the traversal code.
26 
28 (G4VPhysicalVolume* aPV ,int aDepth, int /*replicaNo*/,
29  const G4Transform3D& aTransform)
30 {
31  for (int levels = 0; levels < aDepth; levels++) G4cout << " ";
32  G4cout << aPV->GetName() << " Level:" << aDepth
33  << " Pos:" << aTransform.getTranslation()
34  << " Rot:" << aTransform.getRotation().getTheta()/deg
35  << "," << aTransform.getRotation().getPhi()/deg
36  << "," << aTransform.getRotation().getPsi()/deg
37  << G4endl;
38 }
39 
41 (G4VPhysicalVolume* aPV ,int aDepth, int /*replicaNo*/,
42  const G4Transform3D& aTransform)
43 {
44 
45  // Grab mishmash of useful information from the tree while traversing it
46  // This information will later be written to the geometry file
47  // (Alternatively one might define accessible constants)
48 
49  if ((aPV->GetName() == "WCBarrel") ||
50  (aPV->GetName() == "WorldBox")) { // last condition is the HyperK Envelope name.
51  // Stash info in data member
52  WCOffset = G4ThreeVector(aTransform.getTranslation().getX()/cm,
53  aTransform.getTranslation().getY()/cm,
54  aTransform.getTranslation().getZ()/cm);
55  }
56 
57 
58 
59  // Stash info in data member
60  // AH Need to store this in CM for it to be understood by SK code
61  WCPMTSize = WCPMTRadius/cm;// I think this is just a variable no if needed
62 
63 
64  // Note WC can be off-center... get both extremities
65  static G4double zmin=100000,zmax=-100000.;
66  static G4double xmin=100000,xmax=-100000.;
67  static G4double ymin=100000,ymax=-100000.;
68  if (aDepth == 0) { // Reset for this traversal
69  xmin=100000,xmax=-100000.;
70  ymin=100000,ymax=-100000.;
71  zmin=100000,zmax=-100000.;
72  }
73 
74  if ((aPV->GetName() == "WCCapBlackSheet") || (aPV->GetName().find("glassFaceWCPMT") != std::string::npos)){
75  G4double x = aTransform.getTranslation().getX()/cm;
76  G4double y = aTransform.getTranslation().getY()/cm;
77  G4double z = aTransform.getTranslation().getZ()/cm;
78 
79  if (x<xmin){xmin=x;}
80  if (x>xmax){xmax=x;}
81 
82  if (y<ymin){ymin=y;}
83  if (y>ymax){ymax=y;}
84 
85  if (z<zmin){zmin=z;}
86  if (z>zmax){zmax=z;}
87 
88 
89 
90  WCCylInfo[0] = xmax-xmin;
91  WCCylInfo[1] = ymax-ymin;
92  WCCylInfo[2] = zmax-zmin;
93  // G4cout << "determin hight: " << zmin << " " << zmax << " " << aPV->GetName()<<" " << z << G4endl;
94  }
95 }
96 
97 void WCSimDetectorConstruction::DescribeAndRegisterPMT(G4VPhysicalVolume* aPV ,int aDepth, int replicaNo,
98  const G4Transform3D& aTransform)
99 {
100  static std::string replicaNoString[20];
101 
102  std::stringstream depth;
103  std::stringstream pvname;
104 
105  depth << replicaNo;
106  pvname << aPV->GetName();
107 
108  replicaNoString[aDepth] = pvname.str() + "-" + depth.str();
109 
110  if (aPV->GetName()== WCIDCollectionName ||aPV->GetName()== WCODCollectionName )
111  {
112 
113  // First increment the number of PMTs in the tank.
114  if(aPV->GetName()== WCIDCollectionName) totalNumPMTs++;
115  if(aPV->GetName()== WCODCollectionName) totalNumODPMTs++;
116 
117  // Put the location of this tube into the location map so we can find
118  // its ID later. It is coded by its tubeTag string.
119  // This scheme must match that used in WCSimWCSD::ProcessHits()
120 
121  std::string tubeTag;
122  for (int i=0; i <= aDepth; i++)
123  tubeTag += ":" + replicaNoString[i];
124  // G4cout << tubeTag << G4endl;
125 
126  if(aPV->GetName()== WCIDCollectionName) {
127  if(tubeLocationMap.find(tubeTag) != tubeLocationMap.end()) {
128  G4cerr << "Repeated tube tag: " << tubeTag << G4endl;
129  G4cerr << "Assigned to both tube #" << tubeLocationMap[tubeTag] << " and #" << totalNumPMTs << G4endl;
130  G4cerr << "Cannot continue -- hits will not be recorded correctly." << G4endl;
131  G4cerr << "Please make sure that logical volumes with multiple placements are each given a unique copy number"
132  << G4endl;
133  assert(false);
134  }
135  tubeLocationMap[tubeTag] = totalNumPMTs;
136 
137  // Put the transform for this tube into the map keyed by its ID
138  tubeIDMap[totalNumPMTs] = aTransform;
139  }
140 
141  if(aPV->GetName()== WCODCollectionName) {
142  if(ODtubeLocationMap.find(tubeTag) != ODtubeLocationMap.end()) {
143  G4cerr << "Repeated tube tag: " << tubeTag << G4endl;
144  G4cerr << "Assigned to both tube #" << ODtubeLocationMap[tubeTag] << " and #" << totalNumODPMTs << G4endl;
145  G4cerr << "Cannot continue -- hits will not be recorded correctly." << G4endl;
146  G4cerr << "Please make sure that logical volumes with multiple placements are each given a unique copy number"
147  << G4endl;
148  assert(false);
149  }
151 
152  // Put the transform for this tube into the map keyed by its ID
153  ODtubeIDMap[totalNumODPMTs] = aTransform;
154  }
155 
156  // G4cout << "depth " << depth.str() << G4endl;
157  // G4cout << "tubeLocationmap[" << tubeTag << "]= " << tubeLocationMap[tubeTag] << "\n";
158 
159  // Print
160  // G4cout << "Tube: "<<std::setw(4) << totalNumPMTs << " " << tubeTag
161  // << " Pos:" << aTransform.getTranslation()/cm
162  // << " Rot:" << aTransform.getRotation().getTheta()/deg
163  // << "," << aTransform.getRotation().getPhi()/deg
164  // << "," << aTransform.getRotation().getPsi()/deg
165  // << G4endl;
166  }
167 }
168 
169 // Utilities to do stuff with the info we have found.
170 
171 // Output to WC geometry text file
173 {
174  // Open a file
175  geoFile.open("geofile.txt", std::ios::out);
176 
177  geoFile.precision(2);
178  geoFile.setf(std::ios::fixed);
179 
180  // (JF) Get first tube transform for filling in detector radius
181  // the height is still done with WCCylInfo above
182  G4Transform3D firstTransform = tubeIDMap[2];
183  innerradius = sqrt(pow(firstTransform.getTranslation().getX()/cm,2)
184  + pow(firstTransform.getTranslation().getY()/cm,2));
185 
186  if (isEggShapedHyperK){
187  geoFile << setw(8)<< 0;
188  geoFile << setw(8)<< 0;
189  }else{
190  geoFile << setw(8)<< innerradius;
191  geoFile << setw(8)<<WCCylInfo[2];
192  }
193  geoFile << setw(10)<<totalNumPMTs;
194  geoFile << setw(8)<<WCPMTSize << setw(4) <<G4endl;
195 
196  geoFile << setw(8)<< WCOffset(0)<< setw(8)<<WCOffset(1)<<
197  setw(8) << WCOffset(2)<<G4endl;
198 
199  //G4double maxZ=0.0;// used to tell if pmt is on the top/bottom cap
200  //G4double minZ=0.0;// or the barrel
201  G4int cylLocation;
202 
203 
204  // clear before add new stuff in
205  for (unsigned int i=0;i<fpmts.size();i++){
206  delete fpmts.at(i);
207  }
208  fpmts.clear();
209 
210  // Grab the tube information from the tubeID Map and dump to file.
211  for ( int tubeID = 1; tubeID <= totalNumPMTs; tubeID++){
212  G4Transform3D newTransform = tubeIDMap[tubeID];
213 
214  // Get tube orientation vector
215  G4Vector3D nullOrient = G4Vector3D(0,0,1);
216  G4Vector3D pmtOrientation = newTransform * nullOrient;
217  //cyl_location cylLocation = tubeCylLocation[tubeID];
218 
219  // Figure out if pmt is on top/bottom or barrel
220  // print key: 0-top, 1-barrel, 2-bottom
221  if (pmtOrientation.z()==1.0)//bottom
222  {cylLocation=2;}
223  else if (pmtOrientation.z()==-1.0)//top
224  {cylLocation=0;}
225  else // barrel
226  {cylLocation=1;}
227 
228  geoFile.precision(9);
229  geoFile << setw(4) << tubeID
230  << " " << setw(8) << newTransform.getTranslation().getX()/cm
231  << " " << setw(8) << newTransform.getTranslation().getY()/cm
232  << " " << setw(8) << newTransform.getTranslation().getZ()/cm
233  << " " << setw(7) << pmtOrientation.x()
234  << " " << setw(7) << pmtOrientation.y()
235  << " " << setw(7) << pmtOrientation.z()
236  << " " << setw(3) << cylLocation
237  << G4endl;
238 
239  WCSimPmtInfo *new_pmt = new WCSimPmtInfo(cylLocation,
240  newTransform.getTranslation().getX()/cm,
241  newTransform.getTranslation().getY()/cm,
242  newTransform.getTranslation().getZ()/cm,
243  pmtOrientation.x(),
244  pmtOrientation.y(),
245  pmtOrientation.z(),
246  tubeID);
247 
248  fpmts.push_back(new_pmt);
249 
250  }
251 
252  // Record locations of OD PMTs to file ffODpmts variables
253  for (unsigned int i=0;i<fODpmts.size();i++){
254  delete fODpmts.at(i);
255  }
256  fODpmts.clear();
257 
258  // Grab the tube information from the tubeID Map and dump to file.
259  for ( int tubeID = 1; tubeID <= totalNumODPMTs; tubeID++){
260  G4Transform3D newTransform = ODtubeIDMap[tubeID];
261 
262  // Get tube orientation vector
263  G4Vector3D nullOrient = G4Vector3D(0,0,1);
264  G4Vector3D pmtOrientation = newTransform * nullOrient;
265  //cyl_location cylLocation = tubeCylLocation[tubeID];
266 
267  // TODO: make these record something sensible for the OD
268  if (pmtOrientation.z()==1.0) // TOP OD
269  {cylLocation=5;}
270  else if (pmtOrientation.z()==-1.0) // BOTTOM OD
271  {cylLocation=3;}
272  else // barrel
273  {cylLocation=4;}
274 
275  geoFile.precision(9);
276  geoFile << setw(4) << tubeID
277  << " " << setw(8) << newTransform.getTranslation().getX()/CLHEP::cm
278  << " " << setw(8) << newTransform.getTranslation().getY()/CLHEP::cm
279  << " " << setw(8) << newTransform.getTranslation().getZ()/CLHEP::cm
280  << " " << setw(7) << pmtOrientation.x()
281  << " " << setw(7) << pmtOrientation.y()
282  << " " << setw(7) << pmtOrientation.z()
283  << " " << setw(3) << cylLocation
284  << G4endl;
285 
286  WCSimPmtInfo *new_pmt = new WCSimPmtInfo(cylLocation,
287  newTransform.getTranslation().getX()/CLHEP::cm,
288  newTransform.getTranslation().getY()/CLHEP::cm,
289  newTransform.getTranslation().getZ()/CLHEP::cm,
290  pmtOrientation.x(),
291  pmtOrientation.y(),
292  pmtOrientation.z(),
293  tubeID);
294 
295  fODpmts.push_back(new_pmt);
296 
297  }
298 
299  geoFile.close();
300 
301 }
302 
303 
304 // Code for traversing the geometry tree. This code is very general you pass
305 // it a function and it will call the function with the information on each
306 // object it finds.
307 //
308 // The traversal code comes from a combination of me/G4Lab project &
309 // from source/visualization/modeling/src/G4PhysicalVolumeModel.cc
310 //
311 // If you are trying to understand how passing the function works you need
312 // to understand pointers to member functions...
313 //
314 // Also notice that DescriptionFcnPtr is a (complicated) typedef.
315 //
316 
318 (G4VPhysicalVolume* aPV, int aDepth, const G4Transform3D& aTransform,
319  DescriptionFcnPtr registrationRoutine)
320 {
321  // Recursively visit all of the geometry below the physical volume
322  // pointed to by aPV including replicas.
323 
324  G4ThreeVector originalTranslation = aPV->GetTranslation();
325  G4RotationMatrix* pOriginalRotation = aPV->GetRotation();
326 
327  if (aPV->IsReplicated() )
328  {
329  EAxis axis;
330  G4int nReplicas;
331  G4double width, offset;
332  G4bool consuming;
333 
334  aPV->GetReplicationData(axis,nReplicas,width,offset,consuming);
335 
336  for (int n = 0; n < nReplicas; n++)
337  {
338  switch(axis) {
339  default:
340  case kXAxis:
341  aPV->SetTranslation(G4ThreeVector
342  (-width*(nReplicas-1)*0.5+n*width,0,0));
343  aPV->SetRotation(0);
344  break;
345  case kYAxis:
346  aPV->SetTranslation(G4ThreeVector
347  (0,-width*(nReplicas-1)*0.5+n*width,0));
348  aPV->SetRotation(0);
349  break;
350  case kZAxis:
351  aPV->SetTranslation(G4ThreeVector
352  (0,0,-width*(nReplicas-1)*0.5+n*width));
353  aPV->SetRotation(0);
354  break;
355  case kRho:
356  //Lib::Out::putL("GeometryVisitor::visit: WARNING:");
357  //Lib::Out::putL(" built-in replicated volumes replicated");
358  //Lib::Out::putL(" in radius are not yet properly visualizable.");
359  aPV->SetTranslation(G4ThreeVector(0,0,0));
360  aPV->SetRotation(0);
361  break;
362  case kPhi:
363  {
364  G4RotationMatrix rotation;
365  rotation.rotateZ(-(offset+(n+0.5)*width));
366  // Minus Sign because for the physical volume we need the
367  // coordinate system rotation.
368  aPV->SetTranslation(G4ThreeVector(0,0,0));
369  aPV->SetRotation(&rotation);
370  }
371  break;
372 
373  } // axis switch
374 
375  DescribeAndDescendGeometry(aPV, aDepth, n, aTransform,
376  registrationRoutine);
377 
378  } // num replicas for loop
379  } // if replicated
380  else
381  DescribeAndDescendGeometry(aPV, aDepth, aPV->GetCopyNo(), aTransform,
382  registrationRoutine);
383 
384  // Restore original transformation...
385  aPV->SetTranslation(originalTranslation);
386  aPV->SetRotation(pOriginalRotation);
387 }
388 
390 (G4VPhysicalVolume* aPV ,int aDepth, int replicaNo,
391  const G4Transform3D& aTransform, DescriptionFcnPtr registrationRoutine)
392 {
393  // Calculate the new transform relative to the old transform
394 
395  G4Transform3D* transform =
396  new G4Transform3D(*(aPV->GetObjectRotation()), aPV->GetTranslation());
397 
398  G4Transform3D newTransform = aTransform * (*transform);
399  delete transform;
400 
401  // Call the routine we use to print out geometry descriptions, make
402  // tables, etc. The routine was passed here as a paramater. It needs to
403  // be a memeber function of the class
404 
405  (this->*registrationRoutine)(aPV, aDepth, replicaNo, newTransform);
406 
407  int nDaughters = aPV->GetLogicalVolume()->GetNoDaughters();
408 
409  for (int iDaughter = 0; iDaughter < nDaughters; iDaughter++)
410  TraverseReplicas(aPV->GetLogicalVolume()->GetDaughter(iDaughter),
411  aDepth+1, newTransform, registrationRoutine);
412 }
413 
414 
415 
417  if (i>=0&&i<=2){
418  return WCCylInfo[i];
419  }else if(i==3){
420  return innerradius;
421  }else{
422  return 0;
423  }
424 }
std::vector< WCSimPmtInfo * > fpmts
void DescribeAndRegisterPMT(G4VPhysicalVolume *, int, int, const G4Transform3D &)
void DescribeAndDescendGeometry(G4VPhysicalVolume *, int, int, const G4Transform3D &, DescriptionFcnPtr)
void PrintGeometryTree(G4VPhysicalVolume *, int, int, const G4Transform3D &)
static hash_map< std::string, int, hash< std::string > > ODtubeLocationMap
void GetWCGeom(G4VPhysicalVolume *, int, int, const G4Transform3D &)
void TraverseReplicas(G4VPhysicalVolume *, int, const G4Transform3D &, DescriptionFcnPtr)
static std::map< int, G4Transform3D > ODtubeIDMap
std::vector< WCSimPmtInfo * > fODpmts
static std::map< int, G4Transform3D > tubeIDMap
static hash_map< std::string, int, hash< std::string > > tubeLocationMap