Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/examples/advanced/ChargeExchangeMC/src/CexmcEventAction.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 //
  2 // ********************************************************************
  3 // * License and Disclaimer                                           *
  4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.                             *
 10 // *                                                                  *
 11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                                                  *
 18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // ********************************************************************
 25 //
 26 /*
 27  * ============================================================================
 28  *
 29  *       Filename:  CexmcEventAction.cc
 30  *
 31  *    Description:  event action
 32  *
 33  *        Version:  1.0
 34  *        Created:  27.10.2009 22:48:08
 35  *       Revision:  none
 36  *       Compiler:  gcc
 37  *
 38  *         Author:  Alexey Radkov (), 
 39  *        Company:  PNPI
 40  *
 41  * ============================================================================
 42  */
 43 
 44 #include <cmath>
 45 #ifdef CEXMC_USE_PERSISTENCY
 46 #include <boost/archive/binary_oarchive.hpp>
 47 #endif
 48 #include <G4DigiManager.hh>
 49 #include <G4Event.hh>
 50 #include <G4Circle.hh>
 51 #include <G4VisAttributes.hh>
 52 #include <G4VisManager.hh>
 53 #include <G4VTrajectory.hh>
 54 #include <G4TrajectoryContainer.hh>
 55 #include <G4Colour.hh>
 56 #include <G4SystemOfUnits.hh>
 57 #include "CexmcEventAction.hh"
 58 #include "CexmcEventActionMessenger.hh"
 59 #include "CexmcEventInfo.hh"
 60 #include "CexmcEventSObject.hh"
 61 #include "CexmcEventFastSObject.hh"
 62 #include "CexmcTrackingAction.hh"
 63 #include "CexmcChargeExchangeReconstructor.hh"
 64 #include "CexmcRunManager.hh"
 65 #include "CexmcHistoManager.hh"
 66 #include "CexmcRun.hh"
 67 #include "CexmcPhysicsManager.hh"
 68 #include "CexmcProductionModel.hh"
 69 #include "CexmcProductionModelData.hh"
 70 #include "CexmcEnergyDepositDigitizer.hh"
 71 #include "CexmcEnergyDepositStore.hh"
 72 #include "CexmcTrackPointsDigitizer.hh"
 73 #include "CexmcTrackPointsStore.hh"
 74 #include "CexmcTrackPointInfo.hh"
 75 #include "CexmcException.hh"
 76 #include "CexmcCommon.hh"
 77 
 78 
 79 namespace
 80 {
 81     G4double  CexmcSmallCircleScreenSize( 5.0 );
 82     G4double  CexmcBigCircleScreenSize( 10.0 );
 83     G4Colour  CexmcTrackPointsMarkerColour( 0.0, 1.0, 0.4 );
 84     G4Colour  CexmcRecTrackPointsMarkerColour( 1.0, 0.4, 0.0 );
 85 
 86 #ifdef CEXMC_USE_ROOT
 87     inline G4double  CexmcGetKinEnergy( G4double  momentumAmp, G4double  mass )
 88     {
 89         return std::sqrt( momentumAmp * momentumAmp + mass * mass ) - mass;
 90     }
 91 #endif
 92 }
 93 
 94 
 95 CexmcEventAction::CexmcEventAction( CexmcPhysicsManager *  physicsManager_,
 96                                     G4int  verbose_ ) :
 97     physicsManager( physicsManager_ ), reconstructor( NULL ),
 98 #ifdef CEXMC_USE_ROOT
 99     opKinEnergy( 0. ),
100 #endif
101     verbose( verbose_ ), verboseDraw( 4 ), messenger( NULL )
102 {
103     G4DigiManager *  digiManager( G4DigiManager::GetDMpointer() );
104     digiManager->AddNewModule( new CexmcEnergyDepositDigitizer(
105                                                     CexmcEDDigitizerName ) );
106     digiManager->AddNewModule( new CexmcTrackPointsDigitizer(
107                                                     CexmcTPDigitizerName ) );
108     reconstructor = new CexmcChargeExchangeReconstructor(
109                                         physicsManager->GetProductionModel() );
110     messenger = new CexmcEventActionMessenger( this );
111 }
112 
113 
114 CexmcEventAction::~CexmcEventAction()
115 {
116     delete reconstructor;
117     delete messenger;
118 }
119 
120 
121 void  CexmcEventAction::BeamParticleChangeHook( void )
122 {
123     reconstructor->SetupBeamParticle();
124 }
125 
126 
127 void  CexmcEventAction::BeginOfEventAction( const G4Event * )
128 {
129     G4RunManager *         runManager( G4RunManager::GetRunManager() );
130     CexmcTrackingAction *  trackingAction
131             ( static_cast< CexmcTrackingAction * >(
132                         const_cast< G4UserTrackingAction * >(
133                                     runManager->GetUserTrackingAction() ) ) );
134     trackingAction->BeginOfEventAction();
135 
136     physicsManager->ResetNumberOfTriggeredStudiedInteractions();
137 }
138 
139 
140 CexmcEnergyDepositStore *  CexmcEventAction::MakeEnergyDepositStore(
141                                 const CexmcEnergyDepositDigitizer *  digitizer )
142 {
143     G4double  monitorED( digitizer->GetMonitorED() );
144     G4double  vetoCounterEDLeft( digitizer->GetVetoCounterEDLeft() );
145     G4double  vetoCounterEDRight( digitizer->GetVetoCounterEDRight() );
146     G4double  calorimeterEDLeft( digitizer->GetCalorimeterEDLeft() );
147     G4double  calorimeterEDRight( digitizer->GetCalorimeterEDRight() );
148     G4int     calorimeterEDLeftMaxX( digitizer->GetCalorimeterEDLeftMaxX() );
149     G4int     calorimeterEDLeftMaxY( digitizer->GetCalorimeterEDLeftMaxY() );
150     G4int     calorimeterEDRightMaxX( digitizer->GetCalorimeterEDRightMaxX() );
151     G4int     calorimeterEDRightMaxY( digitizer->GetCalorimeterEDRightMaxY() );
152 
153     const CexmcEnergyDepositCalorimeterCollection &
154               calorimeterEDLeftCollection(
155                             digitizer->GetCalorimeterEDLeftCollection() );
156     const CexmcEnergyDepositCalorimeterCollection &
157               calorimeterEDRightCollection(
158                             digitizer->GetCalorimeterEDRightCollection() );
159 
160     /* ATTENTION: return object in heap - must be freed by caller! */
161     return new CexmcEnergyDepositStore( monitorED, vetoCounterEDLeft,
162                     vetoCounterEDRight, calorimeterEDLeft, calorimeterEDRight,
163                     calorimeterEDLeftMaxX, calorimeterEDLeftMaxY,
164                     calorimeterEDRightMaxX, calorimeterEDRightMaxY,
165                     calorimeterEDLeftCollection, calorimeterEDRightCollection );
166 }
167 
168 
169 CexmcTrackPointsStore *  CexmcEventAction::MakeTrackPointsStore(
170                                 const CexmcTrackPointsDigitizer *  digitizer )
171 {
172     const CexmcTrackPointInfo &
173                 monitorTP( digitizer->GetMonitorTP() );
174     const CexmcTrackPointInfo &
175                 targetTPBeamParticle(
176                     digitizer->GetTargetTPBeamParticle() );
177     const CexmcTrackPointInfo &
178                 targetTPOutputParticle(
179                     digitizer->GetTargetTPOutputParticle() );
180     const CexmcTrackPointInfo &
181                 targetTPNucleusParticle(
182                     digitizer->GetTargetTPNucleusParticle() );
183     const CexmcTrackPointInfo &
184                 targetTPOutputParticleDecayProductParticle1(
185                     digitizer->
186                     GetTargetTPOutputParticleDecayProductParticle( 0 ) );
187     const CexmcTrackPointInfo &
188                 targetTPOutputParticleDecayProductParticle2(
189                     digitizer->
190                     GetTargetTPOutputParticleDecayProductParticle( 1 ) );
191     const CexmcTrackPointInfo &
192                 vetoCounterTPLeft(
193                     digitizer->GetVetoCounterTPLeft() );
194     const CexmcTrackPointInfo &
195                 vetoCounterTPRight(
196                     digitizer->GetVetoCounterTPRight() );
197     const CexmcTrackPointInfo &
198                 calorimeterTPLeft(
199                     digitizer->GetCalorimeterTPLeft() );
200     const CexmcTrackPointInfo &
201                 calorimeterTPRight(
202                     digitizer->GetCalorimeterTPRight() );
203 
204     /* ATTENTION: return object in heap - must be freed by caller! */
205     return new CexmcTrackPointsStore( monitorTP, targetTPBeamParticle,
206                   targetTPOutputParticle, targetTPNucleusParticle,
207                   targetTPOutputParticleDecayProductParticle1,
208                   targetTPOutputParticleDecayProductParticle2,
209                   vetoCounterTPLeft, vetoCounterTPRight,
210                   calorimeterTPLeft, calorimeterTPRight );
211 }
212 
213 
214 void  CexmcEventAction::PrintEnergyDeposit(
215                                     const CexmcEnergyDepositStore *  edStore )
216 {
217     G4cout << " --- Energy Deposit" << G4endl;
218     G4cout << "       monitor : " <<
219             G4BestUnit( edStore->monitorED, "Energy" ) << G4endl;
220     G4cout << "        vc (l) : " <<
221             G4BestUnit( edStore->vetoCounterEDLeft, "Energy" ) << G4endl;
222     G4cout << "        vc (r) : " <<
223             G4BestUnit( edStore->vetoCounterEDRight, "Energy" ) << G4endl;
224     G4cout << "       cal (l) : " <<
225             G4BestUnit( edStore->calorimeterEDLeft, "Energy" );
226     G4cout << edStore->calorimeterEDLeftCollection;
227     G4cout << "       cal (r) : " <<
228             G4BestUnit( edStore->calorimeterEDRight, "Energy" );
229     G4cout << edStore->calorimeterEDRightCollection;
230 }
231 
232 
233 void  CexmcEventAction::PrintTrackPoints(
234                                     const CexmcTrackPointsStore *  tpStore )
235 {
236     if ( ! tpStore )
237         return;
238 
239     G4cout << " --- Track Points" << G4endl;
240     G4cout << "       monitor : " << tpStore->monitorTP << G4endl;
241     G4cout << "        target : " << tpStore->targetTPBeamParticle << G4endl;
242     G4cout << "               : " << tpStore->targetTPOutputParticle << G4endl;
243     G4cout << "               : " << tpStore->targetTPNucleusParticle << G4endl;
244     G4cout << "               : " <<
245             tpStore->targetTPOutputParticleDecayProductParticle1 << G4endl;
246     G4cout << "               : " <<
247             tpStore->targetTPOutputParticleDecayProductParticle2 << G4endl;
248     G4cout << "        vc (l) : " << tpStore->vetoCounterTPLeft << G4endl;
249     G4cout << "        vc (r) : " << tpStore->vetoCounterTPRight << G4endl;
250     G4cout << "       cal (l) : " << tpStore->calorimeterTPLeft << G4endl;
251     G4cout << "       cal (r) : " << tpStore->calorimeterTPRight << G4endl;
252     G4cout << "      ---" << G4endl;
253     G4cout << "      angle between the " <<
254         tpStore->targetTPOutputParticle.particle->GetParticleName() <<
255         " decay products : " <<
256         tpStore->targetTPOutputParticleDecayProductParticle1.directionWorld.
257             angle(
258         tpStore->targetTPOutputParticleDecayProductParticle2.directionWorld ) /
259             deg << " deg" << G4endl;
260 }
261 
262 
263 void  CexmcEventAction::PrintProductionModelData(
264                                 const CexmcAngularRangeList &  angularRanges,
265                                 const CexmcProductionModelData &  pmData )
266 {
267     G4cout << " --- Triggered angular ranges: " << angularRanges;
268     G4cout << " --- Production model data: " << pmData;
269 }
270 
271 
272 void  CexmcEventAction::PrintReconstructedData(
273                     const CexmcAngularRangeList &  triggeredRecAngularRanges,
274                     const CexmcAngularRange &  angularGap ) const
275 {
276     G4cout << " --- Reconstructed data: " << G4endl;
277     G4cout << "       -- entry points:" << G4endl;
278     G4cout << "              left: " << G4BestUnit(
279         reconstructor->GetCalorimeterEPLeftPosition(), "Length" ) << G4endl;
280     G4cout << "             right: " << G4BestUnit(
281         reconstructor->GetCalorimeterEPRightPosition(), "Length" ) << G4endl;
282     G4cout << "            target: " << G4BestUnit(
283         reconstructor->GetTargetEPPosition(), "Length" ) << G4endl;
284     G4cout << "       -- the angle: " << reconstructor->GetTheAngle() / deg <<
285         " deg" << G4endl;
286     G4cout << "       -- mass of the output particle: " << G4BestUnit(
287         reconstructor->GetOutputParticleMass(), "Energy" ) << G4endl;
288     G4cout << "       -- mass of the nucleus output particle: " << G4BestUnit(
289         reconstructor->GetNucleusOutputParticleMass(), "Energy" ) << G4endl;
290     if ( reconstructor->IsMassCutUsed() )
291     {
292         if ( reconstructor->HasMassCutTriggered() )
293             G4cout << "            < mass cut passed >" << G4endl;
294         else
295             G4cout << "            < mass cut failed >" << G4endl;
296     }
297     if ( reconstructor->IsAbsorbedEnergyCutUsed() )
298     {
299         if ( reconstructor->HasAbsorbedEnergyCutTriggered() )
300             G4cout << "            < absorbed energy cut passed >" << G4endl;
301         else
302             G4cout << "            < absorbed energy cut failed >" << G4endl;
303     }
304     const CexmcProductionModelData &  pmData(
305                                     reconstructor->GetProductionModelData() );
306     G4cout << "       -- production model data: " << pmData;
307     G4cout << "       -- triggered angular ranges: ";
308     if ( triggeredRecAngularRanges.empty() )
309         G4cout << "< orphan detected, gap " << angularGap << " >" << G4endl;
310     else
311         G4cout << triggeredRecAngularRanges;
312 }
313 
314 
315 #ifdef CEXMC_USE_ROOT
316 
317 void  CexmcEventAction::FillEDTHistos( const CexmcEnergyDepositStore *  edStore,
318                 const CexmcAngularRangeList &  triggeredAngularRanges ) const
319 {
320     CexmcHistoManager *  histoManager( CexmcHistoManager::Instance() );
321 
322     histoManager->Add( CexmcAbsorbedEnergy_EDT_Histo, 0,
323                        edStore->calorimeterEDLeft,
324                        edStore->calorimeterEDRight );
325 
326     for ( CexmcAngularRangeList::const_iterator
327                         k( triggeredAngularRanges.begin() );
328                                     k != triggeredAngularRanges.end(); ++k )
329     {
330         histoManager->Add( CexmcAbsEnInLeftCalorimeter_ARReal_EDT_Histo,
331                            k->index, edStore->calorimeterEDLeft );
332         histoManager->Add( CexmcAbsEnInRightCalorimeter_ARReal_EDT_Histo,
333                            k->index, edStore->calorimeterEDRight );
334     }
335 }
336 
337 
338 void  CexmcEventAction::FillTPTHistos( const CexmcTrackPointsStore *  tpStore,
339                 const CexmcProductionModelData &  pmData,
340                 const CexmcAngularRangeList &  triggeredAngularRanges ) const
341 {
342     CexmcHistoManager *  histoManager( CexmcHistoManager::Instance() );
343 
344     if ( tpStore->monitorTP.IsValid() )
345     {
346         histoManager->Add( CexmcMomentumBP_TPT_Histo, 0,
347                            tpStore->monitorTP.momentumAmp );
348         histoManager->Add( CexmcTPInMonitor_TPT_Histo, 0,
349                            tpStore->monitorTP.positionLocal.x(),
350                            tpStore->monitorTP.positionLocal.y() );
351     }
352 
353     if ( tpStore->targetTPOutputParticle.IsValid() )
354     {
355         histoManager->Add( CexmcTPInTarget_TPT_Histo, 0,
356                            tpStore->targetTPOutputParticle.positionLocal.x(),
357                            tpStore->targetTPOutputParticle.positionLocal.y(),
358                            tpStore->targetTPOutputParticle.positionLocal.z() );
359         if ( histoManager->GetVerboseLevel() > 0 )
360         {
361             histoManager->Add( CexmcMomentumIP_TPT_Histo, 0,
362                                pmData.incidentParticleLAB.rho() );
363         }
364     }
365 
366     for ( CexmcAngularRangeList::const_iterator
367                         k( triggeredAngularRanges.begin() );
368                                     k != triggeredAngularRanges.end(); ++k )
369     {
370         if ( tpStore->calorimeterTPLeft.IsValid() )
371         {
372             /* kinetic energy and momentum of gamma are equal */
373             G4double  kinEnergy( tpStore->calorimeterTPLeft.momentumAmp );
374             histoManager->Add( CexmcKinEnAtLeftCalorimeter_ARReal_TPT_Histo,
375                                k->index, kinEnergy );
376         }
377         if ( tpStore->calorimeterTPRight.IsValid() )
378         {
379             G4double  kinEnergy( tpStore->calorimeterTPRight.momentumAmp );
380             histoManager->Add( CexmcKinEnAtRightCalorimeter_ARReal_TPT_Histo,
381                                k->index, kinEnergy );
382         }
383         if ( tpStore->targetTPOutputParticle.IsValid() )
384         {
385             histoManager->Add( CexmcTPInTarget_ARReal_TPT_Histo, k->index,
386                            tpStore->targetTPOutputParticle.positionLocal.x(),
387                            tpStore->targetTPOutputParticle.positionLocal.y(),
388                            tpStore->targetTPOutputParticle.positionLocal.z() );
389             histoManager->Add( CexmcKinEnOP_LAB_ARReal_TPT_Histo, k->index,
390                                opKinEnergy );
391             histoManager->Add( CexmcAngleOP_SCM_ARReal_TPT_Histo, k->index,
392                                pmData.outputParticleSCM.cosTheta() );
393         }
394         if ( tpStore->targetTPOutputParticleDecayProductParticle1.IsValid() &&
395              tpStore->targetTPOutputParticleDecayProductParticle2.IsValid() )
396         {
397             G4double  openAngle(
398                         tpStore->targetTPOutputParticleDecayProductParticle1.
399                         directionWorld.angle( tpStore->
400                                 targetTPOutputParticleDecayProductParticle2.
401                                         directionWorld ) / deg );
402             histoManager->Add( CexmcOpenAngle_ARReal_TPT_Histo, k->index,
403                                openAngle );
404         }
405     }
406 }
407 
408 
409 void  CexmcEventAction::FillRTHistos( G4bool  reconstructorHasFullTrigger,
410                 const CexmcEnergyDepositStore *  edStore,
411                 const CexmcTrackPointsStore *  tpStore,
412                 const CexmcProductionModelData &  pmData,
413                 const CexmcAngularRangeList &  triggeredAngularRanges ) const
414 {
415     CexmcHistoManager *  histoManager( CexmcHistoManager::Instance() );
416 
417     G4double    opMass( reconstructor->GetOutputParticleMass() );
418     G4double    nopMass( reconstructor->GetNucleusOutputParticleMass() );
419 
420     histoManager->Add( CexmcRecMasses_EDT_Histo, 0, opMass, nopMass );
421 
422     for ( CexmcAngularRangeList::const_iterator
423                         k( triggeredAngularRanges.begin() );
424                                     k != triggeredAngularRanges.end(); ++k )
425     {
426         if ( tpStore->calorimeterTPLeft.IsValid() )
427         {
428             histoManager->Add( CexmcOPDPAtLeftCalorimeter_ARReal_EDT_Histo,
429                                k->index,
430                                tpStore->calorimeterTPLeft.positionLocal.x(),
431                                tpStore->calorimeterTPLeft.positionLocal.y() );
432         }
433         if ( tpStore->calorimeterTPRight.IsValid() )
434         {
435             histoManager->Add( CexmcOPDPAtRightCalorimeter_ARReal_EDT_Histo,
436                                k->index,
437                                tpStore->calorimeterTPRight.positionLocal.x(),
438                                tpStore->calorimeterTPRight.positionLocal.y() );
439         }
440         histoManager->Add( CexmcRecOPDPAtLeftCalorimeter_ARReal_EDT_Histo,
441                            k->index,
442                            reconstructor->GetCalorimeterEPLeftPosition().x(),
443                            reconstructor->GetCalorimeterEPLeftPosition().y() );
444         histoManager->Add( CexmcRecOPDPAtRightCalorimeter_ARReal_EDT_Histo,
445                            k->index,
446                            reconstructor->GetCalorimeterEPRightPosition().x(),
447                            reconstructor->GetCalorimeterEPRightPosition().y() );
448     }
449 
450     if ( ! reconstructorHasFullTrigger )
451         return;
452 
453     if ( tpStore->monitorTP.IsValid() )
454     {
455         histoManager->Add( CexmcMomentumBP_RT_Histo, 0,
456                            tpStore->monitorTP.momentumAmp );
457     }
458 
459     if ( tpStore->targetTPOutputParticle.IsValid() )
460     {
461         histoManager->Add( CexmcTPInTarget_RT_Histo, 0,
462                            tpStore->targetTPOutputParticle.positionLocal.x(),
463                            tpStore->targetTPOutputParticle.positionLocal.y(),
464                            tpStore->targetTPOutputParticle.positionLocal.z() );
465     }
466 
467     histoManager->Add( CexmcRecMasses_RT_Histo, 0,
468                        reconstructor->GetOutputParticleMass(),
469                        reconstructor->GetNucleusOutputParticleMass() );
470 
471     histoManager->Add( CexmcAbsorbedEnergy_RT_Histo, 0,
472                        edStore->calorimeterEDLeft,
473                        edStore->calorimeterEDRight );
474 
475     G4double  recCosTheta( reconstructor->GetProductionModelData().
476                                                outputParticleSCM.cosTheta());
477 
478     for ( CexmcAngularRangeList::const_iterator
479                         k( triggeredAngularRanges.begin() );
480                                     k != triggeredAngularRanges.end(); ++k )
481     {
482         histoManager->Add( CexmcRecMassOP_ARReal_RT_Histo, k->index, opMass );
483         histoManager->Add( CexmcRecMassNOP_ARReal_RT_Histo, k->index, nopMass );
484         if ( tpStore->calorimeterTPLeft.IsValid() )
485         {
486             G4double  kinEnergy( tpStore->calorimeterTPLeft.momentumAmp );
487             histoManager->Add( CexmcKinEnAtLeftCalorimeter_ARReal_RT_Histo,
488                                k->index, kinEnergy );
489             histoManager->Add( CexmcMissEnFromLeftCalorimeter_ARReal_RT_Histo,
490                                k->index,
491                                kinEnergy - edStore->calorimeterEDLeft );
492         }
493         if ( tpStore->calorimeterTPRight.IsValid() )
494         {
495             G4double  kinEnergy( tpStore->calorimeterTPRight.momentumAmp );
496             histoManager->Add( CexmcKinEnAtRightCalorimeter_ARReal_RT_Histo,
497                                k->index, kinEnergy );
498             histoManager->Add( CexmcMissEnFromRightCalorimeter_ARReal_RT_Histo,
499                                k->index,
500                                kinEnergy - edStore->calorimeterEDRight );
501         }
502         if ( tpStore->targetTPOutputParticle.IsValid() )
503         {
504             histoManager->Add( CexmcTPInTarget_ARReal_RT_Histo, k->index,
505                            tpStore->targetTPOutputParticle.positionLocal.x(),
506                            tpStore->targetTPOutputParticle.positionLocal.y(),
507                            tpStore->targetTPOutputParticle.positionLocal.z() );
508             histoManager->Add( CexmcKinEnOP_LAB_ARReal_RT_Histo, k->index,
509                                opKinEnergy );
510             histoManager->Add( CexmcAngleOP_SCM_ARReal_RT_Histo, k->index,
511                                pmData.outputParticleSCM.cosTheta() );
512             G4double  diffCosTheta( pmData.outputParticleSCM.cosTheta() -
513                                     recCosTheta );
514             histoManager->Add( CexmcDiffAngleOP_SCM_ARReal_RT_Histo, k->index,
515                                diffCosTheta );
516         }
517         if ( tpStore->targetTPOutputParticleDecayProductParticle1.IsValid() &&
518              tpStore->targetTPOutputParticleDecayProductParticle2.IsValid() )
519         {
520             G4double  openAngle(
521                         tpStore->targetTPOutputParticleDecayProductParticle1.
522                         directionWorld.angle( tpStore->
523                                 targetTPOutputParticleDecayProductParticle2.
524                                         directionWorld ) / deg );
525             histoManager->Add( CexmcOpenAngle_ARReal_RT_Histo, k->index,
526                                openAngle );
527             G4double  diffOpenAngle( openAngle - reconstructor->GetTheAngle() /
528                                      deg );
529             histoManager->Add( CexmcDiffOpenAngle_ARReal_RT_Histo, k->index,
530                                diffOpenAngle );
531         }
532         if ( tpStore->calorimeterTPLeft.IsValid() )
533         {
534             histoManager->Add( CexmcOPDPAtLeftCalorimeter_ARReal_RT_Histo,
535                                k->index,
536                                tpStore->calorimeterTPLeft.positionLocal.x(),
537                                tpStore->calorimeterTPLeft.positionLocal.y() );
538         }
539         if ( tpStore->calorimeterTPRight.IsValid() )
540         {
541             histoManager->Add( CexmcOPDPAtRightCalorimeter_ARReal_RT_Histo,
542                                k->index,
543                                tpStore->calorimeterTPRight.positionLocal.x(),
544                                tpStore->calorimeterTPRight.positionLocal.y() );
545         }
546         histoManager->Add( CexmcAbsEnInLeftCalorimeter_ARReal_RT_Histo,
547                            k->index, edStore->calorimeterEDLeft );
548         histoManager->Add( CexmcAbsEnInRightCalorimeter_ARReal_RT_Histo,
549                            k->index, edStore->calorimeterEDRight );
550         histoManager->Add( CexmcRecAngleOP_SCM_ARReal_RT_Histo,
551                            k->index, recCosTheta );
552         histoManager->Add( CexmcRecOpenAngle_ARReal_RT_Histo,
553                            k->index, reconstructor->GetTheAngle() / deg );
554         histoManager->Add( CexmcRecOPDPAtLeftCalorimeter_ARReal_RT_Histo,
555                            k->index,
556                            reconstructor->GetCalorimeterEPLeftPosition().x(),
557                            reconstructor->GetCalorimeterEPLeftPosition().y() );
558         histoManager->Add( CexmcRecOPDPAtRightCalorimeter_ARReal_RT_Histo,
559                            k->index,
560                            reconstructor->GetCalorimeterEPRightPosition().x(),
561                            reconstructor->GetCalorimeterEPRightPosition().y() );
562     }
563 }
564 
565 #endif
566 
567 
568 void  CexmcEventAction::DrawTrajectories( const G4Event *  event )
569 {
570     G4VisManager *  visManager( static_cast< G4VisManager * >(
571                                     G4VVisManager::GetConcreteInstance() ) );
572     if ( ! visManager || ! visManager->GetCurrentGraphicsSystem() )
573         return;
574 
575     G4int                    nTraj( 0 );
576     G4TrajectoryContainer *  trajContainer( event->GetTrajectoryContainer() );
577 
578     if ( ! trajContainer )
579         return;
580 
581     nTraj = trajContainer->entries();
582 
583     for ( int  i( 0 ); i < nTraj; ++i )
584     {
585         G4VTrajectory *  traj( ( *trajContainer )[ i ] );
586         traj->DrawTrajectory();
587     }
588 }
589 
590 
591 void  CexmcEventAction::DrawTrackPoints(
592                                 const CexmcTrackPointsStore *  tpStore ) const
593 {
594     G4VisManager *  visManager( static_cast< G4VisManager * >(
595                                     G4VVisManager::GetConcreteInstance() ) );
596     if ( ! visManager || ! visManager->GetCurrentGraphicsSystem() )
597         return;
598 
599     G4Circle         circle;
600     G4VisAttributes  visAttributes( CexmcTrackPointsMarkerColour );
601     circle.SetScreenSize( CexmcSmallCircleScreenSize );
602     circle.SetFillStyle( G4Circle::filled );
603     circle.SetVisAttributes( visAttributes );
604 
605     if ( tpStore->monitorTP.IsValid() )
606     {
607         circle.SetPosition( tpStore->monitorTP.positionWorld );
608         visManager->Draw( circle );
609     }
610 
611     if ( tpStore->targetTPBeamParticle.IsValid() )
612     {
613         circle.SetPosition( tpStore->targetTPBeamParticle.positionWorld );
614         visManager->Draw( circle );
615     }
616 
617     if ( tpStore->targetTPOutputParticle.IsValid() )
618     {
619         circle.SetPosition( tpStore->targetTPOutputParticle.positionWorld );
620         visManager->Draw( circle );
621     }
622 
623     if ( tpStore->vetoCounterTPLeft.IsValid() )
624     {
625         circle.SetPosition( tpStore->vetoCounterTPLeft.positionWorld );
626         visManager->Draw( circle );
627     }
628 
629     if ( tpStore->vetoCounterTPRight.IsValid() )
630     {
631         circle.SetPosition( tpStore->vetoCounterTPRight.positionWorld );
632         visManager->Draw( circle );
633     }
634 
635     if ( tpStore->calorimeterTPLeft.IsValid() )
636     {
637         circle.SetPosition( tpStore->calorimeterTPLeft.positionWorld );
638         visManager->Draw( circle );
639     }
640 
641     if ( tpStore->calorimeterTPRight.IsValid() )
642     {
643         circle.SetPosition( tpStore->calorimeterTPRight.positionWorld );
644         visManager->Draw( circle );
645     }
646 }
647 
648 
649 void  CexmcEventAction::DrawReconstructionData( void )
650 {
651     G4VisManager *  visManager( static_cast< G4VisManager * >(
652                                     G4VVisManager::GetConcreteInstance() ) );
653     if ( ! visManager || ! visManager->GetCurrentGraphicsSystem() )
654         return;
655 
656     G4Circle  circle( reconstructor->GetTargetEPWorldPosition() );
657     circle.SetScreenSize( CexmcSmallCircleScreenSize );
658     circle.SetFillStyle( G4Circle::filled );
659     G4VisAttributes  visAttributes( CexmcRecTrackPointsMarkerColour );
660     circle.SetVisAttributes( visAttributes );
661     visManager->Draw( circle );
662 
663     circle.SetScreenSize( CexmcBigCircleScreenSize );
664     circle.SetPosition( reconstructor->GetCalorimeterEPLeftWorldPosition() );
665     visManager->Draw( circle );
666 
667     circle.SetPosition( reconstructor->GetCalorimeterEPRightWorldPosition() );
668     visManager->Draw( circle );
669 }
670 
671 
672 void  CexmcEventAction::UpdateRunHits(
673                                     const CexmcAngularRangeList &  aRangesReal,
674                                     const CexmcAngularRangeList &  aRangesRec,
675                                     G4bool  tpDigitizerHasTriggered,
676                                     G4bool  edDigitizerHasTriggered,
677                                     G4bool  edDigitizerMonitorHasTriggered,
678                                     G4bool  reconstructorHasFullTrigger,
679                                     const CexmcAngularRange &  aGap )
680 {
681     G4RunManager *    runManager( G4RunManager::GetRunManager() );
682     const CexmcRun *  run( static_cast< const CexmcRun * >(
683                                                 runManager->GetCurrentRun() ) );
684     CexmcRun *        theRun( const_cast< CexmcRun * >( run ) );
685 
686     if ( tpDigitizerHasTriggered )
687     {
688         for ( CexmcAngularRangeList::const_iterator  k( aRangesReal.begin() );
689                                                 k != aRangesReal.end(); ++k )
690         {
691             theRun->IncrementNmbOfHitsSampledFull( k->index );
692             if ( edDigitizerMonitorHasTriggered )
693                 theRun->IncrementNmbOfHitsSampled( k->index );
694             if ( reconstructorHasFullTrigger )
695                 theRun->IncrementNmbOfHitsTriggeredRealRange( k->index );
696         }
697         if ( reconstructorHasFullTrigger )
698         {
699             if ( aRangesRec.empty() )
700             {
701                 theRun->IncrementNmbOfOrphanHits( aGap.index );
702             }
703             else
704             {
705                 for ( CexmcAngularRangeList::const_iterator
706                         k( aRangesRec.begin() ); k != aRangesRec.end(); ++k )
707                 {
708                     theRun->IncrementNmbOfHitsTriggeredRecRange( k->index );
709                 }
710             }
711         }
712     }
713     else
714     {
715         if ( edDigitizerHasTriggered )
716             theRun->IncrementNmbOfFalseHitsTriggeredEDT();
717         if ( reconstructorHasFullTrigger )
718             theRun->IncrementNmbOfFalseHitsTriggeredRec();
719     }
720 }
721 
722 
723 #ifdef CEXMC_USE_PERSISTENCY
724 
725 void  CexmcEventAction::SaveEvent( const G4Event *  event,
726                                    G4bool  edDigitizerHasTriggered,
727                                    const CexmcEnergyDepositStore *  edStore,
728                                    const CexmcTrackPointsStore *  tpStore,
729                                    const CexmcProductionModelData &  pmData )
730 {
731     CexmcRunManager *  runManager( static_cast< CexmcRunManager * >(
732                                             G4RunManager::GetRunManager() ) );
733     if ( ! runManager->ProjectIsSaved() )
734         return;
735 
736     if ( runManager->GetEventDataVerboseLevel() == CexmcWriteNoEventData )
737         return;
738 
739     if ( ! edDigitizerHasTriggered && runManager->GetEventDataVerboseLevel() !=
740                                                 CexmcWriteEventDataOnEveryTPT )
741         return;
742 
743     boost::archive::binary_oarchive *  archive(
744                                             runManager->GetEventsArchive() );
745     if ( archive )
746     {
747         CexmcEventSObject  sObject = { event->GetEventID(),
748             edDigitizerHasTriggered, edStore->monitorED,
749             edStore->vetoCounterEDLeft, edStore->vetoCounterEDRight,
750             edStore->calorimeterEDLeft, edStore->calorimeterEDRight,
751             edStore->calorimeterEDLeftCollection,
752             edStore->calorimeterEDRightCollection,
753             tpStore->monitorTP, tpStore->targetTPBeamParticle,
754             tpStore->targetTPOutputParticle, tpStore->targetTPNucleusParticle,
755             tpStore->targetTPOutputParticleDecayProductParticle1,
756             tpStore->targetTPOutputParticleDecayProductParticle2,
757             tpStore->vetoCounterTPLeft, tpStore->vetoCounterTPRight,
758             tpStore->calorimeterTPLeft, tpStore->calorimeterTPRight, pmData };
759         archive->operator<<( sObject );
760         const CexmcRun *  run( static_cast< const CexmcRun * >(
761                                                 runManager->GetCurrentRun() ) );
762         CexmcRun *        theRun( const_cast< CexmcRun * >( run ) );
763         theRun->IncrementNmbOfSavedEvents();
764     }
765 }
766 
767 
768 void  CexmcEventAction::SaveEventFast( const G4Event *  event,
769                                        G4bool  tpDigitizerHasTriggered,
770                                        G4bool  edDigitizerHasTriggered,
771                                        G4bool  edDigitizerMonitorHasTriggered,
772                                        G4double  opCosThetaSCM )
773 {
774     CexmcRunManager *  runManager( static_cast< CexmcRunManager * >(
775                                             G4RunManager::GetRunManager() ) );
776     if ( ! runManager->ProjectIsSaved() )
777         return;
778 
779     if ( runManager->GetEventDataVerboseLevel() == CexmcWriteNoEventData )
780         return;
781 
782     boost::archive::binary_oarchive *  archive(
783                                         runManager->GetFastEventsArchive() );
784     if ( archive )
785     {
786         if ( ! tpDigitizerHasTriggered )
787             opCosThetaSCM = CexmcInvalidCosTheta;
788 
789         CexmcEventFastSObject  sObject = { event->GetEventID(), opCosThetaSCM,
790                                            edDigitizerHasTriggered,
791                                            edDigitizerMonitorHasTriggered };
792         archive->operator<<( sObject );
793         const CexmcRun *  run( static_cast< const CexmcRun * >(
794                                                 runManager->GetCurrentRun() ) );
795         CexmcRun *        theRun( const_cast< CexmcRun * >( run ) );
796         theRun->IncrementNmbOfSavedFastEvents();
797     }
798 }
799 
800 #endif
801 
802 
803 void  CexmcEventAction::EndOfEventAction( const G4Event *  event )
804 {
805     G4DigiManager *                digiManager( G4DigiManager::GetDMpointer() );
806     CexmcEnergyDepositDigitizer *  energyDepositDigitizer(
807             static_cast< CexmcEnergyDepositDigitizer * >( digiManager->
808                                 FindDigitizerModule( CexmcEDDigitizerName ) ) );
809     CexmcTrackPointsDigitizer *    trackPointsDigitizer(
810             static_cast< CexmcTrackPointsDigitizer * >( digiManager->
811                                 FindDigitizerModule( CexmcTPDigitizerName ) ) );
812 
813     energyDepositDigitizer->Digitize();
814     trackPointsDigitizer->Digitize();
815 
816     G4bool  edDigitizerMonitorHasTriggered(
817                                 energyDepositDigitizer->MonitorHasTriggered() );
818     G4bool  edDigitizerHasTriggered( false );
819 
820     CexmcEventInfo *  eventInfo( static_cast< CexmcEventInfo * >(
821                                                 event->GetUserInformation() ) );
822     if ( ! eventInfo || eventInfo->EdTriggerIsOk() )
823         edDigitizerHasTriggered = energyDepositDigitizer->HasTriggered();
824 
825     G4bool  tpDigitizerHasTriggered( trackPointsDigitizer->HasTriggered() );
826     G4bool  reconstructorHasBasicTrigger( false );
827     G4bool  reconstructorHasFullTrigger( false );
828 
829     CexmcEnergyDepositStore *  edStore( MakeEnergyDepositStore(
830                                                     energyDepositDigitizer ) );
831     CexmcTrackPointsStore *    tpStore( MakeTrackPointsStore(
832                                                     trackPointsDigitizer ) );
833 
834     try
835     {
836         CexmcProductionModel *  productionModel(
837                                         physicsManager->GetProductionModel() );
838 
839         if ( ! productionModel )
840             throw CexmcException( CexmcWeirdException );
841 
842         const CexmcAngularRangeList &     angularRanges(
843                                 productionModel->GetAngularRanges() );
844         const CexmcAngularRangeList &     triggeredAngularRanges(
845                                 productionModel->GetTriggeredAngularRanges() );
846         const CexmcProductionModelData &  pmData(
847                                 productionModel->GetProductionModelData() );
848 
849         if ( edDigitizerHasTriggered )
850         {
851             reconstructor->Reconstruct( edStore );
852             reconstructorHasBasicTrigger = reconstructor->HasBasicTrigger();
853             reconstructorHasFullTrigger = reconstructor->HasFullTrigger();
854         }
855 
856         CexmcAngularRangeList  triggeredRecAngularRanges;
857 
858         if ( reconstructorHasBasicTrigger )
859         {
860             for ( CexmcAngularRangeList::const_iterator
861                   k( angularRanges.begin() ); k != angularRanges.end(); ++k )
862             {
863                 G4double  cosTheta( reconstructor->GetProductionModelData().
864                                     outputParticleSCM.cosTheta() );
865                 if ( cosTheta <= k->top && cosTheta > k->bottom )
866                     triggeredRecAngularRanges.push_back( CexmcAngularRange(
867                                                 k->top, k->bottom, k->index ) );
868             }
869         }
870 
871         CexmcAngularRange  angularGap( 0.0, 0.0, 0 );
872         if ( triggeredRecAngularRanges.empty() )
873         {
874             CexmcAngularRangeList  angularGaps;
875             GetAngularGaps( angularRanges, angularGaps );
876             for ( CexmcAngularRangeList::const_iterator
877                     k( angularGaps.begin() ); k != angularGaps.end(); ++k )
878             {
879                 G4double  cosTheta( reconstructor->GetProductionModelData().
880                                     outputParticleSCM.cosTheta() );
881                 if ( cosTheta <= k->top && cosTheta > k->bottom )
882                 {
883                     angularGap = *k;
884                     break;
885                 }
886             }
887         }
888 
889         UpdateRunHits( triggeredAngularRanges, triggeredRecAngularRanges,
890                        tpDigitizerHasTriggered, edDigitizerHasTriggered,
891                        edDigitizerMonitorHasTriggered,
892                        reconstructorHasFullTrigger, angularGap );
893 
894         if ( verbose > 0 )
895         {
896             G4bool  printMessages( verbose > 3 ||
897                         ( ( verbose == 1 ) && tpDigitizerHasTriggered ) ||
898                         ( ( verbose == 2 ) && edDigitizerHasTriggered ) ||
899                         ( ( verbose == 3 ) && ( tpDigitizerHasTriggered ||
900                                                 edDigitizerHasTriggered ) ) );
901             if ( printMessages )
902             {
903                 G4cout << "Event " << event->GetEventID() << G4endl;
904                 if ( tpDigitizerHasTriggered )
905                 {
906                     PrintTrackPoints( tpStore );
907                     PrintProductionModelData( triggeredAngularRanges, pmData );
908                 }
909                 if ( reconstructorHasBasicTrigger )
910                     PrintReconstructedData( triggeredRecAngularRanges,
911                                             angularGap );
912                 if ( edDigitizerHasTriggered )
913                     PrintEnergyDeposit( edStore );
914             }
915         }
916 
917         if ( verboseDraw > 0 )
918         {
919             G4bool  drawTrajectories( verboseDraw > 3 ||
920                         ( ( verboseDraw == 1 ) && tpDigitizerHasTriggered ) ||
921                         ( ( verboseDraw == 2 ) && edDigitizerHasTriggered ) ||
922                         ( ( verboseDraw == 3 ) && ( tpDigitizerHasTriggered ||
923                                                 edDigitizerHasTriggered ) ) );
924             if ( drawTrajectories )
925             {
926                 DrawTrajectories( event );
927                 if ( tpDigitizerHasTriggered )
928                     DrawTrackPoints( tpStore );
929                 if ( reconstructorHasBasicTrigger )
930                     DrawReconstructionData();
931             }
932         }
933 
934 #ifdef CEXMC_USE_PERSISTENCY
935         if ( edDigitizerHasTriggered || tpDigitizerHasTriggered )
936         {
937             SaveEventFast( event, tpDigitizerHasTriggered,
938                            edDigitizerHasTriggered,
939                            edDigitizerMonitorHasTriggered,
940                            pmData.outputParticleSCM.cosTheta() );
941             SaveEvent( event, edDigitizerHasTriggered, edStore, tpStore,
942                        pmData );
943         }
944 #endif
945 
946 #ifdef CEXMC_USE_ROOT
947         /* opKinEnergy will be used in several histos */
948         if ( tpStore->targetTPOutputParticle.IsValid() )
949         {
950             opKinEnergy = CexmcGetKinEnergy(
951                     tpStore->targetTPOutputParticle.momentumAmp,
952                     tpStore->targetTPOutputParticle.particle->GetPDGMass() );
953         }
954 
955         if ( edDigitizerHasTriggered )
956             FillEDTHistos( edStore, triggeredAngularRanges );
957 
958         /* fill TPT histos only when the monitor has triggered because events
959          * when it was missed have less value for us */
960         if ( tpDigitizerHasTriggered && edDigitizerMonitorHasTriggered )
961             FillTPTHistos( tpStore, pmData, triggeredAngularRanges );
962 
963         if ( reconstructorHasBasicTrigger )
964             FillRTHistos( reconstructorHasFullTrigger, edStore, tpStore,
965                           pmData, triggeredAngularRanges );
966 #endif
967 
968         G4Event *  theEvent( const_cast< G4Event * >( event ) );
969         if ( eventInfo )
970         {
971             delete eventInfo;
972             theEvent->SetUserInformation( NULL );
973         }
974         theEvent->SetUserInformation( new CexmcEventInfo(
975                                                 edDigitizerHasTriggered,
976                                                 tpDigitizerHasTriggered,
977                                                 reconstructorHasFullTrigger ) );
978     }
979     catch ( CexmcException &  e )
980     {
981         G4cout << e.what() << G4endl;
982     }
983     catch ( ... )
984     {
985         G4cout << "Unknown exception caught" << G4endl;
986     }
987 
988     delete edStore;
989     delete tpStore;
990 }
991 
992