Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 09:21:52

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 /*
0027  * ============================================================================
0028  *
0029  *       Filename:  CexmcEventAction.cc
0030  *
0031  *    Description:  event action
0032  *
0033  *        Version:  1.0
0034  *        Created:  27.10.2009 22:48:08
0035  *       Revision:  none
0036  *       Compiler:  gcc
0037  *
0038  *         Author:  Alexey Radkov (), 
0039  *        Company:  PNPI
0040  *
0041  * ============================================================================
0042  */
0043 
0044 #include <cmath>
0045 #ifdef CEXMC_USE_PERSISTENCY
0046 #include <boost/archive/binary_oarchive.hpp>
0047 #endif
0048 #include <G4DigiManager.hh>
0049 #include <G4Event.hh>
0050 #include <G4Circle.hh>
0051 #include <G4VisAttributes.hh>
0052 #include <G4VisManager.hh>
0053 #include <G4VTrajectory.hh>
0054 #include <G4TrajectoryContainer.hh>
0055 #include <G4Colour.hh>
0056 #include <G4SystemOfUnits.hh>
0057 #include "CexmcEventAction.hh"
0058 #include "CexmcEventActionMessenger.hh"
0059 #include "CexmcEventInfo.hh"
0060 #include "CexmcEventSObject.hh"
0061 #include "CexmcEventFastSObject.hh"
0062 #include "CexmcTrackingAction.hh"
0063 #include "CexmcChargeExchangeReconstructor.hh"
0064 #include "CexmcRunManager.hh"
0065 #include "CexmcHistoManager.hh"
0066 #include "CexmcRun.hh"
0067 #include "CexmcPhysicsManager.hh"
0068 #include "CexmcProductionModel.hh"
0069 #include "CexmcProductionModelData.hh"
0070 #include "CexmcEnergyDepositDigitizer.hh"
0071 #include "CexmcEnergyDepositStore.hh"
0072 #include "CexmcTrackPointsDigitizer.hh"
0073 #include "CexmcTrackPointsStore.hh"
0074 #include "CexmcTrackPointInfo.hh"
0075 #include "CexmcException.hh"
0076 #include "CexmcCommon.hh"
0077 
0078 
0079 namespace
0080 {
0081     G4double  CexmcSmallCircleScreenSize( 5.0 );
0082     G4double  CexmcBigCircleScreenSize( 10.0 );
0083     G4Colour  CexmcTrackPointsMarkerColour( 0.0, 1.0, 0.4 );
0084     G4Colour  CexmcRecTrackPointsMarkerColour( 1.0, 0.4, 0.0 );
0085 
0086 #ifdef CEXMC_USE_ROOT
0087     inline G4double  CexmcGetKinEnergy( G4double  momentumAmp, G4double  mass )
0088     {
0089         return std::sqrt( momentumAmp * momentumAmp + mass * mass ) - mass;
0090     }
0091 #endif
0092 }
0093 
0094 
0095 CexmcEventAction::CexmcEventAction( CexmcPhysicsManager *  physicsManager_,
0096                                     G4int  verbose_ ) :
0097     physicsManager( physicsManager_ ), reconstructor( NULL ),
0098 #ifdef CEXMC_USE_ROOT
0099     opKinEnergy( 0. ),
0100 #endif
0101     verbose( verbose_ ), verboseDraw( 4 ), messenger( NULL )
0102 {
0103     G4DigiManager *  digiManager( G4DigiManager::GetDMpointer() );
0104     digiManager->AddNewModule( new CexmcEnergyDepositDigitizer(
0105                                                     CexmcEDDigitizerName ) );
0106     digiManager->AddNewModule( new CexmcTrackPointsDigitizer(
0107                                                     CexmcTPDigitizerName ) );
0108     reconstructor = new CexmcChargeExchangeReconstructor(
0109                                         physicsManager->GetProductionModel() );
0110     messenger = new CexmcEventActionMessenger( this );
0111 }
0112 
0113 
0114 CexmcEventAction::~CexmcEventAction()
0115 {
0116     delete reconstructor;
0117     delete messenger;
0118 }
0119 
0120 
0121 void  CexmcEventAction::BeamParticleChangeHook( void )
0122 {
0123     reconstructor->SetupBeamParticle();
0124 }
0125 
0126 
0127 void  CexmcEventAction::BeginOfEventAction( const G4Event * )
0128 {
0129     G4RunManager *         runManager( G4RunManager::GetRunManager() );
0130     CexmcTrackingAction *  trackingAction
0131             ( static_cast< CexmcTrackingAction * >(
0132                         const_cast< G4UserTrackingAction * >(
0133                                     runManager->GetUserTrackingAction() ) ) );
0134     trackingAction->BeginOfEventAction();
0135 
0136     physicsManager->ResetNumberOfTriggeredStudiedInteractions();
0137 }
0138 
0139 
0140 CexmcEnergyDepositStore *  CexmcEventAction::MakeEnergyDepositStore(
0141                                 const CexmcEnergyDepositDigitizer *  digitizer )
0142 {
0143     G4double  monitorED( digitizer->GetMonitorED() );
0144     G4double  vetoCounterEDLeft( digitizer->GetVetoCounterEDLeft() );
0145     G4double  vetoCounterEDRight( digitizer->GetVetoCounterEDRight() );
0146     G4double  calorimeterEDLeft( digitizer->GetCalorimeterEDLeft() );
0147     G4double  calorimeterEDRight( digitizer->GetCalorimeterEDRight() );
0148     G4int     calorimeterEDLeftMaxX( digitizer->GetCalorimeterEDLeftMaxX() );
0149     G4int     calorimeterEDLeftMaxY( digitizer->GetCalorimeterEDLeftMaxY() );
0150     G4int     calorimeterEDRightMaxX( digitizer->GetCalorimeterEDRightMaxX() );
0151     G4int     calorimeterEDRightMaxY( digitizer->GetCalorimeterEDRightMaxY() );
0152 
0153     const CexmcEnergyDepositCalorimeterCollection &
0154               calorimeterEDLeftCollection(
0155                             digitizer->GetCalorimeterEDLeftCollection() );
0156     const CexmcEnergyDepositCalorimeterCollection &
0157               calorimeterEDRightCollection(
0158                             digitizer->GetCalorimeterEDRightCollection() );
0159 
0160     /* ATTENTION: return object in heap - must be freed by caller! */
0161     return new CexmcEnergyDepositStore( monitorED, vetoCounterEDLeft,
0162                     vetoCounterEDRight, calorimeterEDLeft, calorimeterEDRight,
0163                     calorimeterEDLeftMaxX, calorimeterEDLeftMaxY,
0164                     calorimeterEDRightMaxX, calorimeterEDRightMaxY,
0165                     calorimeterEDLeftCollection, calorimeterEDRightCollection );
0166 }
0167 
0168 
0169 CexmcTrackPointsStore *  CexmcEventAction::MakeTrackPointsStore(
0170                                 const CexmcTrackPointsDigitizer *  digitizer )
0171 {
0172     const CexmcTrackPointInfo &
0173                 monitorTP( digitizer->GetMonitorTP() );
0174     const CexmcTrackPointInfo &
0175                 targetTPBeamParticle(
0176                     digitizer->GetTargetTPBeamParticle() );
0177     const CexmcTrackPointInfo &
0178                 targetTPOutputParticle(
0179                     digitizer->GetTargetTPOutputParticle() );
0180     const CexmcTrackPointInfo &
0181                 targetTPNucleusParticle(
0182                     digitizer->GetTargetTPNucleusParticle() );
0183     const CexmcTrackPointInfo &
0184                 targetTPOutputParticleDecayProductParticle1(
0185                     digitizer->
0186                     GetTargetTPOutputParticleDecayProductParticle( 0 ) );
0187     const CexmcTrackPointInfo &
0188                 targetTPOutputParticleDecayProductParticle2(
0189                     digitizer->
0190                     GetTargetTPOutputParticleDecayProductParticle( 1 ) );
0191     const CexmcTrackPointInfo &
0192                 vetoCounterTPLeft(
0193                     digitizer->GetVetoCounterTPLeft() );
0194     const CexmcTrackPointInfo &
0195                 vetoCounterTPRight(
0196                     digitizer->GetVetoCounterTPRight() );
0197     const CexmcTrackPointInfo &
0198                 calorimeterTPLeft(
0199                     digitizer->GetCalorimeterTPLeft() );
0200     const CexmcTrackPointInfo &
0201                 calorimeterTPRight(
0202                     digitizer->GetCalorimeterTPRight() );
0203 
0204     /* ATTENTION: return object in heap - must be freed by caller! */
0205     return new CexmcTrackPointsStore( monitorTP, targetTPBeamParticle,
0206                   targetTPOutputParticle, targetTPNucleusParticle,
0207                   targetTPOutputParticleDecayProductParticle1,
0208                   targetTPOutputParticleDecayProductParticle2,
0209                   vetoCounterTPLeft, vetoCounterTPRight,
0210                   calorimeterTPLeft, calorimeterTPRight );
0211 }
0212 
0213 
0214 void  CexmcEventAction::PrintEnergyDeposit(
0215                                     const CexmcEnergyDepositStore *  edStore )
0216 {
0217     G4cout << " --- Energy Deposit" << G4endl;
0218     G4cout << "       monitor : " <<
0219             G4BestUnit( edStore->monitorED, "Energy" ) << G4endl;
0220     G4cout << "        vc (l) : " <<
0221             G4BestUnit( edStore->vetoCounterEDLeft, "Energy" ) << G4endl;
0222     G4cout << "        vc (r) : " <<
0223             G4BestUnit( edStore->vetoCounterEDRight, "Energy" ) << G4endl;
0224     G4cout << "       cal (l) : " <<
0225             G4BestUnit( edStore->calorimeterEDLeft, "Energy" );
0226     G4cout << edStore->calorimeterEDLeftCollection;
0227     G4cout << "       cal (r) : " <<
0228             G4BestUnit( edStore->calorimeterEDRight, "Energy" );
0229     G4cout << edStore->calorimeterEDRightCollection;
0230 }
0231 
0232 
0233 void  CexmcEventAction::PrintTrackPoints(
0234                                     const CexmcTrackPointsStore *  tpStore )
0235 {
0236     if ( ! tpStore )
0237         return;
0238 
0239     G4cout << " --- Track Points" << G4endl;
0240     G4cout << "       monitor : " << tpStore->monitorTP << G4endl;
0241     G4cout << "        target : " << tpStore->targetTPBeamParticle << G4endl;
0242     G4cout << "               : " << tpStore->targetTPOutputParticle << G4endl;
0243     G4cout << "               : " << tpStore->targetTPNucleusParticle << G4endl;
0244     G4cout << "               : " <<
0245             tpStore->targetTPOutputParticleDecayProductParticle1 << G4endl;
0246     G4cout << "               : " <<
0247             tpStore->targetTPOutputParticleDecayProductParticle2 << G4endl;
0248     G4cout << "        vc (l) : " << tpStore->vetoCounterTPLeft << G4endl;
0249     G4cout << "        vc (r) : " << tpStore->vetoCounterTPRight << G4endl;
0250     G4cout << "       cal (l) : " << tpStore->calorimeterTPLeft << G4endl;
0251     G4cout << "       cal (r) : " << tpStore->calorimeterTPRight << G4endl;
0252     G4cout << "      ---" << G4endl;
0253     G4cout << "      angle between the " <<
0254         tpStore->targetTPOutputParticle.particle->GetParticleName() <<
0255         " decay products : " <<
0256         tpStore->targetTPOutputParticleDecayProductParticle1.directionWorld.
0257             angle(
0258         tpStore->targetTPOutputParticleDecayProductParticle2.directionWorld ) /
0259             deg << " deg" << G4endl;
0260 }
0261 
0262 
0263 void  CexmcEventAction::PrintProductionModelData(
0264                                 const CexmcAngularRangeList &  angularRanges,
0265                                 const CexmcProductionModelData &  pmData )
0266 {
0267     G4cout << " --- Triggered angular ranges: " << angularRanges;
0268     G4cout << " --- Production model data: " << pmData;
0269 }
0270 
0271 
0272 void  CexmcEventAction::PrintReconstructedData(
0273                     const CexmcAngularRangeList &  triggeredRecAngularRanges,
0274                     const CexmcAngularRange &  angularGap ) const
0275 {
0276     G4cout << " --- Reconstructed data: " << G4endl;
0277     G4cout << "       -- entry points:" << G4endl;
0278     G4cout << "              left: " << G4BestUnit(
0279         reconstructor->GetCalorimeterEPLeftPosition(), "Length" ) << G4endl;
0280     G4cout << "             right: " << G4BestUnit(
0281         reconstructor->GetCalorimeterEPRightPosition(), "Length" ) << G4endl;
0282     G4cout << "            target: " << G4BestUnit(
0283         reconstructor->GetTargetEPPosition(), "Length" ) << G4endl;
0284     G4cout << "       -- the angle: " << reconstructor->GetTheAngle() / deg <<
0285         " deg" << G4endl;
0286     G4cout << "       -- mass of the output particle: " << G4BestUnit(
0287         reconstructor->GetOutputParticleMass(), "Energy" ) << G4endl;
0288     G4cout << "       -- mass of the nucleus output particle: " << G4BestUnit(
0289         reconstructor->GetNucleusOutputParticleMass(), "Energy" ) << G4endl;
0290     if ( reconstructor->IsMassCutUsed() )
0291     {
0292         if ( reconstructor->HasMassCutTriggered() )
0293             G4cout << "            < mass cut passed >" << G4endl;
0294         else
0295             G4cout << "            < mass cut failed >" << G4endl;
0296     }
0297     if ( reconstructor->IsAbsorbedEnergyCutUsed() )
0298     {
0299         if ( reconstructor->HasAbsorbedEnergyCutTriggered() )
0300             G4cout << "            < absorbed energy cut passed >" << G4endl;
0301         else
0302             G4cout << "            < absorbed energy cut failed >" << G4endl;
0303     }
0304     const CexmcProductionModelData &  pmData(
0305                                     reconstructor->GetProductionModelData() );
0306     G4cout << "       -- production model data: " << pmData;
0307     G4cout << "       -- triggered angular ranges: ";
0308     if ( triggeredRecAngularRanges.empty() )
0309         G4cout << "< orphan detected, gap " << angularGap << " >" << G4endl;
0310     else
0311         G4cout << triggeredRecAngularRanges;
0312 }
0313 
0314 
0315 #ifdef CEXMC_USE_ROOT
0316 
0317 void  CexmcEventAction::FillEDTHistos( const CexmcEnergyDepositStore *  edStore,
0318                 const CexmcAngularRangeList &  triggeredAngularRanges ) const
0319 {
0320     CexmcHistoManager *  histoManager( CexmcHistoManager::Instance() );
0321 
0322     histoManager->Add( CexmcAbsorbedEnergy_EDT_Histo, 0,
0323                        edStore->calorimeterEDLeft,
0324                        edStore->calorimeterEDRight );
0325 
0326     for ( CexmcAngularRangeList::const_iterator
0327                         k( triggeredAngularRanges.begin() );
0328                                     k != triggeredAngularRanges.end(); ++k )
0329     {
0330         histoManager->Add( CexmcAbsEnInLeftCalorimeter_ARReal_EDT_Histo,
0331                            k->index, edStore->calorimeterEDLeft );
0332         histoManager->Add( CexmcAbsEnInRightCalorimeter_ARReal_EDT_Histo,
0333                            k->index, edStore->calorimeterEDRight );
0334     }
0335 }
0336 
0337 
0338 void  CexmcEventAction::FillTPTHistos( const CexmcTrackPointsStore *  tpStore,
0339                 const CexmcProductionModelData &  pmData,
0340                 const CexmcAngularRangeList &  triggeredAngularRanges ) const
0341 {
0342     CexmcHistoManager *  histoManager( CexmcHistoManager::Instance() );
0343 
0344     if ( tpStore->monitorTP.IsValid() )
0345     {
0346         histoManager->Add( CexmcMomentumBP_TPT_Histo, 0,
0347                            tpStore->monitorTP.momentumAmp );
0348         histoManager->Add( CexmcTPInMonitor_TPT_Histo, 0,
0349                            tpStore->monitorTP.positionLocal.x(),
0350                            tpStore->monitorTP.positionLocal.y() );
0351     }
0352 
0353     if ( tpStore->targetTPOutputParticle.IsValid() )
0354     {
0355         histoManager->Add( CexmcTPInTarget_TPT_Histo, 0,
0356                            tpStore->targetTPOutputParticle.positionLocal.x(),
0357                            tpStore->targetTPOutputParticle.positionLocal.y(),
0358                            tpStore->targetTPOutputParticle.positionLocal.z() );
0359         if ( histoManager->GetVerboseLevel() > 0 )
0360         {
0361             histoManager->Add( CexmcMomentumIP_TPT_Histo, 0,
0362                                pmData.incidentParticleLAB.rho() );
0363         }
0364     }
0365 
0366     for ( CexmcAngularRangeList::const_iterator
0367                         k( triggeredAngularRanges.begin() );
0368                                     k != triggeredAngularRanges.end(); ++k )
0369     {
0370         if ( tpStore->calorimeterTPLeft.IsValid() )
0371         {
0372             /* kinetic energy and momentum of gamma are equal */
0373             G4double  kinEnergy( tpStore->calorimeterTPLeft.momentumAmp );
0374             histoManager->Add( CexmcKinEnAtLeftCalorimeter_ARReal_TPT_Histo,
0375                                k->index, kinEnergy );
0376         }
0377         if ( tpStore->calorimeterTPRight.IsValid() )
0378         {
0379             G4double  kinEnergy( tpStore->calorimeterTPRight.momentumAmp );
0380             histoManager->Add( CexmcKinEnAtRightCalorimeter_ARReal_TPT_Histo,
0381                                k->index, kinEnergy );
0382         }
0383         if ( tpStore->targetTPOutputParticle.IsValid() )
0384         {
0385             histoManager->Add( CexmcTPInTarget_ARReal_TPT_Histo, k->index,
0386                            tpStore->targetTPOutputParticle.positionLocal.x(),
0387                            tpStore->targetTPOutputParticle.positionLocal.y(),
0388                            tpStore->targetTPOutputParticle.positionLocal.z() );
0389             histoManager->Add( CexmcKinEnOP_LAB_ARReal_TPT_Histo, k->index,
0390                                opKinEnergy );
0391             histoManager->Add( CexmcAngleOP_SCM_ARReal_TPT_Histo, k->index,
0392                                pmData.outputParticleSCM.cosTheta() );
0393         }
0394         if ( tpStore->targetTPOutputParticleDecayProductParticle1.IsValid() &&
0395              tpStore->targetTPOutputParticleDecayProductParticle2.IsValid() )
0396         {
0397             G4double  openAngle(
0398                         tpStore->targetTPOutputParticleDecayProductParticle1.
0399                         directionWorld.angle( tpStore->
0400                                 targetTPOutputParticleDecayProductParticle2.
0401                                         directionWorld ) / deg );
0402             histoManager->Add( CexmcOpenAngle_ARReal_TPT_Histo, k->index,
0403                                openAngle );
0404         }
0405     }
0406 }
0407 
0408 
0409 void  CexmcEventAction::FillRTHistos( G4bool  reconstructorHasFullTrigger,
0410                 const CexmcEnergyDepositStore *  edStore,
0411                 const CexmcTrackPointsStore *  tpStore,
0412                 const CexmcProductionModelData &  pmData,
0413                 const CexmcAngularRangeList &  triggeredAngularRanges ) const
0414 {
0415     CexmcHistoManager *  histoManager( CexmcHistoManager::Instance() );
0416 
0417     G4double    opMass( reconstructor->GetOutputParticleMass() );
0418     G4double    nopMass( reconstructor->GetNucleusOutputParticleMass() );
0419 
0420     histoManager->Add( CexmcRecMasses_EDT_Histo, 0, opMass, nopMass );
0421 
0422     for ( CexmcAngularRangeList::const_iterator
0423                         k( triggeredAngularRanges.begin() );
0424                                     k != triggeredAngularRanges.end(); ++k )
0425     {
0426         if ( tpStore->calorimeterTPLeft.IsValid() )
0427         {
0428             histoManager->Add( CexmcOPDPAtLeftCalorimeter_ARReal_EDT_Histo,
0429                                k->index,
0430                                tpStore->calorimeterTPLeft.positionLocal.x(),
0431                                tpStore->calorimeterTPLeft.positionLocal.y() );
0432         }
0433         if ( tpStore->calorimeterTPRight.IsValid() )
0434         {
0435             histoManager->Add( CexmcOPDPAtRightCalorimeter_ARReal_EDT_Histo,
0436                                k->index,
0437                                tpStore->calorimeterTPRight.positionLocal.x(),
0438                                tpStore->calorimeterTPRight.positionLocal.y() );
0439         }
0440         histoManager->Add( CexmcRecOPDPAtLeftCalorimeter_ARReal_EDT_Histo,
0441                            k->index,
0442                            reconstructor->GetCalorimeterEPLeftPosition().x(),
0443                            reconstructor->GetCalorimeterEPLeftPosition().y() );
0444         histoManager->Add( CexmcRecOPDPAtRightCalorimeter_ARReal_EDT_Histo,
0445                            k->index,
0446                            reconstructor->GetCalorimeterEPRightPosition().x(),
0447                            reconstructor->GetCalorimeterEPRightPosition().y() );
0448     }
0449 
0450     if ( ! reconstructorHasFullTrigger )
0451         return;
0452 
0453     if ( tpStore->monitorTP.IsValid() )
0454     {
0455         histoManager->Add( CexmcMomentumBP_RT_Histo, 0,
0456                            tpStore->monitorTP.momentumAmp );
0457     }
0458 
0459     if ( tpStore->targetTPOutputParticle.IsValid() )
0460     {
0461         histoManager->Add( CexmcTPInTarget_RT_Histo, 0,
0462                            tpStore->targetTPOutputParticle.positionLocal.x(),
0463                            tpStore->targetTPOutputParticle.positionLocal.y(),
0464                            tpStore->targetTPOutputParticle.positionLocal.z() );
0465     }
0466 
0467     histoManager->Add( CexmcRecMasses_RT_Histo, 0,
0468                        reconstructor->GetOutputParticleMass(),
0469                        reconstructor->GetNucleusOutputParticleMass() );
0470 
0471     histoManager->Add( CexmcAbsorbedEnergy_RT_Histo, 0,
0472                        edStore->calorimeterEDLeft,
0473                        edStore->calorimeterEDRight );
0474 
0475     G4double  recCosTheta( reconstructor->GetProductionModelData().
0476                                                outputParticleSCM.cosTheta());
0477 
0478     for ( CexmcAngularRangeList::const_iterator
0479                         k( triggeredAngularRanges.begin() );
0480                                     k != triggeredAngularRanges.end(); ++k )
0481     {
0482         histoManager->Add( CexmcRecMassOP_ARReal_RT_Histo, k->index, opMass );
0483         histoManager->Add( CexmcRecMassNOP_ARReal_RT_Histo, k->index, nopMass );
0484         if ( tpStore->calorimeterTPLeft.IsValid() )
0485         {
0486             G4double  kinEnergy( tpStore->calorimeterTPLeft.momentumAmp );
0487             histoManager->Add( CexmcKinEnAtLeftCalorimeter_ARReal_RT_Histo,
0488                                k->index, kinEnergy );
0489             histoManager->Add( CexmcMissEnFromLeftCalorimeter_ARReal_RT_Histo,
0490                                k->index,
0491                                kinEnergy - edStore->calorimeterEDLeft );
0492         }
0493         if ( tpStore->calorimeterTPRight.IsValid() )
0494         {
0495             G4double  kinEnergy( tpStore->calorimeterTPRight.momentumAmp );
0496             histoManager->Add( CexmcKinEnAtRightCalorimeter_ARReal_RT_Histo,
0497                                k->index, kinEnergy );
0498             histoManager->Add( CexmcMissEnFromRightCalorimeter_ARReal_RT_Histo,
0499                                k->index,
0500                                kinEnergy - edStore->calorimeterEDRight );
0501         }
0502         if ( tpStore->targetTPOutputParticle.IsValid() )
0503         {
0504             histoManager->Add( CexmcTPInTarget_ARReal_RT_Histo, k->index,
0505                            tpStore->targetTPOutputParticle.positionLocal.x(),
0506                            tpStore->targetTPOutputParticle.positionLocal.y(),
0507                            tpStore->targetTPOutputParticle.positionLocal.z() );
0508             histoManager->Add( CexmcKinEnOP_LAB_ARReal_RT_Histo, k->index,
0509                                opKinEnergy );
0510             histoManager->Add( CexmcAngleOP_SCM_ARReal_RT_Histo, k->index,
0511                                pmData.outputParticleSCM.cosTheta() );
0512             G4double  diffCosTheta( pmData.outputParticleSCM.cosTheta() -
0513                                     recCosTheta );
0514             histoManager->Add( CexmcDiffAngleOP_SCM_ARReal_RT_Histo, k->index,
0515                                diffCosTheta );
0516         }
0517         if ( tpStore->targetTPOutputParticleDecayProductParticle1.IsValid() &&
0518              tpStore->targetTPOutputParticleDecayProductParticle2.IsValid() )
0519         {
0520             G4double  openAngle(
0521                         tpStore->targetTPOutputParticleDecayProductParticle1.
0522                         directionWorld.angle( tpStore->
0523                                 targetTPOutputParticleDecayProductParticle2.
0524                                         directionWorld ) / deg );
0525             histoManager->Add( CexmcOpenAngle_ARReal_RT_Histo, k->index,
0526                                openAngle );
0527             G4double  diffOpenAngle( openAngle - reconstructor->GetTheAngle() /
0528                                      deg );
0529             histoManager->Add( CexmcDiffOpenAngle_ARReal_RT_Histo, k->index,
0530                                diffOpenAngle );
0531         }
0532         if ( tpStore->calorimeterTPLeft.IsValid() )
0533         {
0534             histoManager->Add( CexmcOPDPAtLeftCalorimeter_ARReal_RT_Histo,
0535                                k->index,
0536                                tpStore->calorimeterTPLeft.positionLocal.x(),
0537                                tpStore->calorimeterTPLeft.positionLocal.y() );
0538         }
0539         if ( tpStore->calorimeterTPRight.IsValid() )
0540         {
0541             histoManager->Add( CexmcOPDPAtRightCalorimeter_ARReal_RT_Histo,
0542                                k->index,
0543                                tpStore->calorimeterTPRight.positionLocal.x(),
0544                                tpStore->calorimeterTPRight.positionLocal.y() );
0545         }
0546         histoManager->Add( CexmcAbsEnInLeftCalorimeter_ARReal_RT_Histo,
0547                            k->index, edStore->calorimeterEDLeft );
0548         histoManager->Add( CexmcAbsEnInRightCalorimeter_ARReal_RT_Histo,
0549                            k->index, edStore->calorimeterEDRight );
0550         histoManager->Add( CexmcRecAngleOP_SCM_ARReal_RT_Histo,
0551                            k->index, recCosTheta );
0552         histoManager->Add( CexmcRecOpenAngle_ARReal_RT_Histo,
0553                            k->index, reconstructor->GetTheAngle() / deg );
0554         histoManager->Add( CexmcRecOPDPAtLeftCalorimeter_ARReal_RT_Histo,
0555                            k->index,
0556                            reconstructor->GetCalorimeterEPLeftPosition().x(),
0557                            reconstructor->GetCalorimeterEPLeftPosition().y() );
0558         histoManager->Add( CexmcRecOPDPAtRightCalorimeter_ARReal_RT_Histo,
0559                            k->index,
0560                            reconstructor->GetCalorimeterEPRightPosition().x(),
0561                            reconstructor->GetCalorimeterEPRightPosition().y() );
0562     }
0563 }
0564 
0565 #endif
0566 
0567 
0568 void  CexmcEventAction::DrawTrajectories( const G4Event *  event )
0569 {
0570     G4VisManager *  visManager( static_cast< G4VisManager * >(
0571                                     G4VVisManager::GetConcreteInstance() ) );
0572     if ( ! visManager || ! visManager->GetCurrentGraphicsSystem() )
0573         return;
0574 
0575     G4int                    nTraj( 0 );
0576     G4TrajectoryContainer *  trajContainer( event->GetTrajectoryContainer() );
0577 
0578     if ( ! trajContainer )
0579         return;
0580 
0581     nTraj = trajContainer->entries();
0582 
0583     for ( int  i( 0 ); i < nTraj; ++i )
0584     {
0585         G4VTrajectory *  traj( ( *trajContainer )[ i ] );
0586         traj->DrawTrajectory();
0587     }
0588 }
0589 
0590 
0591 void  CexmcEventAction::DrawTrackPoints(
0592                                 const CexmcTrackPointsStore *  tpStore ) const
0593 {
0594     G4VisManager *  visManager( static_cast< G4VisManager * >(
0595                                     G4VVisManager::GetConcreteInstance() ) );
0596     if ( ! visManager || ! visManager->GetCurrentGraphicsSystem() )
0597         return;
0598 
0599     G4Circle         circle;
0600     G4VisAttributes  visAttributes( CexmcTrackPointsMarkerColour );
0601     circle.SetScreenSize( CexmcSmallCircleScreenSize );
0602     circle.SetFillStyle( G4Circle::filled );
0603     circle.SetVisAttributes( visAttributes );
0604 
0605     if ( tpStore->monitorTP.IsValid() )
0606     {
0607         circle.SetPosition( tpStore->monitorTP.positionWorld );
0608         visManager->Draw( circle );
0609     }
0610 
0611     if ( tpStore->targetTPBeamParticle.IsValid() )
0612     {
0613         circle.SetPosition( tpStore->targetTPBeamParticle.positionWorld );
0614         visManager->Draw( circle );
0615     }
0616 
0617     if ( tpStore->targetTPOutputParticle.IsValid() )
0618     {
0619         circle.SetPosition( tpStore->targetTPOutputParticle.positionWorld );
0620         visManager->Draw( circle );
0621     }
0622 
0623     if ( tpStore->vetoCounterTPLeft.IsValid() )
0624     {
0625         circle.SetPosition( tpStore->vetoCounterTPLeft.positionWorld );
0626         visManager->Draw( circle );
0627     }
0628 
0629     if ( tpStore->vetoCounterTPRight.IsValid() )
0630     {
0631         circle.SetPosition( tpStore->vetoCounterTPRight.positionWorld );
0632         visManager->Draw( circle );
0633     }
0634 
0635     if ( tpStore->calorimeterTPLeft.IsValid() )
0636     {
0637         circle.SetPosition( tpStore->calorimeterTPLeft.positionWorld );
0638         visManager->Draw( circle );
0639     }
0640 
0641     if ( tpStore->calorimeterTPRight.IsValid() )
0642     {
0643         circle.SetPosition( tpStore->calorimeterTPRight.positionWorld );
0644         visManager->Draw( circle );
0645     }
0646 }
0647 
0648 
0649 void  CexmcEventAction::DrawReconstructionData( void )
0650 {
0651     G4VisManager *  visManager( static_cast< G4VisManager * >(
0652                                     G4VVisManager::GetConcreteInstance() ) );
0653     if ( ! visManager || ! visManager->GetCurrentGraphicsSystem() )
0654         return;
0655 
0656     G4Circle  circle( reconstructor->GetTargetEPWorldPosition() );
0657     circle.SetScreenSize( CexmcSmallCircleScreenSize );
0658     circle.SetFillStyle( G4Circle::filled );
0659     G4VisAttributes  visAttributes( CexmcRecTrackPointsMarkerColour );
0660     circle.SetVisAttributes( visAttributes );
0661     visManager->Draw( circle );
0662 
0663     circle.SetScreenSize( CexmcBigCircleScreenSize );
0664     circle.SetPosition( reconstructor->GetCalorimeterEPLeftWorldPosition() );
0665     visManager->Draw( circle );
0666 
0667     circle.SetPosition( reconstructor->GetCalorimeterEPRightWorldPosition() );
0668     visManager->Draw( circle );
0669 }
0670 
0671 
0672 void  CexmcEventAction::UpdateRunHits(
0673                                     const CexmcAngularRangeList &  aRangesReal,
0674                                     const CexmcAngularRangeList &  aRangesRec,
0675                                     G4bool  tpDigitizerHasTriggered,
0676                                     G4bool  edDigitizerHasTriggered,
0677                                     G4bool  edDigitizerMonitorHasTriggered,
0678                                     G4bool  reconstructorHasFullTrigger,
0679                                     const CexmcAngularRange &  aGap )
0680 {
0681     G4RunManager *    runManager( G4RunManager::GetRunManager() );
0682     const CexmcRun *  run( static_cast< const CexmcRun * >(
0683                                                 runManager->GetCurrentRun() ) );
0684     CexmcRun *        theRun( const_cast< CexmcRun * >( run ) );
0685 
0686     if ( tpDigitizerHasTriggered )
0687     {
0688         for ( CexmcAngularRangeList::const_iterator  k( aRangesReal.begin() );
0689                                                 k != aRangesReal.end(); ++k )
0690         {
0691             theRun->IncrementNmbOfHitsSampledFull( k->index );
0692             if ( edDigitizerMonitorHasTriggered )
0693                 theRun->IncrementNmbOfHitsSampled( k->index );
0694             if ( reconstructorHasFullTrigger )
0695                 theRun->IncrementNmbOfHitsTriggeredRealRange( k->index );
0696         }
0697         if ( reconstructorHasFullTrigger )
0698         {
0699             if ( aRangesRec.empty() )
0700             {
0701                 theRun->IncrementNmbOfOrphanHits( aGap.index );
0702             }
0703             else
0704             {
0705                 for ( CexmcAngularRangeList::const_iterator
0706                         k( aRangesRec.begin() ); k != aRangesRec.end(); ++k )
0707                 {
0708                     theRun->IncrementNmbOfHitsTriggeredRecRange( k->index );
0709                 }
0710             }
0711         }
0712     }
0713     else
0714     {
0715         if ( edDigitizerHasTriggered )
0716             theRun->IncrementNmbOfFalseHitsTriggeredEDT();
0717         if ( reconstructorHasFullTrigger )
0718             theRun->IncrementNmbOfFalseHitsTriggeredRec();
0719     }
0720 }
0721 
0722 
0723 #ifdef CEXMC_USE_PERSISTENCY
0724 
0725 void  CexmcEventAction::SaveEvent( const G4Event *  event,
0726                                    G4bool  edDigitizerHasTriggered,
0727                                    const CexmcEnergyDepositStore *  edStore,
0728                                    const CexmcTrackPointsStore *  tpStore,
0729                                    const CexmcProductionModelData &  pmData )
0730 {
0731     CexmcRunManager *  runManager( static_cast< CexmcRunManager * >(
0732                                             G4RunManager::GetRunManager() ) );
0733     if ( ! runManager->ProjectIsSaved() )
0734         return;
0735 
0736     if ( runManager->GetEventDataVerboseLevel() == CexmcWriteNoEventData )
0737         return;
0738 
0739     if ( ! edDigitizerHasTriggered && runManager->GetEventDataVerboseLevel() !=
0740                                                 CexmcWriteEventDataOnEveryTPT )
0741         return;
0742 
0743     boost::archive::binary_oarchive *  archive(
0744                                             runManager->GetEventsArchive() );
0745     if ( archive )
0746     {
0747         CexmcEventSObject  sObject = { event->GetEventID(),
0748             edDigitizerHasTriggered, edStore->monitorED,
0749             edStore->vetoCounterEDLeft, edStore->vetoCounterEDRight,
0750             edStore->calorimeterEDLeft, edStore->calorimeterEDRight,
0751             edStore->calorimeterEDLeftCollection,
0752             edStore->calorimeterEDRightCollection,
0753             tpStore->monitorTP, tpStore->targetTPBeamParticle,
0754             tpStore->targetTPOutputParticle, tpStore->targetTPNucleusParticle,
0755             tpStore->targetTPOutputParticleDecayProductParticle1,
0756             tpStore->targetTPOutputParticleDecayProductParticle2,
0757             tpStore->vetoCounterTPLeft, tpStore->vetoCounterTPRight,
0758             tpStore->calorimeterTPLeft, tpStore->calorimeterTPRight, pmData };
0759         archive->operator<<( sObject );
0760         const CexmcRun *  run( static_cast< const CexmcRun * >(
0761                                                 runManager->GetCurrentRun() ) );
0762         CexmcRun *        theRun( const_cast< CexmcRun * >( run ) );
0763         theRun->IncrementNmbOfSavedEvents();
0764     }
0765 }
0766 
0767 
0768 void  CexmcEventAction::SaveEventFast( const G4Event *  event,
0769                                        G4bool  tpDigitizerHasTriggered,
0770                                        G4bool  edDigitizerHasTriggered,
0771                                        G4bool  edDigitizerMonitorHasTriggered,
0772                                        G4double  opCosThetaSCM )
0773 {
0774     CexmcRunManager *  runManager( static_cast< CexmcRunManager * >(
0775                                             G4RunManager::GetRunManager() ) );
0776     if ( ! runManager->ProjectIsSaved() )
0777         return;
0778 
0779     if ( runManager->GetEventDataVerboseLevel() == CexmcWriteNoEventData )
0780         return;
0781 
0782     boost::archive::binary_oarchive *  archive(
0783                                         runManager->GetFastEventsArchive() );
0784     if ( archive )
0785     {
0786         if ( ! tpDigitizerHasTriggered )
0787             opCosThetaSCM = CexmcInvalidCosTheta;
0788 
0789         CexmcEventFastSObject  sObject = { event->GetEventID(), opCosThetaSCM,
0790                                            edDigitizerHasTriggered,
0791                                            edDigitizerMonitorHasTriggered };
0792         archive->operator<<( sObject );
0793         const CexmcRun *  run( static_cast< const CexmcRun * >(
0794                                                 runManager->GetCurrentRun() ) );
0795         CexmcRun *        theRun( const_cast< CexmcRun * >( run ) );
0796         theRun->IncrementNmbOfSavedFastEvents();
0797     }
0798 }
0799 
0800 #endif
0801 
0802 
0803 void  CexmcEventAction::EndOfEventAction( const G4Event *  event )
0804 {
0805     G4DigiManager *                digiManager( G4DigiManager::GetDMpointer() );
0806     CexmcEnergyDepositDigitizer *  energyDepositDigitizer(
0807             static_cast< CexmcEnergyDepositDigitizer * >( digiManager->
0808                                 FindDigitizerModule( CexmcEDDigitizerName ) ) );
0809     CexmcTrackPointsDigitizer *    trackPointsDigitizer(
0810             static_cast< CexmcTrackPointsDigitizer * >( digiManager->
0811                                 FindDigitizerModule( CexmcTPDigitizerName ) ) );
0812 
0813     energyDepositDigitizer->Digitize();
0814     trackPointsDigitizer->Digitize();
0815 
0816     G4bool  edDigitizerMonitorHasTriggered(
0817                                 energyDepositDigitizer->MonitorHasTriggered() );
0818     G4bool  edDigitizerHasTriggered( false );
0819 
0820     CexmcEventInfo *  eventInfo( static_cast< CexmcEventInfo * >(
0821                                                 event->GetUserInformation() ) );
0822     if ( ! eventInfo || eventInfo->EdTriggerIsOk() )
0823         edDigitizerHasTriggered = energyDepositDigitizer->HasTriggered();
0824 
0825     G4bool  tpDigitizerHasTriggered( trackPointsDigitizer->HasTriggered() );
0826     G4bool  reconstructorHasBasicTrigger( false );
0827     G4bool  reconstructorHasFullTrigger( false );
0828 
0829     CexmcEnergyDepositStore *  edStore( MakeEnergyDepositStore(
0830                                                     energyDepositDigitizer ) );
0831     CexmcTrackPointsStore *    tpStore( MakeTrackPointsStore(
0832                                                     trackPointsDigitizer ) );
0833 
0834     try
0835     {
0836         CexmcProductionModel *  productionModel(
0837                                         physicsManager->GetProductionModel() );
0838 
0839         if ( ! productionModel )
0840             throw CexmcException( CexmcWeirdException );
0841 
0842         const CexmcAngularRangeList &     angularRanges(
0843                                 productionModel->GetAngularRanges() );
0844         const CexmcAngularRangeList &     triggeredAngularRanges(
0845                                 productionModel->GetTriggeredAngularRanges() );
0846         const CexmcProductionModelData &  pmData(
0847                                 productionModel->GetProductionModelData() );
0848 
0849         if ( edDigitizerHasTriggered )
0850         {
0851             reconstructor->Reconstruct( edStore );
0852             reconstructorHasBasicTrigger = reconstructor->HasBasicTrigger();
0853             reconstructorHasFullTrigger = reconstructor->HasFullTrigger();
0854         }
0855 
0856         CexmcAngularRangeList  triggeredRecAngularRanges;
0857 
0858         if ( reconstructorHasBasicTrigger )
0859         {
0860             for ( CexmcAngularRangeList::const_iterator
0861                   k( angularRanges.begin() ); k != angularRanges.end(); ++k )
0862             {
0863                 G4double  cosTheta( reconstructor->GetProductionModelData().
0864                                     outputParticleSCM.cosTheta() );
0865                 if ( cosTheta <= k->top && cosTheta > k->bottom )
0866                     triggeredRecAngularRanges.push_back( CexmcAngularRange(
0867                                                 k->top, k->bottom, k->index ) );
0868             }
0869         }
0870 
0871         CexmcAngularRange  angularGap( 0.0, 0.0, 0 );
0872         if ( triggeredRecAngularRanges.empty() )
0873         {
0874             CexmcAngularRangeList  angularGaps;
0875             GetAngularGaps( angularRanges, angularGaps );
0876             for ( CexmcAngularRangeList::const_iterator
0877                     k( angularGaps.begin() ); k != angularGaps.end(); ++k )
0878             {
0879                 G4double  cosTheta( reconstructor->GetProductionModelData().
0880                                     outputParticleSCM.cosTheta() );
0881                 if ( cosTheta <= k->top && cosTheta > k->bottom )
0882                 {
0883                     angularGap = *k;
0884                     break;
0885                 }
0886             }
0887         }
0888 
0889         UpdateRunHits( triggeredAngularRanges, triggeredRecAngularRanges,
0890                        tpDigitizerHasTriggered, edDigitizerHasTriggered,
0891                        edDigitizerMonitorHasTriggered,
0892                        reconstructorHasFullTrigger, angularGap );
0893 
0894         if ( verbose > 0 )
0895         {
0896             G4bool  printMessages( verbose > 3 ||
0897                         ( ( verbose == 1 ) && tpDigitizerHasTriggered ) ||
0898                         ( ( verbose == 2 ) && edDigitizerHasTriggered ) ||
0899                         ( ( verbose == 3 ) && ( tpDigitizerHasTriggered ||
0900                                                 edDigitizerHasTriggered ) ) );
0901             if ( printMessages )
0902             {
0903                 G4cout << "Event " << event->GetEventID() << G4endl;
0904                 if ( tpDigitizerHasTriggered )
0905                 {
0906                     PrintTrackPoints( tpStore );
0907                     PrintProductionModelData( triggeredAngularRanges, pmData );
0908                 }
0909                 if ( reconstructorHasBasicTrigger )
0910                     PrintReconstructedData( triggeredRecAngularRanges,
0911                                             angularGap );
0912                 if ( edDigitizerHasTriggered )
0913                     PrintEnergyDeposit( edStore );
0914             }
0915         }
0916 
0917         if ( verboseDraw > 0 )
0918         {
0919             G4bool  drawTrajectories( verboseDraw > 3 ||
0920                         ( ( verboseDraw == 1 ) && tpDigitizerHasTriggered ) ||
0921                         ( ( verboseDraw == 2 ) && edDigitizerHasTriggered ) ||
0922                         ( ( verboseDraw == 3 ) && ( tpDigitizerHasTriggered ||
0923                                                 edDigitizerHasTriggered ) ) );
0924             if ( drawTrajectories )
0925             {
0926                 DrawTrajectories( event );
0927                 if ( tpDigitizerHasTriggered )
0928                     DrawTrackPoints( tpStore );
0929                 if ( reconstructorHasBasicTrigger )
0930                     DrawReconstructionData();
0931             }
0932         }
0933 
0934 #ifdef CEXMC_USE_PERSISTENCY
0935         if ( edDigitizerHasTriggered || tpDigitizerHasTriggered )
0936         {
0937             SaveEventFast( event, tpDigitizerHasTriggered,
0938                            edDigitizerHasTriggered,
0939                            edDigitizerMonitorHasTriggered,
0940                            pmData.outputParticleSCM.cosTheta() );
0941             SaveEvent( event, edDigitizerHasTriggered, edStore, tpStore,
0942                        pmData );
0943         }
0944 #endif
0945 
0946 #ifdef CEXMC_USE_ROOT
0947         /* opKinEnergy will be used in several histos */
0948         if ( tpStore->targetTPOutputParticle.IsValid() )
0949         {
0950             opKinEnergy = CexmcGetKinEnergy(
0951                     tpStore->targetTPOutputParticle.momentumAmp,
0952                     tpStore->targetTPOutputParticle.particle->GetPDGMass() );
0953         }
0954 
0955         if ( edDigitizerHasTriggered )
0956             FillEDTHistos( edStore, triggeredAngularRanges );
0957 
0958         /* fill TPT histos only when the monitor has triggered because events
0959          * when it was missed have less value for us */
0960         if ( tpDigitizerHasTriggered && edDigitizerMonitorHasTriggered )
0961             FillTPTHistos( tpStore, pmData, triggeredAngularRanges );
0962 
0963         if ( reconstructorHasBasicTrigger )
0964             FillRTHistos( reconstructorHasFullTrigger, edStore, tpStore,
0965                           pmData, triggeredAngularRanges );
0966 #endif
0967 
0968         G4Event *  theEvent( const_cast< G4Event * >( event ) );
0969         if ( eventInfo )
0970         {
0971             delete eventInfo;
0972             theEvent->SetUserInformation( NULL );
0973         }
0974         theEvent->SetUserInformation( new CexmcEventInfo(
0975                                                 edDigitizerHasTriggered,
0976                                                 tpDigitizerHasTriggered,
0977                                                 reconstructorHasFullTrigger ) );
0978     }
0979     catch ( CexmcException &  e )
0980     {
0981         G4cout << e.what() << G4endl;
0982     }
0983     catch ( ... )
0984     {
0985         G4cout << "Unknown exception caught" << G4endl;
0986     }
0987 
0988     delete edStore;
0989     delete tpStore;
0990 }
0991