]>
Commit | Line | Data |
---|---|---|
b68f7176 | 1 | // $Id$ |
2 | // Category: geometry | |
3 | // | |
4 | // See the class description in the header file. | |
5 | ||
6 | #include "TG4GeometryServices.h" | |
7 | #include "TG4VSensitiveDetector.h" | |
8 | #include "TG4Globals.h" | |
9 | #include "TG3Units.h" | |
10 | ||
11 | #include <G4VSensitiveDetector.hh> | |
12 | #include <G4LogicalVolumeStore.hh> | |
13 | #include <G4LogicalVolume.hh> | |
14 | #include <G4Material.hh> | |
e4a64a3a | 15 | #include <G4UserLimits.hh> |
b68f7176 | 16 | #include <G3toG4.hh> |
17 | ||
18 | TG4GeometryServices* TG4GeometryServices::fgInstance = 0; | |
19 | ||
20 | TG4GeometryServices::TG4GeometryServices(TG4intVector* mediumIdVector, | |
21 | TG4NameMap* nameMap) | |
22 | { | |
23 | // | |
24 | if (fgInstance) { | |
25 | TG4Globals::Exception( | |
26 | "TG4GeometryServices: attempt to create two instances of singleton."); | |
27 | } | |
28 | ||
29 | fMediumIdVector = mediumIdVector; | |
30 | fNameMap = nameMap; | |
31 | ||
32 | fgInstance = this; | |
33 | } | |
34 | ||
35 | TG4GeometryServices::TG4GeometryServices() { | |
36 | // | |
37 | TG4Globals::Exception( | |
38 | "Attempt to copy TG4GeometryServices singleton."); | |
39 | } | |
40 | ||
41 | ||
42 | TG4GeometryServices::TG4GeometryServices(const TG4GeometryServices& right) { | |
43 | // | |
44 | TG4Globals::Exception( | |
45 | "Attempt to copy TG4GeometryServices singleton."); | |
46 | } | |
47 | ||
48 | ||
49 | TG4GeometryServices::~TG4GeometryServices() { | |
50 | // | |
51 | } | |
52 | ||
53 | //============================================================================= | |
54 | // | |
55 | // operators | |
56 | // | |
57 | //============================================================================= | |
58 | ||
59 | TG4GeometryServices& | |
60 | TG4GeometryServices::operator=(const TG4GeometryServices& right) | |
61 | { | |
62 | // check assignement to self | |
63 | if (this == &right) return *this; | |
64 | ||
65 | TG4Globals::Exception( | |
66 | "Attempt to assign TG4GeometryServices singleton."); | |
67 | ||
68 | return *this; | |
69 | } | |
70 | ||
71 | ||
72 | //============================================================================= | |
73 | // | |
74 | // public methods | |
75 | // | |
76 | //============================================================================= | |
77 | ||
78 | ||
79 | G4double* TG4GeometryServices::CreateG4doubleArray(Float_t* array, | |
80 | G4int size) const | |
81 | { | |
82 | // Converts Float_t* array to G4double*, | |
83 | // !! The new array has to be deleted by user. | |
84 | // --- | |
85 | ||
86 | G4double* doubleArray; | |
87 | if (size>0) { | |
88 | doubleArray = new G4double[size]; | |
89 | for (G4int i=0; i<size; i++) doubleArray[i] = array[i]; | |
90 | } | |
91 | else { | |
92 | doubleArray = 0; | |
93 | } | |
94 | return doubleArray; | |
95 | } | |
96 | ||
97 | ||
98 | G4String TG4GeometryServices::CutName(const char* name) const | |
99 | { | |
100 | // Removes spaces after the name if present. | |
101 | // --- | |
102 | ||
103 | G4String cutName = name; | |
104 | G4int i = cutName.length(); | |
105 | while (cutName(--i) == ' ') cutName = cutName(0,i); | |
106 | ||
107 | return cutName; | |
108 | } | |
109 | ||
b68f7176 | 110 | void TG4GeometryServices::G4ToG3VolumeName(G4String& name) const |
111 | { | |
112 | // Cuts _copyNo extension added to logical volume name in case | |
113 | // the logical volume was created by Gsposp method. | |
114 | // --- | |
115 | ||
116 | if (name.contains(gSeparator)) | |
117 | name = name(0,name.first(gSeparator)); | |
118 | } | |
119 | ||
e4a64a3a | 120 | G4int TG4GeometryServices::SetUserLimits(G4UserLimits* userLimits, |
121 | G4LogicalVolume* lv) | |
122 | { | |
123 | // Sets user limits to all logical volumes corresponding to | |
124 | // the same G3 volume as the volume with specified name. | |
125 | // Returns the number of updated logical volumes. | |
126 | // --- | |
127 | ||
128 | G4LogicalVolumeStore* pLVStore = G4LogicalVolumeStore::GetInstance(); | |
129 | ||
130 | G4String volName = lv->GetName(); | |
131 | G4ToG3VolumeName(volName); | |
132 | ||
133 | G4int counter = 0; | |
134 | for (G4int i=0; i<pLVStore->entries(); i++) { | |
135 | G4LogicalVolume* lv = (*pLVStore)[i]; | |
136 | G4String name = lv->GetName(); | |
137 | G4ToG3VolumeName(name); | |
138 | if (name == volName) { | |
139 | lv->SetUserLimits(userLimits); | |
140 | counter++; | |
141 | } | |
142 | } | |
143 | ||
144 | return counter; | |
145 | } | |
b68f7176 | 146 | |
147 | G4Material* TG4GeometryServices::MixMaterials(G4String name, G4double density, | |
148 | TG4StringVector* matNames, TG4doubleVector* matWeights) | |
149 | { | |
150 | // Creates a mixture of selected materials | |
151 | // --- | |
152 | ||
153 | // number of materials to be mixed | |
154 | G4int nofMaterials = matNames->entries(); | |
155 | if (nofMaterials != matWeights->entries()) { | |
156 | G4String text = "TG4GeometryServices::MixMaterials: "; | |
157 | text = text + "different number of material names and weigths."; | |
158 | TG4Globals::Exception(text); | |
159 | } | |
160 | // add verbose | |
161 | // G4cout << "Nof of materials to be mixed: " << nofMaterials << G4endl; | |
162 | ||
163 | // fill vector of materials | |
164 | TG4MaterialVector matVector; | |
165 | G4int im; | |
166 | for (im=0; im< nofMaterials; im++) { | |
167 | // material | |
168 | G4Material* material = G4Material::GetMaterial((*matNames)[im]); | |
169 | matVector.insert(material); | |
170 | } | |
171 | ||
172 | // create the mixed material | |
173 | G4Material* mixture = new G4Material(name, density, nofMaterials); | |
174 | for (im=0; im< nofMaterials; im++) { | |
175 | G4Material* material = matVector[im]; | |
176 | G4double fraction = (*matWeights)[im]; | |
177 | mixture->AddMaterial(material, fraction); | |
178 | } | |
179 | ||
180 | return mixture; | |
181 | } | |
182 | ||
183 | ||
184 | Int_t TG4GeometryServices::NofG3Volumes() const | |
185 | { | |
186 | // Returns the total number of logical volumes corresponding | |
187 | // to G3 volumes. ( | |
188 | // The logical volume that were created by Gsposp method | |
189 | // with a generic name (name_copyNo) are NOT included. | |
190 | // --- | |
191 | ||
192 | G4LogicalVolumeStore* pLVStore = G4LogicalVolumeStore::GetInstance(); | |
193 | ||
194 | G4int counter = 0; | |
195 | for (G4int i=0; i<pLVStore->entries(); i++) { | |
196 | G4LogicalVolume* lv = (*pLVStore)[i]; | |
197 | if (IsG3Volume(lv->GetName())) counter++; | |
198 | } | |
199 | ||
200 | return counter; | |
201 | } | |
202 | ||
203 | ||
204 | Int_t TG4GeometryServices::NofG4LogicalVolumes() const | |
205 | { | |
206 | // Returns the total number of logical volumes in the geometry. | |
207 | // --- | |
208 | ||
209 | G4LogicalVolumeStore* pLVStore = G4LogicalVolumeStore::GetInstance(); | |
210 | return pLVStore->entries(); | |
211 | } | |
212 | ||
213 | ||
214 | Int_t TG4GeometryServices::NofG4PhysicalVolumes() const | |
215 | { | |
216 | // Returns the total number of physical volumes in the geometry. | |
217 | // --- | |
218 | ||
219 | G4LogicalVolumeStore* pLVStore = G4LogicalVolumeStore::GetInstance(); | |
220 | ||
221 | G4int counter = 0; | |
222 | for (G4int i=0; i<pLVStore->entries(); i++) { | |
223 | counter += ((*pLVStore)[i])->GetNoDaughters(); | |
224 | } | |
225 | ||
226 | return counter; | |
227 | } | |
228 | ||
229 | ||
230 | Int_t TG4GeometryServices::NofSensitiveDetectors() const | |
231 | { | |
232 | // Returns the total number of sensitive detectors. | |
233 | // --- | |
234 | ||
235 | return TG4VSensitiveDetector::GetTotalNofSensitiveDetectors(); | |
236 | } | |
237 | ||
238 | ||
239 | G4int TG4GeometryServices::GetVolumeID(const G4String& volName) const | |
240 | { | |
241 | // Returns the sensitive detector identifier. | |
242 | // !! Gives exception in case logical volume is not associated with | |
243 | // a sensitive detector. | |
244 | // --- | |
245 | ||
246 | G4String g4VolName = CutName(volName); | |
247 | G4LogicalVolumeStore* pLVStore = G4LogicalVolumeStore::GetInstance(); | |
248 | ||
249 | for (G4int i=0; i<pLVStore->entries(); i++) { | |
250 | G4LogicalVolume* lv = pLVStore->at(i); | |
251 | G4VSensitiveDetector* sd = lv->GetSensitiveDetector(); | |
252 | ||
253 | if ((sd) && (sd->GetName()==g4VolName)) { | |
254 | TG4VSensitiveDetector* tsd = dynamic_cast<TG4VSensitiveDetector*>(sd); | |
255 | if (tsd) | |
256 | return tsd->GetID(); | |
257 | else { | |
258 | TG4Globals::Exception( | |
259 | "TG4GeometryServices::GetVolumeID: Unknown sensitive detector type"); | |
260 | return 0; | |
261 | } | |
262 | } | |
263 | } | |
264 | ||
265 | G4String text = "TG4GeometryServices::VolId: Sensitive detector "; | |
266 | text = text + g4VolName; | |
267 | text = text + " is not defined.\n"; | |
268 | TG4Globals::Warning(text); | |
269 | return 0; | |
270 | } | |
271 | ||
272 | ||
273 | G4int TG4GeometryServices::GetVolumeID(G4LogicalVolume* logicalVolume) const | |
274 | { | |
275 | // Returns the sensitive detector ID of the specified | |
276 | // logical volume. | |
277 | // --- | |
278 | ||
279 | // sensitive detector ID | |
280 | G4VSensitiveDetector* sd | |
281 | = logicalVolume->GetSensitiveDetector(); | |
282 | if (sd) { | |
283 | TG4VSensitiveDetector* tsd = dynamic_cast<TG4VSensitiveDetector*>(sd); | |
284 | if (tsd) | |
285 | return tsd->GetID(); | |
286 | else { | |
287 | TG4Globals::Exception( | |
288 | "TG4GeometryServices::GetVolumeID: Unknown sensitive detector type"); | |
289 | return 0; | |
290 | } | |
291 | } | |
292 | else { | |
293 | G4String text = "TG4GeometryServices::GetVolumeID: \n"; | |
294 | text = text + " Volume " + logicalVolume->GetName(); | |
295 | text = text + " has not a sensitive detector."; | |
296 | //TG4Globals::Exception(text); | |
297 | TG4Globals::Warning(text); | |
298 | return 0; | |
299 | } | |
300 | } | |
301 | ||
302 | ||
303 | G4String TG4GeometryServices::GetVolumeName(G4int volumeId) const | |
304 | { | |
305 | // Returns the name of the sensitive detector with the given identifier. | |
306 | // Gives a warning in case logical volume is not associated with | |
307 | // a sensitive detector. | |
308 | // --- | |
309 | ||
310 | G4LogicalVolumeStore* pLVStore = G4LogicalVolumeStore::GetInstance(); | |
311 | ||
312 | for (G4int i=0; i<pLVStore->entries(); i++) { | |
313 | G4LogicalVolume* lv = pLVStore->at(i); | |
314 | G4VSensitiveDetector* sd = lv->GetSensitiveDetector(); | |
315 | ||
316 | if (sd) { | |
317 | G4int sdID; | |
318 | TG4VSensitiveDetector* tsd = dynamic_cast<TG4VSensitiveDetector*>(sd); | |
319 | if (tsd) | |
320 | sdID = tsd->GetID(); | |
321 | else { | |
322 | TG4Globals::Exception( | |
323 | "TG4GeometryServices::VolId: Unknown sensitive detector type"); | |
324 | return ""; | |
325 | } | |
326 | if (sdID == volumeId) return sd->GetName(); | |
327 | } | |
328 | } | |
329 | ||
330 | G4String text = "TG4GeometryServices::VolName:\n"; | |
331 | text = text + " Sensitive detector with given id is not defined. \n"; | |
332 | TG4Globals::Warning(text); | |
333 | return ""; | |
334 | } | |
335 | ||
336 | ||
337 | G4LogicalVolume* TG4GeometryServices::GetLogicalVolume(G4int volumeId) const | |
338 | { | |
339 | // Finds the first logical volume with specified volumeId | |
340 | // (sensitive detector ID) in G4LogicalVolumeStore. | |
341 | // --- | |
342 | ||
343 | G4LogicalVolumeStore* pLVStore = G4LogicalVolumeStore::GetInstance(); | |
344 | ||
345 | for (G4int i=0; i<pLVStore->entries(); i++) { | |
346 | G4LogicalVolume* lv = pLVStore->at(i); | |
347 | if (GetVolumeID(lv) == volumeId) return lv; | |
348 | } | |
349 | ||
350 | G4String text = "TG4GeometryServices::GetLogicalVolume: \n"; | |
351 | text = text + " Logical volume with given ID does not exist."; | |
352 | return 0; | |
353 | } | |
354 | ||
355 | ||
356 | G4bool TG4GeometryServices::IsG3Volume(const G4String& lvName) const | |
357 | { | |
358 | // Returns true if the logical volume of given volumeName | |
359 | // was not created by Gsposp method with a generic name | |
360 | // (name_copyNo). | |
361 | // --- | |
362 | ||
363 | if (lvName.contains(gSeparator)) | |
364 | return false; | |
365 | else | |
366 | return true; | |
367 | } | |
368 | ||
369 | ||
370 | const G4String& TG4GeometryServices::GetMapSecond(const G4String& name) | |
371 | { | |
372 | // Returns the second string associated with the name in | |
373 | // the name map. | |
374 | // --- | |
375 | ||
376 | return fNameMap->GetSecond(name); | |
377 | } | |
378 | ||
379 | ||
380 | G4int TG4GeometryServices::GetMediumId(G4Material* material) const | |
381 | { | |
382 | // Returns the second index for materials (having its origin in | |
383 | // G4 tracking media concept) | |
384 | // --- | |
385 | ||
386 | return (*fMediumIdVector)[material->GetIndex()]; | |
387 | } | |
388 | ||
389 | ||
390 | Int_t TG4GeometryServices::GetMediumId(G4int volumeId) const | |
391 | { | |
392 | // Return the material number for a given volume id | |
393 | // --- | |
394 | ||
395 | G4LogicalVolume* logicalVolume = GetLogicalVolume(volumeId); | |
396 | ||
397 | G4Material* material = logicalVolume->GetMaterial(); | |
398 | ||
399 | return GetMediumId(material); | |
400 | } | |
401 | ||
402 | ||
403 | G4double TG4GeometryServices::GetEffA(G4Material* material) const | |
404 | { | |
405 | // Returns A or effective A=sum(pi*Ai) (if compound/mixture) | |
406 | // of given material. | |
407 | // --- | |
408 | ||
409 | G4double a = 0.; | |
410 | G4int nofElements = material->GetNumberOfElements(); | |
411 | if (nofElements > 1) { | |
412 | G4String text = "Effective A for material mixture ("; | |
413 | text = text + material->GetName(); | |
414 | text = text + ") is used."; | |
415 | //TG4Globals::Warning(text); | |
416 | ||
417 | for (G4int i=0; i<nofElements; i++) { | |
418 | G4double aOfElement = material->GetElement(i)->GetA(); | |
419 | G4double massFraction = material->GetFractionVector()[i]; | |
420 | a += aOfElement*massFraction /(TG3Units::AtomicWeight()); | |
421 | } | |
422 | } | |
423 | else { | |
424 | a = material->GetA(); | |
425 | a /= TG3Units::AtomicWeight(); | |
426 | } | |
427 | return a; | |
428 | } | |
429 | ||
430 | ||
431 | G4double TG4GeometryServices::GetEffZ(G4Material* material) const | |
432 | { | |
433 | // Returns Z or effective Z=sum(pi*Zi) (if compound/mixture) | |
434 | // of given material. | |
435 | // --- | |
436 | ||
437 | G4double z = 0.; | |
438 | G4int nofElements = material->GetNumberOfElements(); | |
439 | if (nofElements > 1) { | |
440 | G4String text = "Effective Z for material mixture ("; | |
441 | text = text + material->GetName(); | |
442 | text = text + ") is used."; | |
443 | //TG4Globals::Warning(text); | |
444 | ||
445 | for (G4int i=0; i<nofElements; i++) { | |
446 | G4double zOfElement = material->GetElement(i)->GetZ(); | |
447 | G4double massFraction = material->GetFractionVector()[i]; | |
448 | z += zOfElement*massFraction; | |
449 | } | |
450 | } | |
451 | else { | |
452 | z = material->GetZ(); | |
453 | } | |
454 | return z; | |
455 | } |