SToGS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
SToGS_TwoShellsDetectorConstruction.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 
28 // G4 includes
29 #include "G4Material.hh"
30 #include "G4Box.hh"
31 #include "G4Sphere.hh"
32 #include "G4LogicalVolume.hh"
33 #include "G4PVPlacement.hh"
34 #include "G4PVParameterised.hh"
35 #include "G4UserLimits.hh"
36 #include "G4VisAttributes.hh"
37 #include "G4Colour.hh"
38 #include "G4ios.hh"
39 
40 // SToGS:: includes
43 #include "SToGS_DetectorFactory.hh"
44 
45 using namespace std;
46 
47 SToGS::TwoShellsDetectorConstruction::aShell::aShell()
48 {
49  Name = "";
50  MatName = "";
51  RMin = 0.0;
52  RMax = 0.0;
53  PhiStart = 0.0;
54  PhiDelta = 0.0;
55  ThetaStart = 0.0;
56  ThetaDelta = 0.0;
57  IsActive = 0;
58 }
59 
60 SToGS::TwoShellsDetectorConstruction::aShell::aShell(const aShell &from)
61 {
62  Name = from.Name;
63  MatName = from.MatName;
64  RMin = from.RMin;
65  RMax = from.RMax;
66  PhiStart = from.PhiStart;
67  PhiDelta = from.PhiDelta;
68  ThetaStart = from.ThetaStart;
69  ThetaDelta = from.ThetaDelta;
70  IsActive = from.IsActive;
71 }
72 
73 void SToGS::TwoShellsDetectorConstruction::aShell::Print(std::ostream &out)
74 {
75  out << Name << " " << MatName << " "
76  << RMin/CLHEP::cm << " " << RMax/CLHEP::cm << " "
77  << PhiStart<< " " << PhiDelta/CLHEP::deg << " " << ThetaStart/CLHEP::deg << " " << ThetaDelta/CLHEP::deg << " " << IsActive << endl;
78 }
79 
81  solidWorld(0),
82  logicWorld(0),
83  physiWorld(0)
84 {
85  Inner.Name = "Shell:0";
86  Inner.MatName = "NaI";
87 
88  Inner.RMin = 10.*CLHEP::cm;
89  Inner.RMax = 15.*CLHEP::cm;
90  Inner.PhiStart = 0.*CLHEP::deg;
91  Inner.PhiDelta = 360.*CLHEP::deg;
92  Inner.ThetaStart = 0.*CLHEP::deg;
93  Inner.ThetaDelta = 180.*CLHEP::deg;
94  Inner.IsActive = 1;
95 
96  Outer.Name = "Shell:1";
97  Outer.MatName = "BGO";
98 
99  Outer.RMin = 25.*CLHEP::cm;
100  Outer.RMax = 40.*CLHEP::cm;
101  Outer.PhiStart = 0.*CLHEP::deg;
102  Outer.PhiDelta = 360.*CLHEP::deg;
103  Outer.ThetaStart = 0.*CLHEP::deg;
104  Outer.ThetaDelta = 180.*CLHEP::deg;
105  Outer.IsActive = 1;
106 
107  // reads parameters from an ascii file
109 }
110 
112  solidWorld(0),
113  logicWorld(0),
114  physiWorld(0)
115 {
116  Inner.Name = "Shell:0";
117  Inner.MatName = "NaI";
118 
119  Inner.RMin = 10.*CLHEP::cm;
120  Inner.RMax = 15.*CLHEP::cm;
121  Inner.PhiStart = 0.0*CLHEP::deg;
122  Inner.PhiDelta = 360.*CLHEP::deg;
123  Inner.ThetaStart = 0.*CLHEP::deg;
124  Inner.ThetaDelta = 180.*CLHEP::deg;
125  Inner.IsActive = 1;
126 
127  Outer.Name = "Shell:1";
128  Outer.MatName = "BGO";
129 
130  Outer.RMin = 25.*CLHEP::cm;
131  Outer.RMax = 40.*CLHEP::cm;
132  Outer.PhiStart = 0.*CLHEP::deg;
133  Outer.PhiDelta = 360.*CLHEP::deg;
134  Outer.ThetaStart = 0.*CLHEP::deg;
135  Outer.ThetaDelta = 180.*CLHEP::deg;
136  Outer.IsActive = 1;
137 
138  // reads parameters from an ascii file
139  ComputeParameters(filename);
140 }
141 
143 {
144  for(unsigned int i = 0; i < otherShells.size() ; i++ ) {
145  delete otherShells[i];
146  }
147 }
148 
150 {
151  G4cout << " ------ INF ------ from SToGS::TwoShellsDetectorConstruction::ComputeParameters with " << filename << G4endl;
152 
153  // init the MaterialConsultant to check the materials defined
154  SToGS::MaterialConsultant *materialFactory = SToGS::MaterialConsultant::theConsultant();
155 
156  // open the ascii file
157  ifstream file; file.open(filename.data());
158  if ( file.is_open() == false ) {
159  G4cout << " ** WARNING ** cannot open file " << filename << G4endl;
160  G4cout << " ==> Current parameters are used " << G4endl;
161  Inner.Print(G4cout);
162  Outer.Print(G4cout);
163  return;
164  }
165 
166  // read the file and init the Shell structures
167  const G4int MAXWIDTH = 300; char aline[MAXWIDTH]; file.getline(aline,MAXWIDTH);
168  aShell tmp;
169  G4int nb_active = 0, nb_mandatory = 0; G4double rlastmin = 0.0, rlastmax = 0.0;
170  while ( file.good() ) {
171 
172  if ( aline[0] == '#' ) {
173  file.getline(aline,MAXWIDTH);
174  continue;
175  } // this line is a comment
176 
177  // from the line extract the sphere definition
178  char name[30], mat[30];
179  G4float tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; G4int tmpi;
180 
181  G4int format = sscanf(aline,"%s %s %f %f %f %f %f %f %d",name,mat,&tmp1,&tmp2,&tmp3,&tmp4,&tmp5,&tmp6,&tmpi);
182 
183  tmp.Name = name; tmp.MatName = mat;
184 
185  tmp.RMin = tmp1*CLHEP::cm;
186  tmp.RMax = tmp2*CLHEP::cm;
187  tmp.PhiStart = tmp3*CLHEP::deg;
188  tmp.PhiDelta = tmp4*CLHEP::deg;
189  tmp.ThetaStart = tmp5*CLHEP::deg;
190  tmp.ThetaDelta = tmp6*CLHEP::deg;
191  tmp.IsActive = tmpi;
192 
193  // check if these values are consistents ... if not the shell is not registered
194  // geometrical considerations
195  G4int check;
196 
197  check = 0;
198  if ( tmp.RMin > tmp.RMax )
199  check++;
200  if ( tmp.PhiStart < 0.0 || tmp.PhiStart > 360.0/CLHEP::deg )
201  check++;
202  if ( tmp.PhiDelta < 0.0 || tmp.PhiDelta > 360.0/CLHEP::deg )
203  check++;
204  if ( tmp.ThetaStart < 0.0 || tmp.ThetaStart > 180.0/CLHEP::deg )
205  check++;
206  if ( tmp.ThetaDelta < 0.0 || tmp.ThetaDelta > 180.0/CLHEP::deg )
207  check++;
208 
209  if ( check > 0 ) {
210  G4cout << " ** WARNING ** the following shell has geometrical problems (removed from the final geometry) ";
211  tmp.Print(G4cout);
212  }
213  // check if the material is known
214  if ( materialFactory->FindOrBuildMaterial(tmp.MatName) == NULL ) {
215  G4cout << " ** WARNING ** the material of the following shell is unknown: "; tmp.Print(G4cout);
216  G4cout << *(G4Material::GetMaterialTable()) << G4endl;
217  check++;
218  }
219  if ( ( tmp.RMin > rlastmin && tmp.RMin < rlastmax ) || ( tmp.RMax > rlastmin && tmp.RMax < rlastmax ) ) {
220  G4cout << " ** WARNING ** the following shell overlaps with a previous one: "; tmp.Print(G4cout);
221  check++;
222  }
223  if ( check > 0 ) {
224  file.getline(aline,MAXWIDTH);
225  continue;
226  }
227 
228  if ( format == 9 ) { // it has been read with the expected format = no errors
229 
230  rlastmin = tmp.RMin; rlastmax = tmp.RMax; // keep the radius of the last shell
231 
232  if ( tmp.Name == "Shell:0" ) {
233  if ( tmp.MatName == "AIR" )
234  tmp.IsActive = 0; // Air cannot be a detector
235 
236  Inner = tmp; nb_mandatory++; if ( tmp.IsActive ) nb_active++;
237  }
238  else {
239  if ( tmp.Name == "Shell:1" ) {
240  if ( tmp.MatName == "AIR" )
241  tmp.IsActive = 0;
242 
243  Outer = tmp; nb_mandatory++; if ( tmp.IsActive ) nb_active++;
244  }
245  else { // inactive shell
246  tmp.IsActive = 0; // just to be sure
247 
248  // add it to the collection of inactive shells
249  aShell *ptshell = new aShell(); (*ptshell) = tmp; otherShells.push_back(ptshell);
250  }
251  }
252  }
253  else { G4cout << " ** WARNING ** the following line does not have the expected format:" << G4endl << aline << G4endl; }
254 
255  file.getline(aline,MAXWIDTH); // READ NEXT LINE
256  }
257  file.close();
258 
259  // now check out if something looks wrong (overlappings, etc ..)
260  if ( nb_active == 0 ) { // there are no active shells ..
261  G4cout << " ** WARNING **, there is no active shell defined " << G4endl;
262  }
263  if ( nb_mandatory != 2 ) { //
264  G4cout << " ** WARNING **, " << 2 - nb_mandatory << " shell(s) missing " << G4endl;
265  }
266  // print oout the final geometry loaded
267  G4cout << " Shell:0 and Shell:1 definitions: " << G4endl;
268  G4cout << "\t"; Inner.Print(G4cout); G4cout << "\t"; Outer.Print(G4cout);
269  if ( otherShells.size() ) {
270  G4cout << " List of passive materials: " << G4endl;
271  for(unsigned int i = 0; i < otherShells.size() ; i++ ) { G4cout << "\t"; otherShells[i]->Print(G4cout); }
272  }
273  G4cout << " ------ END ------ from SToGS::TwoShellsDetectorConstruction::ComputeParameters " << G4endl;
274 }
275 
277 {
278  G4cout << " ------ INF ------ from SToGS::TwoShellsDetectorConstruction::Construct() " << G4endl;
279 
280  // Clean old geometry, if any
281  //
282  // G4GeometryManager::GetInstance()->OpenGeometry();
283  // G4PhysicalVolumeStore::GetInstance()->Clean();
284  // G4LogicalVolumeStore::GetInstance()->Clean();
285  // G4SolidStore::GetInstance()->Clean();
286 
287  // build the world based on the outer shell
288  G4double HalfWorldLength = 1.5*Outer.RMax;
289 
290  // just check out that a passive material has not been added after the outer shell
291  for (unsigned int i = 0; i < otherShells.size() ; i++ ) {
292  if ( otherShells[i]->RMax > Outer.RMax )
293  HalfWorldLength = 1.5*otherShells[i]->RMax;
294  }
295 
296  solidWorld= new G4Box("TwoShells",HalfWorldLength,HalfWorldLength,HalfWorldLength);
297  logicWorld= new G4LogicalVolume(solidWorld, SToGS::MaterialConsultant::theConsultant()->FindOrBuildMaterial("AIR"), "TheWorld", 0, 0, 0);
298 
299  logicWorld->SetVisAttributes(G4VisAttributes::Invisible); // hide the world
300 
301  // Must place the World Physical volume unrotated at (0,0,0).
302  physiWorld = new G4PVPlacement(0, // no rotation
303  G4ThreeVector(), // at (0,0,0)
304  logicWorld, // its logical volume
305  "TwoShells", // its name
306  0, // its mother volume
307  false, // no boolean operations
308  -1); // copy number
309 
310  // Inner and outer are built
311  G4Sphere *asolidShell; G4LogicalVolume *alogicShell; G4VPhysicalVolume *aphysiShell; G4VisAttributes *visatt;
312 
313  asolidShell = new G4Sphere(Inner.Name, Inner.RMin, Inner.RMax, Inner.PhiStart, Inner.PhiDelta, Inner.ThetaStart, Inner.ThetaDelta);
314  logicInner = new G4LogicalVolume(asolidShell,
315  SToGS::MaterialConsultant::theConsultant()->FindOrBuildMaterial(Inner.MatName),
316  Inner.Name,0,0,0);
317  visatt = new G4VisAttributes( G4Colour(0.0, 0.0, 1.0) ); visatt->SetVisibility(true);
318  logicInner->SetVisAttributes( visatt );
319  aphysiShell = new G4PVPlacement(0, // no rotation
320  G4ThreeVector(), // at (0,0,0)
321  logicInner, // its logical volume
322  Inner.Name, // its name
323  logicWorld, // its mother volume
324  false, // no boolean operations
325  0); // copy number
326 
327 
328  asolidShell = new G4Sphere(Outer.Name, Outer.RMin, Outer.RMax, Outer.PhiStart, Outer.PhiDelta, Outer.ThetaStart, Outer.ThetaDelta);
329  logicOuter = new G4LogicalVolume(asolidShell,
330  SToGS::MaterialConsultant::theConsultant()->FindOrBuildMaterial(Outer.MatName),
331  Outer.Name,0,0,0);
332  visatt = new G4VisAttributes( G4Colour(1.0, 0.0, 0.) ); visatt->SetVisibility(true);
333  logicOuter->SetVisAttributes( visatt );
334  aphysiShell = new G4PVPlacement(0, // no rotation
335  G4ThreeVector(), // at (0,0,0)
336  logicOuter, // its logical volume
337  Outer.Name, // its name
338  logicWorld, // its mother volume
339  false, // no boolean operations
340  1); // copy number
341 
342  // do the same for other shells
343  for (unsigned int i = 0; i < otherShells.size() ; i++ ) {
344  aShell *tmp = otherShells[i];
345 
346  asolidShell = new G4Sphere(tmp->Name, tmp->RMin, tmp->RMax, tmp->PhiStart, tmp->PhiDelta, tmp->ThetaStart, tmp->ThetaDelta);
347  alogicShell = new G4LogicalVolume(asolidShell,
348  SToGS::MaterialConsultant::theConsultant()->FindOrBuildMaterial(tmp->MatName),
349  tmp->Name,0,0,0);
350  visatt = new G4VisAttributes( G4Colour(0.3, 0.3, 0.3) ); visatt->SetVisibility(true);
351  alogicShell->SetVisAttributes( visatt );
352  aphysiShell = new G4PVPlacement(0, // no rotation
353  G4ThreeVector(), // at (0,0,0)
354  alogicShell, // its logical volume
355  tmp->Name, // its name
356  logicWorld, // its mother volume
357  false, // no boolean operations
358  -1); // copy number
359  }
360 
361 #ifdef G4MULTITHREADED
362 #else
363  ConstructSDandField();
364 #endif
365  G4cout << " ------ END ------ from SToGS::TwoShellsDetectorConstruction::Construct() " << G4endl;
366 
367  // the world is returned
368  return physiWorld;
369 }
370 
372 {
373  G4cout << " ------ INF ------ from SToGS::TwoShellsDetectorConstruction::ConstructSDandField() " << G4endl;
374 
375  // sensitive part. Because the sensitive part depends on what we would to extrac
376  // for analysis, it asks th OutputManager to give it the sensitive part
377  G4VSensitiveDetector *sd = SToGS::DetectorFactory::GetSD("/SToGS/SD/Tracker");
378  if ( sd && Inner.IsActive ) {
379  //SetSensitiveDetector("Shell:0", sd);
380  logicInner->SetSensitiveDetector( sd );
381  }
382  // sensitive part. Because the sensitive part depends on what we would to extract
383  // for analysis, it asks th OutputManager to give it the sensitive part
384  if ( sd && Outer.IsActive ) {
385  // SetSensitiveDetector("Shell:1", sd);
386  logicOuter->SetSensitiveDetector( sd );
387  }
388  G4cout << " ------ END ------ from SToGS::TwoShellsDetectorConstruction::ConstructSDandField() " << G4endl;
389 }
390 
391 
392 
393 
394 
void ComputeParameters(G4String filename="DetectorFactory/Generics/TwoShells.geo")
from a given file, it computes the parameters of the two shells
static G4VSensitiveDetector * GetSD(G4String opt, const char sd_type= 'S')
Get a particular SD. S means a SD while s is for Scorers.
virtual G4VPhysicalVolume * Construct()
One of the mandatory class to be implemented in order to have G4 working properly.
virtual void ConstructSDandField()
NEW G4.10 ... but also define for G4.9 except is is called explicitely at the end of Construct...