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