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