Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CexmcSetup.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  *
29  * Filename: CexmcSetup.cc
30  *
31  * Description: physical setup
32  *
33  * Version: 1.0
34  * Created: 10.10.2009 23:00:50
35  * Revision: none
36  * Compiler: gcc
37  *
38  * Author: Alexey Radkov (),
39  * Company: PNPI
40  *
41  * =============================================================================
42  */
43 
44 #include <G4GDMLParser.hh>
46 #include <G4SDManager.hh>
47 #include <G4LogicalVolume.hh>
48 #include <G4VPhysicalVolume.hh>
49 #include <G4PhysicalVolumeStore.hh>
50 #include <G4Box.hh>
51 #include <G4LogicalVolumeStore.hh>
52 #include <G4Region.hh>
53 #include <G4RegionStore.hh>
54 #include <G4ProductionCuts.hh>
55 #include <G4VUserPhysicsList.hh>
56 #include "CexmcSetup.hh"
57 #include "CexmcPrimitiveScorer.hh"
58 #include "CexmcTrackPoints.hh"
65 #include "CexmcRunManager.hh"
66 #include "CexmcPhysicsManager.hh"
67 #include "CexmcException.hh"
68 
69 
70 CexmcSetup::CexmcSetup( const G4String & gdmlFile, G4bool validateGDMLFile ) :
71  world( 0 ), gdmlFile( gdmlFile ), validateGDMLFile( validateGDMLFile ),
72  calorimeterRegionInitialized( false ),
73  calorimeterGeometryDataInitialized( false ), monitorVolume( NULL ),
74  vetoCounterVolume( NULL ), calorimeterVolume( NULL ), targetVolume( NULL ),
75  rightVetoCounter( NULL ), rightCalorimeter( NULL )
76 {
77 }
78 
79 
81 {
82  if ( world )
83  return world;
84 
85  G4GDMLParser gdmlParser;
86 
87  gdmlParser.Read( gdmlFile, validateGDMLFile );
88  world = gdmlParser.GetWorldVolume();
89 
90  SetupSpecialVolumes( gdmlParser );
91 
92  ReadTransforms( gdmlParser );
93 
94  ReadRightDetectors();
95 
96  CexmcRunManager * runManager( static_cast< CexmcRunManager * >(
98 
99  runManager->SetupConstructionHook();
100 
101  const CexmcPhysicsManager * physicsManager(
102  dynamic_cast< const CexmcPhysicsManager * >(
103  runManager->GetUserPhysicsList() ) );
104 
105  if ( ! physicsManager )
107 
108  CexmcPhysicsManager * thePhysicsManager(
109  const_cast< CexmcPhysicsManager * >( physicsManager ) );
110  thePhysicsManager->SetupConstructionHook( this );
111 
112  return world;
113 }
114 
115 
116 void CexmcSetup::SetupSpecialVolumes( const G4GDMLParser & gdmlParser )
117 {
119  { NULL };
121 
122  for ( std::vector< G4LogicalVolume * >::const_iterator
123  lvIter( lvs->begin() ); lvIter != lvs->end(); ++lvIter )
124  {
125  G4String volumeName( G4String( ( *lvIter )->GetName() ) );
127  *lvIter ) );
129 
130  for ( G4GDMLAuxListType::const_iterator pair( auxInfo.begin() );
131  pair != auxInfo.end(); ++pair )
132  {
133  CexmcPrimitiveScorer * scorer( NULL );
134  G4String detectorName( "uninitialized" );
135  do
136  {
137  if ( pair->type == "EnergyDepositDetector" )
138  {
139  do
140  {
141  if ( pair->value == "MonitorRole" )
142  {
143  AssertAndAsignDetectorRole( curDetectorRole,
145  scorer = new CexmcSimpleEnergyDeposit(
147  break;
148  }
149  if ( pair->value == "VetoCounterRole" )
150  {
151  AssertAndAsignDetectorRole( curDetectorRole,
155  this );
156  break;
157  }
158  if ( pair->value == "CalorimeterRole" )
159  {
160  AssertAndAsignDetectorRole( curDetectorRole,
162  scorer = new CexmcEnergyDepositInCalorimeter(
164  this );
165  break;
166  }
167  } while ( false );
168  detectorName = CexmcDetectorRoleName[ curDetectorRole ];
169  G4cout << CEXMC_LINE_START "ED Scorer of detector role '" <<
170  detectorName << "' in volume '" << volumeName <<
171  "'" << G4endl;
172  break;
173  }
174  if ( pair->type == "TrackPointsDetector" )
175  {
176  do
177  {
178  if ( pair->value == "MonitorRole" )
179  {
180  AssertAndAsignDetectorRole( curDetectorRole,
182  scorer = new CexmcTrackPoints(
184  break;
185  }
186  if ( pair->value == "VetoCounterRole" )
187  {
188  AssertAndAsignDetectorRole( curDetectorRole,
190  scorer = new CexmcTrackPointsInLeftRightSet(
192  this );
193  break;
194  }
195  if ( pair->value == "CalorimeterRole" )
196  {
197  AssertAndAsignDetectorRole( curDetectorRole,
199  scorer = new CexmcTrackPointsInCalorimeter(
201  this );
202  break;
203  }
204  if ( pair->value == "TargetRole" )
205  {
206  AssertAndAsignDetectorRole( curDetectorRole,
208  scorer = new CexmcTrackPoints(
210  break;
211  }
212  } while ( false );
213  detectorName = CexmcDetectorRoleName[ curDetectorRole ];
214  G4cout << CEXMC_LINE_START "TP Scorer of detector role '" <<
215  detectorName << "' in volume '" << volumeName <<
216  "'" << G4endl;
217  if ( scorer )
218  {
219  CexmcTrackPointsFilter * filter(
220  new CexmcTrackPointsFilter( "trackPoints" ) );
221  scorer->SetFilter( filter );
222  }
223  break;
224  }
225  if ( pair->type == "SensitiveRegion" )
226  {
227  do
228  {
229  if ( pair->value == "CalorimeterRegion" )
230  {
231  G4Region * region( NULL );
232  if ( calorimeterRegionInitialized )
233  {
234  region = G4RegionStore::GetInstance()->
235  GetRegion( CexmcCalorimeterRegionName );
236  }
237  else
238  {
239  region = new G4Region(
241  G4ProductionCuts * cuts(
242  new G4ProductionCuts );
243  G4double defaultProductionCut( 1.0 * mm );
244  const G4VUserPhysicsList * physicsList(
246  GetUserPhysicsList() );
247  if ( physicsList )
248  defaultProductionCut =
249  physicsList->GetDefaultCutValue();
250  cuts->SetProductionCut( defaultProductionCut );
251  region->SetProductionCuts( cuts );
252  calorimeterRegionInitialized = true;
253  }
254  region->AddRootLogicalVolume( *lvIter );
255  break;
256  }
257  } while ( false );
258  G4cout << CEXMC_LINE_START "Sensitive Region for logical "
259  "volume '" << volumeName << "' registered" <<
260  G4endl;
261  break;
262  }
263  if ( pair->type == "SpecialVolume" )
264  {
265  do
266  {
267  if ( pair->value == "Monitor" )
268  {
269  monitorVolume = *lvIter;
270  G4cout << CEXMC_LINE_START "Monitor volume '";
271  break;
272  }
273  if ( pair->value == "VetoCounter" )
274  {
275  vetoCounterVolume = *lvIter;
276  G4cout << CEXMC_LINE_START "VetoCounter volume '";
277  break;
278  }
279  if ( pair->value == "Calorimeter" )
280  {
281  calorimeterVolume = *lvIter;
282  G4cout << CEXMC_LINE_START "Calorimeter volume '";
283  ReadCalorimeterGeometryData( *lvIter );
284  calorimeterGeometryDataInitialized = true;
285  break;
286  }
287  if ( pair->value == "Target" )
288  {
289  targetVolume = *lvIter;
290  G4cout << CEXMC_LINE_START "Target volume '";
291  break;
292  }
293  } while ( false );
294  G4cout << volumeName << "' registered" << G4endl;
295  break;
296  }
297  }
298  while ( false );
299 
300  if ( scorer )
301  {
302  /* curDetectorRole must be intact when scorer is not NULL */
303  if ( ! detector[ curDetectorRole ] )
304  {
305  detector[ curDetectorRole ] =
306  new G4MultiFunctionalDetector( detectorName );
307  }
308  detector[ curDetectorRole ]->RegisterPrimitive( scorer );
309  /* now that scorer has initialized pointer to its detector, its
310  * messenger's path shall be properly initialized as well */
311  scorer->InitializeMessenger();
312  /* NB: logical volumes in GDML file may not have multiple
313  * detector roles: for example volume Monitor may have only one
314  * role MonitorRole. This restriction arises from that fact that
315  * a logical volume may contain only one sensitive detector. */
316  ( *lvIter )->SetSensitiveDetector(
317  detector[ curDetectorRole ] );
318  }
319  }
320  }
321 
322  if ( ! calorimeterRegionInitialized )
324 
325  if ( ! calorimeterGeometryDataInitialized )
327 
328  for ( G4int i( 0 ); i < CexmcNumberOfDetectorRoles; ++i )
329  {
330  if ( detector[ i ] )
331  G4SDManager::GetSDMpointer()->AddNewDetector( detector[ i ] );
332  }
333 }
334 
335 
336 void CexmcSetup::ReadTransforms( const G4GDMLParser & gdmlParser )
337 {
338  G4ThreeVector position( gdmlParser.GetPosition( "TargetPos" ) );
339  G4ThreeVector rotation( gdmlParser.GetRotation( "TargetRot" ) );
340  G4RotationMatrix rm;
341 
342  RotateMatrix( rotation, rm );
343  targetTransform.SetNetTranslation( position );
344  targetTransform.SetNetRotation( rm );
345 
346  position = gdmlParser.GetPosition( "CalorimeterLeftPos" );
347  rotation = gdmlParser.GetRotation( "CalorimeterLeftRot" );
348  rm = G4RotationMatrix();
349  RotateMatrix( rotation, rm );
350  calorimeterLeftTransform.SetNetTranslation( position );
351  calorimeterLeftTransform.SetNetRotation( rm );
352 
353  position = gdmlParser.GetPosition( "CalorimeterRightPos" );
354  rotation = gdmlParser.GetRotation( "CalorimeterRightRot" );
355  rm = G4RotationMatrix();
356  RotateMatrix( rotation, rm );
357  calorimeterRightTransform.SetNetTranslation( position );
358  calorimeterRightTransform.SetNetRotation( rm );
359 }
360 
361 
362 void CexmcSetup::ReadCalorimeterGeometryData(
363  const G4LogicalVolume * lVolume )
364 {
365  if ( lVolume->GetNoDaughters() == 0 )
367 
368  G4VPhysicalVolume * pVolume( lVolume->GetDaughter( 0 ) );
369  EAxis axis;
370  G4double width;
371  G4double offset;
372  G4bool consuming;
373 
374  if ( ! pVolume )
376 
377  if ( pVolume->IsReplicated() )
378  {
379  pVolume->GetReplicationData( axis,
380  calorimeterGeometry.nCrystalsInColumn,
381  width, offset, consuming );
382  }
383 
384  lVolume = pVolume->GetLogicalVolume();
385 
386  if ( lVolume->GetNoDaughters() == 0 )
388 
389  pVolume = lVolume->GetDaughter( 0 );
390 
391  if ( ! pVolume )
393 
394  if ( pVolume->IsReplicated() )
395  {
396  pVolume->GetReplicationData( axis, calorimeterGeometry.nCrystalsInRow,
397  width, offset, consuming );
398  }
399 
400  lVolume = pVolume->GetLogicalVolume();
401 
402  /* NB: this is not necessarily a crystal itself as far as crystals can be
403  * wrapped in paper and other materials, but this is what reconstructor and
404  * digitizers really need */
405  G4Box * crystalBox( dynamic_cast< G4Box * >( lVolume->GetSolid() ) );
406 
407  if ( ! crystalBox )
409 
410  calorimeterGeometry.crystalWidth = crystalBox->GetXHalfLength() * 2;
411  calorimeterGeometry.crystalHeight = crystalBox->GetYHalfLength() * 2;
412  calorimeterGeometry.crystalLength = crystalBox->GetZHalfLength() * 2;
413 }
414 
415 
417  G4int & row, G4int & column, G4ThreeVector & dst ) const
418 {
419  G4int nCrystalsInColumn( calorimeterGeometry.nCrystalsInColumn );
420  G4int nCrystalsInRow( calorimeterGeometry.nCrystalsInRow );
421  G4double crystalWidth( calorimeterGeometry.crystalWidth );
422  G4double crystalHeight( calorimeterGeometry.crystalHeight );
423 
424  row = G4int( ( src.y() + crystalHeight * nCrystalsInColumn / 2 ) /
425  crystalHeight );
426  column = G4int( ( src.x() + crystalWidth * nCrystalsInRow / 2 ) /
427  crystalWidth );
428  G4double xInCalorimeterOffset(
429  ( G4double( column ) - G4double( nCrystalsInRow ) / 2 ) *
430  crystalWidth + crystalWidth / 2 );
431  G4double yInCalorimeterOffset(
432  ( G4double( row ) - G4double( nCrystalsInColumn ) / 2 ) *
433  crystalHeight + crystalHeight / 2 );
434  dst.setX( src.x() - xInCalorimeterOffset );
435  dst.setY( src.y() - yInCalorimeterOffset );
436 }
437 
438 
439 void CexmcSetup::ReadRightDetectors( void )
440 {
442 
443  for ( std::vector< G4VPhysicalVolume * >::const_iterator k( pvs->begin() );
444  k != pvs->end(); ++k )
445  {
446  /* FIXME: it would be more reasonable to find detectors from volumes
447  * tagged with 'EnergyDepositDetector' or 'TrackPointsDetector', and not
448  * from volumes tagged with 'SpecialVolume' as it is done here. However
449  * in case of calorimeters the role of detectors are played by crystal
450  * volumes, not the calorimeters themselves, but only calorimeters can
451  * hold information about their left or right positions! Thus, following
452  * considerations of convenience, right detectors for all detector roles
453  * are chosen from volumes tagged with 'SpecialVolume' */
454  do
455  {
456  if ( ( *k )->GetLogicalVolume() == vetoCounterVolume )
457  {
458  if ( ( *k )->GetName().contains( "Right" ) )
459  rightVetoCounter = *k;
460  break;
461  }
462  if ( ( *k )->GetLogicalVolume() == calorimeterVolume )
463  {
464  if ( ( *k )->GetName().contains( "Right" ) )
465  rightCalorimeter = *k;
466  break;
467  }
468  } while ( false );
469  }
470 }
471 
472 
473 void CexmcSetup::AssertAndAsignDetectorRole( CexmcDetectorRole & detectorRole,
475 {
476  if ( detectorRole != CexmcNumberOfDetectorRoles && detectorRole != value )
478 
479  detectorRole = value;
480 }
481 
482 
483 void CexmcSetup::RotateMatrix( const G4ThreeVector & rot,
484  G4RotationMatrix & rm )
485 {
486  rm.rotateX( rot.x() );
487  rm.rotateY( rot.y() );
488  rm.rotateZ( rot.z() );
489 }
490