Problem 1499

Summary: Geant4 10.0 beta: impossible to draw trajectories from user end of event actions
Product: Geant4 Reporter: Alexey <alexey.radkov>
Component: visualization/modelingAssignee: John.Allison
Status: RESOLVED FIXED    
Severity: trivial    
Priority: P5    
Version: other   
Hardware: All   
OS: All   

Description Alexey 2013-07-22 23:18:08 CEST
Hi.

I draw trajectories from user end of event action in code like that:

void  CexmcEventAction::DrawTrajectories( const G4Event *  event )
{
    G4VisManager *  visManager( static_cast< G4VisManager * >(
                                    G4VVisManager::GetConcreteInstance() ) );
    if ( ! visManager || ! visManager->GetCurrentGraphicsSystem() )
        return;

    G4int                    nTraj( 0 );
    G4TrajectoryContainer *  trajContainer( event->GetTrajectoryContainer() );

    if ( ! trajContainer )
        return;

    nTraj = trajContainer->entries();

    for ( int  i( 0 ); i < nTraj; ++i )
    {
        G4VTrajectory *  traj( ( *trajContainer )[ i ] );
        traj->DrawTrajectory();
    }
}

And i do not normally use /vis/scene/add/trajectories.

Since Geant4 0.10 beta trajectories are no longer drawn. After investigation i found that the issue is in the new code of G4VisManager::DispatchToModel(). Since the previous version there were added additional checks for IsValidView() and trajectoriesModel that is pointer returned by dynamic cast from fpSceneHandler->GetModel(). In my case IsValidView() is OK, but trajectoriesModel is NULL and therefore trajectories is no longer drawn.

Looks like this check was added to serialize access to scene models during "normal" drawing process (e.g. when add/trajectories was set), but calling DrawTrajectories from within EndOfEventAction() breaks this "normal" drawing process and cannot be accomplished in the new Geant4 10.0 beta.

Cheers, Alexey.
Comment 1 John.Allison 2013-07-22 23:59:34 CEST
If you do not

  /vis/scene/addTrajectories

you must stil

  /tracking/storeTrajectory

(Let me know if that is not the problem.)
Comment 2 Alexey 2013-07-23 00:10:35 CEST
No. This is not the problem. I used "/tracking/storeTrajectory 1" always during 9.x series and now. Actually removing mentioned check against trajectoriesModel fixes my issue and trajectorries get drawn well.
Comment 3 John.Allison 2013-07-23 00:18:36 CEST
OK.  Great!
Comment 4 Alexey 2013-07-23 00:29:55 CEST
Looks like i misguided you in my latest comment. I removed check in G4VisManager::DispatchToModel() but not in my own code. So i think that the issue still exists!
Comment 5 John.Allison 2013-07-23 09:06:36 CEST
Away on holiday at the moment so not able to study your problem in detail but it certainly IS possible to draw trajectories and here is a example I happen to have to hand.

#include "G4VVisManager.hh"
#include "G4VTrajectory.hh"
void B1EventAction::EndOfEventAction(const G4Event* event)
{
  G4TrajectoryContainer* TC = event -> GetTrajectoryContainer ();
  if (!TC) return;

  G4VVisManager* pVVisManager = G4VVisManager::GetConcreteInstance();
  if (!pVVisManager) return;

  pVVisManager->BeginDraw();
  for (G4int iT = 0; iT < TC->entries(); iT++) {
    G4VTrajectory* trajectory = (*TC) [iT];
    if (!trajectory) continue;
    for (G4int iPoint = 0; iPoint < trajectory->GetPointEntries(); iPoint++) {
        pVVisManager->Draw(*trajectory);
    }
  }
  pVVisManager->EndDraw();
}
Comment 6 Alexey 2013-07-23 09:35:54 CEST
Thank you. But this did not work for me. The following change in my code makes trajectories get drawn:


void  CexmcEventAction::DrawTrajectories( const G4Event *  event )
{
    G4VisManager *  visManager( static_cast< G4VisManager * >(
                                    G4VVisManager::GetConcreteInstance() ) );
    if ( ! visManager || ! visManager->GetCurrentGraphicsSystem() )
        return;

    G4int                    nTraj( 0 );
    G4TrajectoryContainer *  trajContainer( event->GetTrajectoryContainer() );

    if ( ! trajContainer )
        return;

    nTraj = trajContainer->entries();

#if G4VERSION_NUMBER >= 1000
    G4VModel *  curModel( visManager->GetCurrentSceneHandler()->GetModel() );
    visManager->GetCurrentSceneHandler()->SetModel( &trajModel );
#endif

    for ( int  i( 0 ); i < nTraj; ++i )
    {
        G4VTrajectory *  traj( ( *trajContainer )[ i ] );
        traj->DrawTrajectory();
    }

#if G4VERSION_NUMBER >= 1000
    visManager->GetCurrentSceneHandler()->SetModel( curModel );
#endif
}


Here i temporarily set model trajModel of type G4TrajectoriesModel and this ugly trick cheats G4VisManager::DispatchToModel(). Before i inserted this code i checked value of visManager->GetCurrentSceneHandler()->GetModel(): it was 0. I do not know if it was OK and i always had some error when i ran my DrawTrajectories() from within my EndOfEventAction().
Comment 7 Alexey 2013-07-23 12:14:45 CEST
Another potential issue.

When i ran my program with diagnostic messages put in my DrawTrajectories() (using G4cout) it became extremely slow. I could see how every little bit of trajectories was redrawn. Probably this is due to constant redraws of GUI pseudo-terminal, though I did not see flickers or redraws (the terminal was scrolled up for some reason every time i ran a new beam).
Comment 8 John.Allison 2013-07-29 16:19:35 CEST
OK.  Back from holiday.  Ready to look at this problem in depth.

You are right.  In a migration for 10.0.beta we have introduced a bug.

  trajectory->DrawTrajectory();

no longer works.  Apologies.

A workaround is to change the above to

  pVVisManager->Draw(*trajectory);

The bug fix is to delete ll.1141-3 and l.1145 of G4VisManage.cc.  This will be fixed for 10.0 in November.

As for speed of drawing, with the default trajectory model and with ordinary trajectories (/vis/scene/add/trajectories or "/tracking/storeTrajectory 1") the trajectory is drawn as a polyline and, if requested, polymarkers at each step point, so it should be quite efficient.  If you use rich trajectories ("/vis/scene/add/trajectories rich" or "/tracking/storeTrajectory 3"), the start and end global times are stored for each trajectory step and the trajectory is chopped up into many pieces depending on

  /vis/modeling/trajectories/drawByCharge-0/default/setTimeSliceInterval

Are you using rich trajectories?  What GUI are you using?
Comment 9 Alexey 2013-07-29 16:37:41 CEST
> In a migration for 10.0.beta we have introduced a bug. ... This will be
fixed for 10.0 in November.

Ok. Good.

As to performance of trajectory drawing I do not actually claim about that. Normally it is good enough and draws fast. I only noticed a big performance decrease (not specifically of drawing trajectory but rather of whole program) when i print traces (with G4cout) on stdout for every trajectory drawing event). They are printed out on a dedicated terminal in GUI layout, so i just assumed that it could be due to no buffering of drawing events in that terminal window (though there could be other reasons).
Comment 10 Alexey 2013-07-29 16:39:23 CEST
Forgot to say that I use Qt.
Comment 11 John.Allison 2013-07-29 17:38:40 CEST
OK.  Let us close this with RESOLVED, FIXED, i.e., understood and will be fixed in the next release.

Thanks for bringing this to our attention.  The call sequence for trajectories is quite complex for the very reason that we wish to maintain the user's privilege to DrawTrajectory.  I apologise for not thoroughly testing this method.

Again, thanks.
Comment 12 Alexey 2013-07-29 17:40:34 CEST
Ok. Thank you.