File indexing completed on 2025-01-31 09:21:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 #include "CexmcReconstructor.hh"
0045 #include "CexmcReconstructorMessenger.hh"
0046 #include "CexmcEnergyDepositStore.hh"
0047 #include "CexmcRunManager.hh"
0048
0049
0050 CexmcReconstructor::CexmcReconstructor() : hasBasicTrigger( false ),
0051 epDefinitionAlgorithm( CexmcEntryPointBySqrtEDWeights ),
0052 epDepthDefinitionAlgorithm( CexmcEntryPointDepthPlain ),
0053 csAlgorithm( CexmcSelectAllCrystals ), useInnerRefCrystal( false ),
0054 epDepth( 0 ), theAngle( 0 ), calorimeterEDLeftAdjacent( 0 ),
0055 calorimeterEDRightAdjacent( 0 ), collectEDInAdjacentCrystals( false ),
0056 targetEPInitialized( false ), messenger( NULL )
0057 {
0058 G4RunManager * runManager( G4RunManager::GetRunManager() );
0059 const CexmcSetup * setup( static_cast< const CexmcSetup * >(
0060 runManager->GetUserDetectorConstruction() ) );
0061 calorimeterGeometry = setup->GetCalorimeterGeometry();
0062 targetTransform = setup->GetTargetTransform();
0063 calorimeterLeftTransform = setup->GetCalorimeterLeftTransform();
0064 calorimeterRightTransform = setup->GetCalorimeterRightTransform();
0065
0066 messenger = new CexmcReconstructorMessenger( this );
0067 }
0068
0069
0070 CexmcReconstructor::~CexmcReconstructor()
0071 {
0072 delete messenger;
0073 }
0074
0075
0076 void CexmcReconstructor::Reconstruct(
0077 const CexmcEnergyDepositStore * edStore )
0078 {
0079 ReconstructEntryPoints( edStore );
0080 if ( hasBasicTrigger )
0081 ReconstructTargetPoint();
0082 if ( hasBasicTrigger )
0083 ReconstructAngle();
0084 }
0085
0086
0087 G4bool CexmcReconstructor::HasFullTrigger( void ) const
0088 {
0089 return hasBasicTrigger;
0090 }
0091
0092
0093 void CexmcReconstructor::ReconstructEntryPoints(
0094 const CexmcEnergyDepositStore * edStore )
0095 {
0096 G4int columnLeft( edStore->calorimeterEDLeftMaxX );
0097 G4int rowLeft( edStore->calorimeterEDLeftMaxY );
0098 G4int columnRight( edStore->calorimeterEDRightMaxX );
0099 G4int rowRight( edStore->calorimeterEDRightMaxY );
0100 G4double crystalLength( calorimeterGeometry.crystalLength );
0101
0102 if ( useInnerRefCrystal )
0103 {
0104 TransformToAdjacentInnerCrystal( columnLeft, rowLeft );
0105 TransformToAdjacentInnerCrystal( columnRight, rowRight );
0106 }
0107
0108 calorimeterEPLeftPosition.setX( 0 );
0109 calorimeterEPLeftPosition.setY( 0 );
0110 calorimeterEPLeftPosition.setZ( -crystalLength / 2 + epDepth );
0111 calorimeterEPLeftDirection.setX( 0 );
0112 calorimeterEPLeftDirection.setY( 0 );
0113 calorimeterEPLeftDirection.setZ( 0 );
0114 calorimeterEPRightPosition.setX( 0 );
0115 calorimeterEPRightPosition.setY( 0 );
0116 calorimeterEPRightPosition.setZ( -crystalLength / 2 + epDepth );
0117 calorimeterEPRightDirection.setX( 0 );
0118 calorimeterEPRightDirection.setY( 0 );
0119 calorimeterEPRightDirection.setZ( 0 );
0120
0121 G4bool edInAdjacentCrystalsCollected( false );
0122
0123 switch ( epDefinitionAlgorithm )
0124 {
0125 case CexmcEntryPointInTheCenter :
0126 break;
0127 case CexmcEntryPointInTheCenterOfCrystalWithMaxED :
0128 {
0129 G4int nCrystalsInColumn(
0130 calorimeterGeometry.nCrystalsInColumn );
0131 G4int nCrystalsInRow( calorimeterGeometry.nCrystalsInRow );
0132 G4double crystalWidth( calorimeterGeometry.crystalWidth );
0133 G4double crystalHeight( calorimeterGeometry.crystalHeight );
0134
0135 calorimeterEPLeftPosition.setX(
0136 ( G4double( columnLeft ) - G4double( nCrystalsInRow ) / 2 ) *
0137 crystalWidth + crystalWidth / 2 );
0138 calorimeterEPLeftPosition.setY(
0139 ( G4double( rowLeft ) - G4double( nCrystalsInColumn ) / 2 ) *
0140 crystalHeight + crystalHeight / 2 );
0141 calorimeterEPRightPosition.setX(
0142 ( G4double( columnRight ) - G4double( nCrystalsInRow ) / 2 ) *
0143 crystalWidth + crystalWidth / 2 );
0144 calorimeterEPRightPosition.setY(
0145 ( G4double( rowRight ) - G4double( nCrystalsInColumn ) / 2 ) *
0146 crystalHeight + crystalHeight / 2 );
0147 }
0148 break;
0149 case CexmcEntryPointByLinearEDWeights :
0150 case CexmcEntryPointBySqrtEDWeights :
0151 {
0152 G4double x( 0 );
0153 G4double y( 0 );
0154
0155 CalculateWeightedEPPosition( edStore->calorimeterEDLeftCollection,
0156 rowLeft, columnLeft, x, y,
0157 calorimeterEDLeftAdjacent );
0158 calorimeterEPLeftPosition.setX( x );
0159 calorimeterEPLeftPosition.setY( y );
0160 CalculateWeightedEPPosition( edStore->calorimeterEDRightCollection,
0161 rowRight, columnRight, x, y,
0162 calorimeterEDRightAdjacent );
0163 calorimeterEPRightPosition.setX( x );
0164 calorimeterEPRightPosition.setY( y );
0165
0166 if ( csAlgorithm == CexmcSelectAdjacentCrystals )
0167 edInAdjacentCrystalsCollected = true;
0168 }
0169 break;
0170 default :
0171 break;
0172 }
0173
0174 switch ( epDepthDefinitionAlgorithm )
0175 {
0176 case CexmcEntryPointDepthPlain :
0177 break;
0178 case CexmcEntryPointDepthSphere :
0179 {
0180 G4double calorimeterEPLeftRadiusOfTheSphere(
0181 calorimeterLeftTransform.NetTranslation().mag() +
0182 calorimeterEPLeftPosition.z() );
0183 G4double calorimeterEPLeftRadiusOfTheSphere2(
0184 calorimeterEPLeftRadiusOfTheSphere *
0185 calorimeterEPLeftRadiusOfTheSphere );
0186 G4double calorimeterEPLeftPositionX2(
0187 calorimeterEPLeftPosition.x() *
0188 calorimeterEPLeftPosition.x() );
0189 G4double calorimeterEPLeftPositionY2(
0190 calorimeterEPLeftPosition.y() *
0191 calorimeterEPLeftPosition.y() );
0192 G4double calorimeterEPLeftPositionZOffset(
0193 calorimeterEPLeftRadiusOfTheSphere - std::sqrt(
0194 calorimeterEPLeftRadiusOfTheSphere2 -
0195 calorimeterEPLeftPositionX2 -
0196 calorimeterEPLeftPositionY2 ) );
0197 G4double calorimeterEPRightRadiusOfTheSphere(
0198 calorimeterRightTransform.NetTranslation().mag() +
0199 calorimeterEPRightPosition.z() );
0200 G4double calorimeterEPRightRadiusOfTheSphere2(
0201 calorimeterEPRightRadiusOfTheSphere *
0202 calorimeterEPRightRadiusOfTheSphere );
0203 G4double calorimeterEPRightPositionX2(
0204 calorimeterEPRightPosition.x() *
0205 calorimeterEPRightPosition.x() );
0206 G4double calorimeterEPRightPositionY2(
0207 calorimeterEPRightPosition.y() *
0208 calorimeterEPRightPosition.y() );
0209 G4double calorimeterEPRightPositionZOffset(
0210 calorimeterEPRightRadiusOfTheSphere - std::sqrt(
0211 calorimeterEPRightRadiusOfTheSphere2 -
0212 calorimeterEPRightPositionX2 -
0213 calorimeterEPRightPositionY2 ) );
0214 calorimeterEPLeftPosition.setZ( calorimeterEPLeftPosition.z() -
0215 calorimeterEPLeftPositionZOffset );
0216 calorimeterEPRightPosition.setZ( calorimeterEPRightPosition.z() -
0217 calorimeterEPRightPositionZOffset );
0218 }
0219 break;
0220 default :
0221 break;
0222 }
0223
0224 calorimeterEPLeftWorldPosition = calorimeterLeftTransform.TransformPoint(
0225 calorimeterEPLeftPosition );
0226 calorimeterEPLeftWorldDirection = calorimeterLeftTransform.TransformAxis(
0227 calorimeterEPLeftDirection );
0228 calorimeterEPRightWorldPosition = calorimeterRightTransform.TransformPoint(
0229 calorimeterEPRightPosition );
0230 calorimeterEPRightWorldDirection = calorimeterRightTransform.TransformAxis(
0231 calorimeterEPRightDirection );
0232
0233 if ( collectEDInAdjacentCrystals && ! edInAdjacentCrystalsCollected )
0234 {
0235 CollectEDInAdjacentCrystals( edStore->calorimeterEDLeftCollection,
0236 rowLeft, columnLeft,
0237 calorimeterEDLeftAdjacent );
0238 CollectEDInAdjacentCrystals( edStore->calorimeterEDRightCollection,
0239 rowRight, columnRight,
0240 calorimeterEDRightAdjacent );
0241 }
0242
0243 hasBasicTrigger = true;
0244 }
0245
0246
0247 void CexmcReconstructor::ReconstructTargetPoint( void )
0248 {
0249 if ( ! targetEPInitialized )
0250 {
0251 targetEPWorldPosition = targetTransform.TransformPoint(
0252 G4ThreeVector( 0, 0, 0 ) );
0253 targetEPWorldDirection.setX( 0 );
0254 targetEPWorldDirection.setY( 0 );
0255 targetEPWorldDirection.setZ( 1 );
0256
0257 targetEPPosition = targetTransform.Inverse().TransformPoint(
0258 targetEPWorldPosition );
0259 targetEPDirection = targetTransform.Inverse().TransformAxis(
0260 targetEPWorldDirection );
0261 targetEPInitialized = true;
0262 }
0263
0264 hasBasicTrigger = true;
0265 }
0266
0267
0268 void CexmcReconstructor::ReconstructAngle( void )
0269 {
0270 G4ThreeVector epLeft( calorimeterEPLeftWorldPosition -
0271 targetEPWorldPosition );
0272 G4ThreeVector epRight( calorimeterEPRightWorldPosition -
0273 targetEPWorldPosition );
0274 theAngle = epLeft.angle( epRight );
0275
0276 hasBasicTrigger = true;
0277 }
0278
0279
0280 void CexmcReconstructor::CollectEDInAdjacentCrystals(
0281 const CexmcEnergyDepositCalorimeterCollection & edHits,
0282 G4int row, G4int column, G4double & ed )
0283 {
0284 G4int i( 0 );
0285
0286 for ( CexmcEnergyDepositCalorimeterCollection::const_iterator
0287 k( edHits.begin() ); k != edHits.end(); ++k )
0288 {
0289 if ( i - row > 1 || i - row < -1 )
0290 {
0291 ++i;
0292 continue;
0293 }
0294
0295 G4int j( 0 );
0296 for ( CexmcEnergyDepositCrystalRowCollection::const_iterator
0297 l( k->begin() ); l != k->end(); ++l )
0298 {
0299 if ( j - column > 1 || j - column < -1 )
0300 {
0301 ++j;
0302 continue;
0303 }
0304 ed += *l;
0305 ++j;
0306 }
0307 ++i;
0308 }
0309 }
0310
0311
0312 void CexmcReconstructor::CalculateWeightedEPPosition(
0313 const CexmcEnergyDepositCalorimeterCollection & edHits,
0314 G4int row, G4int column, G4double & x, G4double & y,
0315 G4double & ed )
0316 {
0317 G4int nCrystalsInColumn( calorimeterGeometry.nCrystalsInColumn );
0318 G4int nCrystalsInRow( calorimeterGeometry.nCrystalsInRow );
0319 G4double crystalWidth( calorimeterGeometry.crystalWidth );
0320 G4double crystalHeight( calorimeterGeometry.crystalHeight );
0321
0322 G4int i( 0 );
0323 G4double xWeightsSum( 0 );
0324 G4double yWeightsSum( 0 );
0325 G4double energyWeightsSum( 0 );
0326
0327 if ( csAlgorithm == CexmcSelectAdjacentCrystals )
0328 ed = 0.;
0329
0330 for ( CexmcEnergyDepositCalorimeterCollection::const_iterator
0331 k( edHits.begin() ); k != edHits.end(); ++k )
0332 {
0333 if ( csAlgorithm == CexmcSelectAdjacentCrystals &&
0334 ( i - row > 1 || i - row < -1 ) )
0335 {
0336 ++i;
0337 continue;
0338 }
0339
0340 G4int j( 0 );
0341 for ( CexmcEnergyDepositCrystalRowCollection::const_iterator
0342 l( k->begin() ); l != k->end(); ++l )
0343 {
0344 if ( csAlgorithm == CexmcSelectAdjacentCrystals &&
0345 ( j - column > 1 || j - column < -1 ) )
0346 {
0347 ++j;
0348 continue;
0349 }
0350
0351 if ( csAlgorithm == CexmcSelectAdjacentCrystals )
0352 ed += *l;
0353
0354 G4double xInCalorimeterOffset(
0355 ( G4double( j ) - G4double( nCrystalsInRow ) / 2 ) *
0356 crystalWidth + crystalWidth / 2 );
0357 G4double energyWeight(
0358 epDefinitionAlgorithm ==
0359 CexmcEntryPointBySqrtEDWeights ?
0360 std::sqrt( *l ) : *l );
0361 xWeightsSum += energyWeight * xInCalorimeterOffset;
0362 G4double yInCalorimeterOffset(
0363 ( G4double( i ) - G4double( nCrystalsInColumn ) / 2 ) *
0364 crystalHeight + crystalHeight / 2 );
0365 yWeightsSum += energyWeight * yInCalorimeterOffset;
0366 energyWeightsSum += energyWeight;
0367 ++j;
0368 }
0369 ++i;
0370 }
0371
0372 x = xWeightsSum / energyWeightsSum;
0373 y = yWeightsSum / energyWeightsSum;
0374 }
0375