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