Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 /* 26 /* 27 * =========================================== 27 * ============================================================================= 28 * 28 * 29 * Filename: CexmcSetup.cc 29 * Filename: CexmcSetup.cc 30 * 30 * 31 * Description: physical setup 31 * Description: physical setup 32 * 32 * 33 * Version: 1.0 33 * Version: 1.0 34 * Created: 10.10.2009 23:00:50 34 * Created: 10.10.2009 23:00:50 35 * Revision: none 35 * Revision: none 36 * Compiler: gcc 36 * Compiler: gcc 37 * 37 * 38 * Author: Alexey Radkov (), 38 * Author: Alexey Radkov (), 39 * Company: PNPI 39 * Company: PNPI 40 * 40 * 41 * =========================================== 41 * ============================================================================= 42 */ 42 */ 43 43 44 #include <G4GDMLParser.hh> 44 #include <G4GDMLParser.hh> 45 #include <G4MultiFunctionalDetector.hh> 45 #include <G4MultiFunctionalDetector.hh> 46 #include <G4SDManager.hh> 46 #include <G4SDManager.hh> 47 #include <G4LogicalVolume.hh> 47 #include <G4LogicalVolume.hh> 48 #include <G4VPhysicalVolume.hh> 48 #include <G4VPhysicalVolume.hh> 49 #include <G4PhysicalVolumeStore.hh> 49 #include <G4PhysicalVolumeStore.hh> 50 #include <G4Box.hh> 50 #include <G4Box.hh> 51 #include <G4LogicalVolumeStore.hh> 51 #include <G4LogicalVolumeStore.hh> 52 #include <G4Region.hh> 52 #include <G4Region.hh> 53 #include <G4RegionStore.hh> 53 #include <G4RegionStore.hh> 54 #include <G4ProductionCuts.hh> 54 #include <G4ProductionCuts.hh> 55 #include <G4VUserPhysicsList.hh> 55 #include <G4VUserPhysicsList.hh> 56 #include <G4SystemOfUnits.hh> 56 #include <G4SystemOfUnits.hh> 57 #include "CexmcSetup.hh" 57 #include "CexmcSetup.hh" 58 #include "CexmcPrimitiveScorer.hh" 58 #include "CexmcPrimitiveScorer.hh" 59 #include "CexmcTrackPoints.hh" 59 #include "CexmcTrackPoints.hh" 60 #include "CexmcTrackPointsInLeftRightSet.hh" 60 #include "CexmcTrackPointsInLeftRightSet.hh" 61 #include "CexmcTrackPointsInCalorimeter.hh" 61 #include "CexmcTrackPointsInCalorimeter.hh" 62 #include "CexmcTrackPointsFilter.hh" 62 #include "CexmcTrackPointsFilter.hh" 63 #include "CexmcSimpleEnergyDeposit.hh" 63 #include "CexmcSimpleEnergyDeposit.hh" 64 #include "CexmcEnergyDepositInLeftRightSet.hh" 64 #include "CexmcEnergyDepositInLeftRightSet.hh" 65 #include "CexmcEnergyDepositInCalorimeter.hh" 65 #include "CexmcEnergyDepositInCalorimeter.hh" 66 #include "CexmcRunManager.hh" 66 #include "CexmcRunManager.hh" 67 #include "CexmcPhysicsManager.hh" 67 #include "CexmcPhysicsManager.hh" 68 #include "CexmcException.hh" 68 #include "CexmcException.hh" 69 69 70 70 71 CexmcSetup::CexmcSetup( const G4String & gdml 71 CexmcSetup::CexmcSetup( const G4String & gdmlFile_, 72 G4bool validateGDMLFi 72 G4bool validateGDMLFile_ ) : 73 world( 0 ), gdmlFile( gdmlFile_ ), validat 73 world( 0 ), gdmlFile( gdmlFile_ ), validateGDMLFile( validateGDMLFile_ ), 74 calorimeterRegionInitialized( false ), 74 calorimeterRegionInitialized( false ), 75 calorimeterGeometryDataInitialized( false 75 calorimeterGeometryDataInitialized( false ), monitorVolume( NULL ), 76 vetoCounterVolume( NULL ), calorimeterVolu 76 vetoCounterVolume( NULL ), calorimeterVolume( NULL ), targetVolume( NULL ), 77 rightVetoCounter( NULL ), rightCalorimeter 77 rightVetoCounter( NULL ), rightCalorimeter( NULL ) 78 { 78 { 79 } 79 } 80 80 81 81 82 G4VPhysicalVolume * CexmcSetup::Construct( vo 82 G4VPhysicalVolume * CexmcSetup::Construct( void ) 83 { 83 { 84 if ( world ) 84 if ( world ) 85 return world; 85 return world; 86 86 87 G4GDMLParser gdmlParser; 87 G4GDMLParser gdmlParser; 88 88 89 gdmlParser.Read( gdmlFile, validateGDMLFil 89 gdmlParser.Read( gdmlFile, validateGDMLFile ); 90 world = gdmlParser.GetWorldVolume(); 90 world = gdmlParser.GetWorldVolume(); 91 91 92 SetupSpecialVolumes( gdmlParser ); 92 SetupSpecialVolumes( gdmlParser ); 93 93 94 ReadTransforms( gdmlParser ); 94 ReadTransforms( gdmlParser ); 95 95 96 ReadRightDetectors(); 96 ReadRightDetectors(); 97 97 98 CexmcRunManager * runManager( static_cast 98 CexmcRunManager * runManager( static_cast< CexmcRunManager * >( 99 G4 99 G4RunManager::GetRunManager() ) ); 100 100 101 runManager->SetupConstructionHook(); 101 runManager->SetupConstructionHook(); 102 102 103 const CexmcPhysicsManager * physicsManage 103 const CexmcPhysicsManager * physicsManager( 104 dynamic_cast< const CexmcPhysicsMa 104 dynamic_cast< const CexmcPhysicsManager * >( 105 runMan 105 runManager->GetUserPhysicsList() ) ); 106 106 107 if ( ! physicsManager ) 107 if ( ! physicsManager ) 108 throw CexmcException( CexmcWeirdExcept 108 throw CexmcException( CexmcWeirdException ); 109 109 110 CexmcPhysicsManager * thePhysicsMan 110 CexmcPhysicsManager * thePhysicsManager( 111 const_cast< CexmcPhysicsManager * 111 const_cast< CexmcPhysicsManager * >( physicsManager ) ); 112 thePhysicsManager->SetupConstructionHook( 112 thePhysicsManager->SetupConstructionHook( this ); 113 113 114 return world; 114 return world; 115 } 115 } 116 116 117 117 118 void CexmcSetup::SetupSpecialVolumes( const G 118 void CexmcSetup::SetupSpecialVolumes( const G4GDMLParser & gdmlParser ) 119 { 119 { 120 G4MultiFunctionalDetector * detector[ Ce 120 G4MultiFunctionalDetector * detector[ CexmcNumberOfDetectorRoles ] = 121 121 { NULL }; 122 const G4LogicalVolumeStore * lvs( G4Logic 122 const G4LogicalVolumeStore * lvs( G4LogicalVolumeStore::GetInstance() ); 123 123 124 for ( std::vector< G4LogicalVolume * >::co 124 for ( std::vector< G4LogicalVolume * >::const_iterator 125 lvIter( lvs->begin() ) 125 lvIter( lvs->begin() ); lvIter != lvs->end(); ++lvIter ) 126 { 126 { 127 G4String volumeName( G4Strin 127 G4String volumeName( G4String( ( *lvIter )->GetName() ) ); 128 G4GDMLAuxListType auxInfo( gdmlParser 128 G4GDMLAuxListType auxInfo( gdmlParser.GetVolumeAuxiliaryInformation( 129 129 *lvIter ) ); 130 CexmcDetectorRole curDetectorRole( Ce 130 CexmcDetectorRole curDetectorRole( CexmcNumberOfDetectorRoles ); 131 131 132 for ( G4GDMLAuxListType::const_iterato 132 for ( G4GDMLAuxListType::const_iterator pair( auxInfo.begin() ); 133 133 pair != auxInfo.end(); ++pair ) 134 { 134 { 135 CexmcPrimitiveScorer * scorer( NU 135 CexmcPrimitiveScorer * scorer( NULL ); 136 G4String detectorNa 136 G4String detectorName( "uninitialized" ); 137 do 137 do 138 { 138 { 139 if ( pair->type == "EnergyDepo 139 if ( pair->type == "EnergyDepositDetector" ) 140 { 140 { 141 do 141 do 142 { 142 { 143 if ( pair->value == "M 143 if ( pair->value == "MonitorRole" ) 144 { 144 { 145 AssertAndAsignDete 145 AssertAndAsignDetectorRole( curDetectorRole, 146 146 CexmcMonitorDetectorRole ); 147 scorer = new Cexmc 147 scorer = new CexmcSimpleEnergyDeposit( 148 CexmcDetec 148 CexmcDetectorTypeName[ CexmcEDDetector ] ); 149 break; 149 break; 150 } 150 } 151 if ( pair->value == "V 151 if ( pair->value == "VetoCounterRole" ) 152 { 152 { 153 AssertAndAsignDete 153 AssertAndAsignDetectorRole( curDetectorRole, 154 154 CexmcVetoCounterDetectorRole ); 155 scorer = new Cexmc 155 scorer = new CexmcEnergyDepositInLeftRightSet( 156 CexmcDetec 156 CexmcDetectorTypeName[ CexmcEDDetector ], 157 this ); 157 this ); 158 break; 158 break; 159 } 159 } 160 if ( pair->value == "C 160 if ( pair->value == "CalorimeterRole" ) 161 { 161 { 162 AssertAndAsignDete 162 AssertAndAsignDetectorRole( curDetectorRole, 163 163 CexmcCalorimeterDetectorRole ); 164 scorer = new Cexmc 164 scorer = new CexmcEnergyDepositInCalorimeter( 165 CexmcDetec 165 CexmcDetectorTypeName[ CexmcEDDetector ], 166 this ); 166 this ); 167 break; 167 break; 168 } 168 } 169 } while ( false ); 169 } while ( false ); 170 detectorName = CexmcDetect 170 detectorName = CexmcDetectorRoleName[ curDetectorRole ]; 171 G4cout << CEXMC_LINE_START 171 G4cout << CEXMC_LINE_START "ED Scorer of detector role '" << 172 detectorName << 172 detectorName << "' in volume '" << volumeName << 173 "'" << G4endl; 173 "'" << G4endl; 174 break; 174 break; 175 } 175 } 176 if ( pair->type == "TrackPoint 176 if ( pair->type == "TrackPointsDetector" ) 177 { 177 { 178 do 178 do 179 { 179 { 180 if ( pair->value == "M 180 if ( pair->value == "MonitorRole" ) 181 { 181 { 182 AssertAndAsignDete 182 AssertAndAsignDetectorRole( curDetectorRole, 183 183 CexmcMonitorDetectorRole ); 184 scorer = new Cexmc 184 scorer = new CexmcTrackPoints( 185 CexmcDetec 185 CexmcDetectorTypeName[ CexmcTPDetector ] ); 186 break; 186 break; 187 } 187 } 188 if ( pair->value == "V 188 if ( pair->value == "VetoCounterRole" ) 189 { 189 { 190 AssertAndAsignDete 190 AssertAndAsignDetectorRole( curDetectorRole, 191 191 CexmcVetoCounterDetectorRole ); 192 scorer = new Cexmc 192 scorer = new CexmcTrackPointsInLeftRightSet( 193 CexmcDetec 193 CexmcDetectorTypeName[ CexmcTPDetector ], 194 this ); 194 this ); 195 break; 195 break; 196 } 196 } 197 if ( pair->value == "C 197 if ( pair->value == "CalorimeterRole" ) 198 { 198 { 199 AssertAndAsignDete 199 AssertAndAsignDetectorRole( curDetectorRole, 200 200 CexmcCalorimeterDetectorRole ); 201 scorer = new Cexmc 201 scorer = new CexmcTrackPointsInCalorimeter( 202 CexmcDetec 202 CexmcDetectorTypeName[ CexmcTPDetector ], 203 this ); 203 this ); 204 break; 204 break; 205 } 205 } 206 if ( pair->value == "T 206 if ( pair->value == "TargetRole" ) 207 { 207 { 208 AssertAndAsignDete 208 AssertAndAsignDetectorRole( curDetectorRole, 209 209 CexmcTargetDetectorRole ); 210 scorer = new Cexmc 210 scorer = new CexmcTrackPoints( 211 CexmcDetec 211 CexmcDetectorTypeName[ CexmcTPDetector ] ); 212 break; 212 break; 213 } 213 } 214 } while ( false ); 214 } while ( false ); 215 detectorName = CexmcDetect 215 detectorName = CexmcDetectorRoleName[ curDetectorRole ]; 216 G4cout << CEXMC_LINE_START 216 G4cout << CEXMC_LINE_START "TP Scorer of detector role '" << 217 detectorName << 217 detectorName << "' in volume '" << volumeName << 218 "'" << G4endl; 218 "'" << G4endl; 219 if ( scorer ) 219 if ( scorer ) 220 { 220 { 221 CexmcTrackPointsFilter 221 CexmcTrackPointsFilter * filter( 222 new CexmcTrac 222 new CexmcTrackPointsFilter( "trackPoints" ) ); 223 scorer->SetFilter( fil 223 scorer->SetFilter( filter ); 224 } 224 } 225 break; 225 break; 226 } 226 } 227 if ( pair->type == "SensitiveR 227 if ( pair->type == "SensitiveRegion" ) 228 { 228 { 229 do 229 do 230 { 230 { 231 if ( pair->value == "C 231 if ( pair->value == "CalorimeterRegion" ) 232 { 232 { 233 G4Region * region 233 G4Region * region( NULL ); 234 if ( calorimeterRe 234 if ( calorimeterRegionInitialized ) 235 { 235 { 236 region = G4Reg 236 region = G4RegionStore::GetInstance()-> 237 GetReg 237 GetRegion( CexmcCalorimeterRegionName ); 238 } 238 } 239 else 239 else 240 { 240 { 241 region = new G 241 region = new G4Region( 242 242 CexmcCalorimeterRegionName ); 243 G4ProductionCu 243 G4ProductionCuts * cuts( 244 244 new G4ProductionCuts ); 245 G4double defa 245 G4double defaultProductionCut( 1.0 * mm ); 246 const G4VUserP 246 const G4VUserPhysicsList * physicsList( 247 G4 247 G4RunManager::GetRunManager()-> 248 248 GetUserPhysicsList() ); 249 if ( physicsLi 249 if ( physicsList ) 250 defaultPro 250 defaultProductionCut = 251 ph 251 physicsList->GetDefaultCutValue(); 252 cuts->SetProdu 252 cuts->SetProductionCut( defaultProductionCut ); 253 region->SetPro 253 region->SetProductionCuts( cuts ); 254 calorimeterReg 254 calorimeterRegionInitialized = true; 255 } 255 } 256 region->AddRootLog 256 region->AddRootLogicalVolume( *lvIter ); 257 break; 257 break; 258 } 258 } 259 } while ( false ); 259 } while ( false ); 260 G4cout << CEXMC_LINE_START 260 G4cout << CEXMC_LINE_START "Sensitive Region for logical " 261 "volume '" << v 261 "volume '" << volumeName << "' registered" << 262 G4endl; 262 G4endl; 263 break; 263 break; 264 } 264 } 265 if ( pair->type == "SpecialVol 265 if ( pair->type == "SpecialVolume" ) 266 { 266 { 267 do 267 do 268 { 268 { 269 if ( pair->value == "M 269 if ( pair->value == "Monitor" ) 270 { 270 { 271 monitorVolume = *l 271 monitorVolume = *lvIter; 272 G4cout << CEXMC_LI 272 G4cout << CEXMC_LINE_START "Monitor volume '"; 273 break; 273 break; 274 } 274 } 275 if ( pair->value == "V 275 if ( pair->value == "VetoCounter" ) 276 { 276 { 277 vetoCounterVolume 277 vetoCounterVolume = *lvIter; 278 G4cout << CEXMC_LI 278 G4cout << CEXMC_LINE_START "VetoCounter volume '"; 279 break; 279 break; 280 } 280 } 281 if ( pair->value == "C 281 if ( pair->value == "Calorimeter" ) 282 { 282 { 283 calorimeterVolume 283 calorimeterVolume = *lvIter; 284 G4cout << CEXMC_LI 284 G4cout << CEXMC_LINE_START "Calorimeter volume '"; 285 ReadCalorimeterGeo 285 ReadCalorimeterGeometryData( *lvIter ); 286 calorimeterGeometr 286 calorimeterGeometryDataInitialized = true; 287 break; 287 break; 288 } 288 } 289 if ( pair->value == "T 289 if ( pair->value == "Target" ) 290 { 290 { 291 targetVolume = *lv 291 targetVolume = *lvIter; 292 G4cout << CEXMC_LI 292 G4cout << CEXMC_LINE_START "Target volume '"; 293 break; 293 break; 294 } 294 } 295 } while ( false ); 295 } while ( false ); 296 G4cout << volumeName << "' 296 G4cout << volumeName << "' registered" << G4endl; 297 break; 297 break; 298 } 298 } 299 } 299 } 300 while ( false ); 300 while ( false ); 301 301 302 if ( scorer ) 302 if ( scorer ) 303 { 303 { 304 /* curDetectorRole must be int 304 /* curDetectorRole must be intact when scorer is not NULL */ 305 if ( ! detector[ curDetectorRo 305 if ( ! detector[ curDetectorRole ] ) 306 { 306 { 307 detector[ curDetectorRole 307 detector[ curDetectorRole ] = 308 new G4MultiFun 308 new G4MultiFunctionalDetector( detectorName ); 309 } 309 } 310 detector[ curDetectorRole ]->R 310 detector[ curDetectorRole ]->RegisterPrimitive( scorer ); 311 /* now that scorer has initial 311 /* now that scorer has initialized pointer to its detector, its 312 * messenger's path shall be p 312 * messenger's path shall be properly initialized as well */ 313 scorer->InitializeMessenger(); 313 scorer->InitializeMessenger(); 314 /* NB: logical volumes in GDML 314 /* NB: logical volumes in GDML file may not have multiple 315 * detector roles: for example 315 * detector roles: for example volume Monitor may have only one 316 * role MonitorRole. This rest 316 * role MonitorRole. This restriction arises from that fact that 317 * a logical volume may contai 317 * a logical volume may contain only one sensitive detector. */ 318 ( *lvIter )->SetSensitiveDetec 318 ( *lvIter )->SetSensitiveDetector( 319 319 detector[ curDetectorRole ] ); 320 } 320 } 321 } 321 } 322 } 322 } 323 323 324 if ( ! calorimeterRegionInitialized ) 324 if ( ! calorimeterRegionInitialized ) 325 throw CexmcException( CexmcCalorimeter 325 throw CexmcException( CexmcCalorimeterRegionNotInitialized ); 326 326 327 if ( ! calorimeterGeometryDataInitialized 327 if ( ! calorimeterGeometryDataInitialized ) 328 throw CexmcException( CexmcCalorimeter 328 throw CexmcException( CexmcCalorimeterGeometryDataNotInitialized ); 329 329 330 for ( G4int i( 0 ); i < CexmcNumberOfDete 330 for ( G4int i( 0 ); i < CexmcNumberOfDetectorRoles; ++i ) 331 { 331 { 332 if ( detector[ i ] ) 332 if ( detector[ i ] ) 333 G4SDManager::GetSDMpointer()->AddN 333 G4SDManager::GetSDMpointer()->AddNewDetector( detector[ i ] ); 334 } 334 } 335 } 335 } 336 336 337 337 338 void CexmcSetup::ReadTransforms( const G4GDML 338 void CexmcSetup::ReadTransforms( const G4GDMLParser & gdmlParser ) 339 { 339 { 340 G4ThreeVector position( gdmlParser.Get 340 G4ThreeVector position( gdmlParser.GetPosition( "TargetPos" ) ); 341 G4ThreeVector rotation( gdmlParser.Get 341 G4ThreeVector rotation( gdmlParser.GetRotation( "TargetRot" ) ); 342 G4RotationMatrix rm; 342 G4RotationMatrix rm; 343 343 344 RotateMatrix( rotation, rm ); 344 RotateMatrix( rotation, rm ); 345 targetTransform.SetNetTranslation( positio 345 targetTransform.SetNetTranslation( position ); 346 targetTransform.SetNetRotation( rm ); 346 targetTransform.SetNetRotation( rm ); 347 347 348 position = gdmlParser.GetPosition( "Calori 348 position = gdmlParser.GetPosition( "CalorimeterLeftPos" ); 349 rotation = gdmlParser.GetRotation( "Calori 349 rotation = gdmlParser.GetRotation( "CalorimeterLeftRot" ); 350 rm = G4RotationMatrix(); 350 rm = G4RotationMatrix(); 351 RotateMatrix( rotation, rm ); 351 RotateMatrix( rotation, rm ); 352 calorimeterLeftTransform.SetNetTranslation 352 calorimeterLeftTransform.SetNetTranslation( position ); 353 calorimeterLeftTransform.SetNetRotation( r 353 calorimeterLeftTransform.SetNetRotation( rm ); 354 354 355 position = gdmlParser.GetPosition( "Calori 355 position = gdmlParser.GetPosition( "CalorimeterRightPos" ); 356 rotation = gdmlParser.GetRotation( "Calori 356 rotation = gdmlParser.GetRotation( "CalorimeterRightRot" ); 357 rm = G4RotationMatrix(); 357 rm = G4RotationMatrix(); 358 RotateMatrix( rotation, rm ); 358 RotateMatrix( rotation, rm ); 359 calorimeterRightTransform.SetNetTranslatio 359 calorimeterRightTransform.SetNetTranslation( position ); 360 calorimeterRightTransform.SetNetRotation( 360 calorimeterRightTransform.SetNetRotation( rm ); 361 } 361 } 362 362 363 363 364 void CexmcSetup::ReadCalorimeterGeometryData( 364 void CexmcSetup::ReadCalorimeterGeometryData( 365 co 365 const G4LogicalVolume * lVolume ) 366 { 366 { 367 if ( lVolume->GetNoDaughters() == 0 ) 367 if ( lVolume->GetNoDaughters() == 0 ) 368 throw CexmcException( CexmcIncompatibl 368 throw CexmcException( CexmcIncompatibleGeometry ); 369 369 370 G4VPhysicalVolume * pVolume( lVolume->Get 370 G4VPhysicalVolume * pVolume( lVolume->GetDaughter( 0 ) ); 371 EAxis axis; 371 EAxis axis; 372 G4double width; 372 G4double width; 373 G4double offset; 373 G4double offset; 374 G4bool consuming; 374 G4bool consuming; 375 375 376 if ( ! pVolume ) 376 if ( ! pVolume ) 377 throw CexmcException( CexmcIncompatibl 377 throw CexmcException( CexmcIncompatibleGeometry ); 378 378 379 if ( pVolume->IsReplicated() ) 379 if ( pVolume->IsReplicated() ) 380 { 380 { 381 pVolume->GetReplicationData( axis, 381 pVolume->GetReplicationData( axis, 382 calorimet 382 calorimeterGeometry.nCrystalsInColumn, 383 width, of 383 width, offset, consuming ); 384 } 384 } 385 385 386 lVolume = pVolume->GetLogicalVolume(); 386 lVolume = pVolume->GetLogicalVolume(); 387 387 388 if ( lVolume->GetNoDaughters() == 0 ) 388 if ( lVolume->GetNoDaughters() == 0 ) 389 throw CexmcException( CexmcIncompatibl 389 throw CexmcException( CexmcIncompatibleGeometry ); 390 390 391 pVolume = lVolume->GetDaughter( 0 ); 391 pVolume = lVolume->GetDaughter( 0 ); 392 392 393 if ( ! pVolume ) 393 if ( ! pVolume ) 394 throw CexmcException( CexmcIncompatibl 394 throw CexmcException( CexmcIncompatibleGeometry ); 395 395 396 if ( pVolume->IsReplicated() ) 396 if ( pVolume->IsReplicated() ) 397 { 397 { 398 pVolume->GetReplicationData( axis, cal 398 pVolume->GetReplicationData( axis, calorimeterGeometry.nCrystalsInRow, 399 width, of 399 width, offset, consuming ); 400 } 400 } 401 401 402 lVolume = pVolume->GetLogicalVolume(); 402 lVolume = pVolume->GetLogicalVolume(); 403 403 404 /* NB: this is not necessarily a crystal i 404 /* NB: this is not necessarily a crystal itself as far as crystals can be 405 * wrapped in paper and other materials, b 405 * wrapped in paper and other materials, but this is what reconstructor and 406 * digitizers really need */ 406 * digitizers really need */ 407 G4Box * crystalBox( dynamic_cast< G4Box * 407 G4Box * crystalBox( dynamic_cast< G4Box * >( lVolume->GetSolid() ) ); 408 408 409 if ( ! crystalBox ) 409 if ( ! crystalBox ) 410 throw CexmcException( CexmcIncompatibl 410 throw CexmcException( CexmcIncompatibleGeometry ); 411 411 412 calorimeterGeometry.crystalWidth = crystal 412 calorimeterGeometry.crystalWidth = crystalBox->GetXHalfLength() * 2; 413 calorimeterGeometry.crystalHeight = crysta 413 calorimeterGeometry.crystalHeight = crystalBox->GetYHalfLength() * 2; 414 calorimeterGeometry.crystalLength = crysta 414 calorimeterGeometry.crystalLength = crystalBox->GetZHalfLength() * 2; 415 } 415 } 416 416 417 417 418 void CexmcSetup::ConvertToCrystalGeometry( co 418 void CexmcSetup::ConvertToCrystalGeometry( const G4ThreeVector & src, 419 G4int & row, G4int & col 419 G4int & row, G4int & column, G4ThreeVector & dst ) const 420 { 420 { 421 G4int nCrystalsInColumn( calorimeterGe 421 G4int nCrystalsInColumn( calorimeterGeometry.nCrystalsInColumn ); 422 G4int nCrystalsInRow( calorimeterGeome 422 G4int nCrystalsInRow( calorimeterGeometry.nCrystalsInRow ); 423 G4double crystalWidth( calorimeterGeometr 423 G4double crystalWidth( calorimeterGeometry.crystalWidth ); 424 G4double crystalHeight( calorimeterGeomet 424 G4double crystalHeight( calorimeterGeometry.crystalHeight ); 425 425 426 row = G4int( ( src.y() + crystalHeight * n 426 row = G4int( ( src.y() + crystalHeight * nCrystalsInColumn / 2 ) / 427 crystalHeight ); 427 crystalHeight ); 428 column = G4int( ( src.x() + crystalWidth * 428 column = G4int( ( src.x() + crystalWidth * nCrystalsInRow / 2 ) / 429 crystalWidth ); 429 crystalWidth ); 430 G4double xInCalorimeterOffset( 430 G4double xInCalorimeterOffset( 431 ( G4double( column ) - G4d 431 ( G4double( column ) - G4double( nCrystalsInRow ) / 2 ) * 432 cr 432 crystalWidth + crystalWidth / 2 ); 433 G4double yInCalorimeterOffset( 433 G4double yInCalorimeterOffset( 434 ( G4double( row ) - G4doub 434 ( G4double( row ) - G4double( nCrystalsInColumn ) / 2 ) * 435 cr 435 crystalHeight + crystalHeight / 2 ); 436 dst.setX( src.x() - xInCalorimeterOffset ) 436 dst.setX( src.x() - xInCalorimeterOffset ); 437 dst.setY( src.y() - yInCalorimeterOffset ) 437 dst.setY( src.y() - yInCalorimeterOffset ); 438 } 438 } 439 439 440 440 441 void CexmcSetup::ReadRightDetectors( void ) 441 void CexmcSetup::ReadRightDetectors( void ) 442 { 442 { 443 G4PhysicalVolumeStore * pvs( G4PhysicalVo 443 G4PhysicalVolumeStore * pvs( G4PhysicalVolumeStore::GetInstance() ); 444 444 445 for ( std::vector< G4VPhysicalVolume * >:: 445 for ( std::vector< G4VPhysicalVolume * >::const_iterator k( pvs->begin() ); 446 446 k != pvs->end(); ++k ) 447 { 447 { 448 /* FIXME: it would be more reasonable 448 /* FIXME: it would be more reasonable to find detectors from volumes 449 * tagged with 'EnergyDepositDetector' 449 * tagged with 'EnergyDepositDetector' or 'TrackPointsDetector', and not 450 * from volumes tagged with 'SpecialVo 450 * from volumes tagged with 'SpecialVolume' as it is done here. However 451 * in case of calorimeters the role of 451 * in case of calorimeters the role of detectors are played by crystal 452 * volumes, not the calorimeters thems 452 * volumes, not the calorimeters themselves, but only calorimeters can 453 * hold information about their left o 453 * hold information about their left or right positions! Thus, following 454 * considerations of convenience, righ 454 * considerations of convenience, right detectors for all detector roles 455 * are chosen from volumes tagged with 455 * are chosen from volumes tagged with 'SpecialVolume' */ 456 do 456 do 457 { 457 { 458 if ( ( *k )->GetLogicalVolume() == 458 if ( ( *k )->GetLogicalVolume() == vetoCounterVolume ) 459 { 459 { 460 if ( G4StrUtil::contains(( *k << 460 if ( ( *k )->GetName().contains( "Right" ) ) 461 rightVetoCounter = *k; 461 rightVetoCounter = *k; 462 break; 462 break; 463 } 463 } 464 if ( ( *k )->GetLogicalVolume() == 464 if ( ( *k )->GetLogicalVolume() == calorimeterVolume ) 465 { 465 { 466 if ( G4StrUtil::contains(( *k << 466 if ( ( *k )->GetName().contains( "Right" ) ) 467 rightCalorimeter = *k; 467 rightCalorimeter = *k; 468 break; 468 break; 469 } 469 } 470 } while ( false ); 470 } while ( false ); 471 } 471 } 472 } 472 } 473 473 474 474 475 void CexmcSetup::AssertAndAsignDetectorRole( 475 void CexmcSetup::AssertAndAsignDetectorRole( CexmcDetectorRole & detectorRole, 476 476 CexmcDetectorRole value ) 477 { 477 { 478 if ( detectorRole != CexmcNumberOfDetector 478 if ( detectorRole != CexmcNumberOfDetectorRoles && detectorRole != value ) 479 throw CexmcException( CexmcMultipleDet 479 throw CexmcException( CexmcMultipleDetectorRoles ); 480 480 481 detectorRole = value; 481 detectorRole = value; 482 } 482 } 483 483 484 484 485 void CexmcSetup::RotateMatrix( const G4ThreeV 485 void CexmcSetup::RotateMatrix( const G4ThreeVector & rot, 486 G4RotationMatr 486 G4RotationMatrix & rm ) 487 { 487 { 488 rm.rotateX( rot.x() ); 488 rm.rotateX( rot.x() ); 489 rm.rotateY( rot.y() ); 489 rm.rotateY( rot.y() ); 490 rm.rotateZ( rot.z() ); 490 rm.rotateZ( rot.z() ); 491 } 491 } 492 492 493 493