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