Best way to compile and debug standalone Eve/track.C tutorial example

Hello,

I have been trying to create a standalone executable of the track.C macro with the intent to debug it and become more familiar with the data structures and the methods to manage and render particle tracks.

I have managed to make a manual build of the latest ROOT distribution with debug symbols. I have subsequently used it to generate the dictionary and shared library with this command:

root [0] .L track.C+g

which created the following:
-rw-r–r-- 1 pbr pbr 8288 Jan 5 15:04 track_C.d
-rw-r–r-- 1 pbr pbr 1449 Jan 5 15:04 track_C_ACLiC_dict_rdict.pcm
-rwxr-xr-x 1 pbr pbr 344296 Jan 5 15:04 track_C.so

I then compiled the main program:

#include "TEveTrackPropagator.h"
#include "TEveTrack.h"
#include "TEveVSDStructs.h"
#include "TEveManager.h"
#include "TEveViewer.h"
#include "TSystem.h"
#include "TGLViewer.h"
#include "TMath.h"

#include "TEveViewer.h"
#include "TEvePointSet.h"

#include <iostream>

#include "./track.C"

//void track(int, bool);

int main(){

track(4,kTRUE);

return 0;
}

with the following:

and finally linked the two with the following command:

~/root_install2/tmp$ g++ -g  -o build/main_track_C.exe  build/main_track_C.o src/track_C.so -Wl,-rpath,'$ORIGIN' `../bin/root-config --libs` `../bin/root-config --glibs` -lEve -lRGL -lpthread -lrt -Lhome/pbr/root_install2/lib

This generated the standalone executable with the debug symbols, however when run it exits with a segmentation violation error.

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b8bba0 in TApplication::InitializeGraphics (this=0x0) at /home/pbr/root_src/core/base/src/TApplication.cxx:264
264	   LoadGraphicsLibs();

Here is the full stack trace:

(gdb) bt
#0  0x00007ffff7b8bba0 in TApplication::InitializeGraphics (this=0x0) at /home/pbr/root_src/core/base/src/TApplication.cxx:264
#1  0x00007ffff4eb2af7 in TEveManager::Create (map_window=true, opt=0x55555555e241 "FIV")
    at /home/pbr/root_src/graf3d/eve/src/TEveManager.cxx:905
#2  0x000055555555a5ee in track (mode=4, isRungeKutta=true) at ../src/./track.C:170
#3  0x000055555555b87a in main () at ../src/main_track_C.cpp:21

My goal again is to follow this “simple” example step by step to get a better understanding of the data structures and methods in play.

What am I missing?
Is there a better way to accomplish this?

Thank you.
Pietro

_ROOT Version: 6.22/02
_Platform: Debian GNU/Linux 10 (buster)
_Compiler: g++ (Debian 8.3.0-6) 8.3.0

May be @matevz can help you.

Hmmh, why are you trying to have your own main? This is asking for a lot of trouble …

Anyway, Eve requires root TApplication or TRint (if you want root prompt) to be created and running:

main(argc argv)
{
TApplication app(“myApp”, argc, argv); // or TRint
// your init
app.Run();
}

Cheers,
Matevz

Hi Matevz,

Thank you for the prompt reply. I am making progress, no more segmentation errors, but not quite there yet… the program executes but it hangs in the event loop… Am I missing additional needed steps?

Here is the revised main I am using:

//int main(){
//
//track(4,kTRUE);
//
//return 0;
//}

int main(int argc, char **argv) {

    const char *appname = "track";

    argc    = 2;
    argv[0] = (char *) "4";
    argv[1] = (char *) "true";

    TApplication* app = new TApplication(appname, &argc, argv);

    app->Run(kTRUE);

    return 0;
}

The program hangs. When I debug and do a Ctrl-C I obtain the following trace:

Program received signal SIGINT, Interrupt.
0x00007ffff45afff7 in select () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) bt
#0  0x00007ffff45afff7 in select () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x00007ffff7d15028 in TUnixSystem::UnixSelect (nfds=4, readready=0x55555557ff10, writeready=0x55555557ffa0, timeout=-1)
    at /home/pbr/root_src/core/unix/src/TUnixSystem.cxx:3893
#2  0x00007ffff7d0e18a in TUnixSystem::DispatchOneEvent (this=0x55555557f260, pendingOnly=false)
    at /home/pbr/root_src/core/unix/src/TUnixSystem.cxx:1120
#3  0x00007ffff7c03551 in TSystem::InnerLoop (this=0x55555557f260) at /home/pbr/root_src/core/base/src/TSystem.cxx:401
#4  0x00007ffff7c032ff in TSystem::Run (this=0x55555557f260) at /home/pbr/root_src/core/base/src/TSystem.cxx:351
#5  0x00007ffff7b921fa in TApplication::Run (this=0x55555567de50, retrn=true) at /home/pbr/root_src/core/base/src/TApplication.cxx:1622
#6  0x000055555555522b in main (argc=2, argv=0x7fffffffe078) at src/main_track_C.cpp:37

to be clear: what I am trying to do is run the track.C macro at ROOT: tutorials/eve/track.C Source File (cern.ch) that yields the following Eve Window when run from the root command line:

I would like to be able to establish breakpoints within track.C and follow the execution of the macro step by step and be able to look at data structures and methods as they are activated to yield the final Canvas in the above image.

Thanks.
Pietro

Hi Pietro,

TApplication/TRint::Run() runs the main root event loop: waiting for gui events, timers, file-descriptors and, in case of trint, on the command-line. You have to create your scene before calling it – simply call track() on the line before calling Run.

However, for what you want to do, you can also do it all with root.exe as the main application:
gdb root.exe
(gdb) run
(root) .L track.C+g
— control c or z to get back to gdb
(gdb) b track.C:line-number
(gdb) cont
(root) track()

I can actually tell you most about what happens in track.C and in Eve / GL … but I don’t know what part you’re interested in :slight_smile: In principle, there are 3 stages:

  1. initialization in track.C, set track parameters and points track passes through (measurement points);
  2. call MakeTrack() – this will actually call the propagator that will propagate the track in the given magnetic field towards each path-mark and then fix the trajectory when reaching point of closest approach to each of them;
  3. Drawing is done through the ROOT GL system, class TEveTrackGL knows how to convert data in TEveTrack to appropriate GL calls, based on attributes set in the track and track propagator.

Good luck! :slight_smile:
Matevz

Excellent, thank you! This is exactly what I was looking for. I now have the debug session running on Eclipse, much easier to follow…

The part I am interested in, to begin, is the trajectory generation, which is still not very clear to me (disclaimer: I am new to particle physics). Is track.C meant to be an example of path reconstruction? what are the fixed/measured quantities? and what are we adjusting to obtain the final trajectory?

No, it’s not an example of path reconstruction … it shows how to setup visualization of tracks:

  • specification of magnetic field
  • setup of TEveTrackPropagator
  • specifying track starting parameters, position and momentum
  • specifying known points where the particle passed through – PathMarks.

Now, the track can come from simulation or from reconstruction and there are different types of path-marks allowing you to specify “events” on the particle trajectory.

Eve propagator steps from one path mark (or initial position) to the next like this:

  • propagate particle from current position to the closest point of approach to the path-mark (using RungeKutta integration);
  • store intermediate points in an array;
  • calculate distance vector (delta) between the path-mark and calculated extrapolated position;
  • add this delta to stored points along the path so that nothing is added to the first point, full delta to the last one, and proportional amount to intermediate points – this makes the calculated trajectory smooth and pass through the given path-mark.

This is the best one can do from visualization perspective, adding minimal assumptions into what has actually happened to the track and why (energy loss, decay, or just wrong starting parameters).

If there are no path-marks, the track is just propagated with given momentum … this is an imaginary / ideal trajectory for a particle that does not interact with matter (lose energy) or decay.

qpbr_tracks.C (4.8 KB)
Hi Matevz,

Thanks again for the information, it has been very helpful and I have made some progress, but now I need another nudge to proceed further. I am assuming this is the appropriate forum for these types of questions, but let me know if that is not the case.

First let me describe the context of what I am trying to achieve, and then tell you where I could use some immediate help.

The ultimate task for me is to create a naïve no-frills…

  1. …simulation of a collision with 2 opposite primary beam particles, …
  2. …that generate 4 secondary product particles.
  3. Evaluate the hit points of the secondary particles on a cylindrical detector surface where tracks terminate and all energy is absorbed.
  4. Visualize the cumulative energy levels absorbed at the surface with a spatial grid resolution of my choosing.
  5. Create a side-by-side track simulation view and the energy distribution view
  6. Animate both views with a time resolution of my choosing.
    That is in summary what I would like to achieve at the end of this exercise.

So far (please see attached macro), I have been able to create the geometry and instantiate the “beam” tracks which decay at the collision point. I have also instantiated 4 independent tracks, but in the immediate it is not clear to me how to:

  • create the appropriate mother/daughter dependencies for the particles/tracks
  • detect the surface endpoints
  • extract time information and ensure secondary particle generation is consistent with time of collision

If I can have some tips on these points, I should then be able to move on to tackle 4. through 6. above next.

Thanks!
Pietro

Hi Pietro,

First, I should warn you that you are stretching Eve well beyond its intended purpose as it is not a simulation tool and does not handle energy loss and does not really handle intersections with arbitrary geometry volumes – for this you could use TGeo.

Now, you can trick TEvePropagator to do what you want … you set it MaxR MaxZ and the track will stop on that cylinder. You just get the last point from the track and you should be good to go.

There is no special daughter/mother relationship between tracks in eve … the pathmark type daughter creation simply tells eve propagator to subtract the momentum carried away by the daughter (this is meant for delta electrons, bremssthralung photons etc). But you can just assign “daughters” as eve children to their parent tracks and manually set the origin to the last point of the mother track. This will allow you to have a reasonable view in the side list-tree view and also to togglew RnrDaughters on/off for a given parent.

I’m not sure what you mean with time information for the secondary. You mean if time at which the seconday intersects the cylinder is within some trigger window? I forgot how exactly this is done but internally eve-track-propagator works with 4-vectors so it knows about the time on each point and I’m pretty sure this can be extracted somehow, I’d have to look.

Cheers,
Matevz

1 Like

Hi Matevz,

Thanks for the comments, things are clearer regarding TEve and its relation to TGeo, and I have been able to make some progress, but I am at the point where need a few more nudges to move forward.

I have implemented your suggestions to detect the surface “hits” and utilized 4-vectors to include time values (completely arbitrary) for the generated tracks that will do for the purposes of trying to animate the scene). I have stored my “hits” in a tree object and, more or “less”, I have been able to implement points 3 through 5 (see Jan 17 message and current revised macro +qpbr_tracks.C (12.9 KB) ), that is the rendering of geometry and tracks, side-by-side with a 2D histogram for the distribution of the energy “hits” on the surface. I have parroted the tutorials/eve/calorimeters.C example to achieve this outcome, and I have more questions further below regarding refining the display of the elements, but in the immediate I could use some advice on how to implement the animation. As can be seen from running the macro, I have made 2 slots, the top slot renders the geometry and tracks, the one below has the histogram of the energy “hits” distribution. Ideally, I would like to start from a clean geometry with no tracks and clean histogram, and update the scenes by rendering the tracks and bars on the histogram as long as the time value associated to them is at or below the current time in the animation. Assuming a TTimer is what I need to use for this, how do I turn the rendering of the elements on and off (at least for the tracks)? Any recommendations on dealing with the histogram?

Regarding the refinements I alluded to before, as you can see by running the macro or in the picture below, the initial orientation and magnification of the objects in the two slots are not ideal:

and I need to manually intervene to obtain de-magnified isometric looking projections, such as below:

I have played with the Camera settings, as you can see in the macro, but no no avail. What steps do you take to implement this in the code?

Finally, in the upper slot of my “Composite Views” tab (see below)

I wanted to have an entire replica of the “GL” viewer tab I create in the early stages of my macro. Since I use a slotTop->ReplaceWindow(ev) command at line 284 of the macro to populate the scene, I lose the scene in “GL” and end up with an empty tab (see below). How do I make a full copy of the original viewer/scene and properly initialize the top slot in the “Composite Views” tab while retaining the same outcome for the “GL” tab?
image

Thanks!
Pietro

Hi @matevz,
An additional question to the above posting from earlier this week:
Given the end goal of having the animation of two side-by-side windows, the physical “detector” and the corresponding layout of the energy distribution of the “hits”, would an experienced ROOT user prefer the TEve route? like I set out to do here, or would they employ an alternative approach?

Thanks!
Pietro

Hi,

You want to do animation in sort of real time (as opposed to saving images and making a movie), I gather. Hmmh, you would need a way to set max-time for tracks … and store also the time information for each point, than use this in TEveTrackGL to render line just to that point. I sort of remember this has been done before … hmmh, let me look at the code … ah, nope, I did this in another framework, long time ago, sorry.

So, the best way forward would be to set for track a final path-mark (decay, probably) on the point where you want the particle to be at that time frame … and then re-propagate. I realize this is not ideal but the above option of storing time info and using it requires quite some development — would you like to try it on? I can try guiding you but it’s not going to be easy.

TTimer should work, you could also do

for (time t)
{
  // do what you need at this t, updade objects;
  gEve->Redraw3D();
  gSystem->ProcessEvents();
  gSystem->Sleep(10); // in milisec
}

To populate a view / tab with the same content you just call the same functions as are called there. I’m pretty sure you can also reorder tabs … see docs of TGTab in gui/gui.

For how to manipulate camera, take a look at class TGLAutoRotator, in graf3d/gl. If you want to reset camera after you load the scene, I think you just need true argument to FullRedraw()

  gEve->FullRedraw3D(kTRUE);
 // And this is how you can reset it after changing camera on some viewer
  gl_viewer->ResetCurrentCamera();
  gl_viewer->RequestDraw(TGLRnrCtx::kLODHigh);

I don’t understand your question about what people experienced with ROOT would expect / prefer. You see, I don’t really know for what purpose you are doing this :slight_smile:

Cheers,
Matevz

Hi @matevz ,

Thanks for the alice_esd tip, as I digest the materials I hope you don’t mind if I keep this thread alive, by asking additional related, but separate, questions.

I have made some progress with my script qpbr_tracks.C (14.8 KB) and was able to implement the time “loop” we discussed earlier with a TPad window, e.g.,


in an “animated” fashion.

My current question is: is there a quick way to embed something like this TPad itself in a TEve tabbed window? Similar to what I have done for the other views/scenes in my script?

Thanks!
Pietro

Hi Pietro,

Yes, it’s possible, you just embed TCanvas in the eve window slot … look at tutorials/eve window_manager.C and histobrowser.C

Cheers,
Matevz

Hi @matevz,

Awesome!! Now I have run into a resulting issue after implementing it in the latest version qpbr_tracks.C (15.3 KB) of the macro.

While in the animation loop, the animation window (bottom right) looks zoomed in:


then it fully fits all the windows at the end of the loop, which is the outcome I ultimately want:

Question: how do I force it to render the window(s) with full fit during the loop?

Thanks!
Pietro

Hi Pietro!

Hmmh, I’m guessing a bit here … but as both eve and tcanvas are partially shown I’d assume the system window resize has not completed. You can let ROOT GUI handle outstanding events (including window resize messages from the windowing system) by calling gSystem->ProcessEvents().

Cheers,
Matevz

Perfect. Worked like a charm, thank you! -Pietro

Hi @matevz,

I have entered the final stretch but have some issues I have not been able to resolve on my own and need a little nudge.

I want to replicate the “animation effect” I achieved earlier for the TCanvas lego plot also for the top slot in my main window (the one supposed to show the tracks that hit the “calorimeter”). I have the corresponding track labels stored in a TTree and would like to add the tracks one by one in the correct temporal order to the scene (the scene labeled “Track-Hits”).

To extract the relevant tracks I have tried using the FindTrackByLabel method (see line line 410 of the qpbr_tracks.C (17.5 KB) macro), but even though the method is able to “see” the matches, it generates a “segmentation violation”. My first question is: am I missing anything in setting up the Viewer/Scenes/TEve Lists that is causing the error? Or using the method inappropriately in some other way?

The other question is the following. I have hacked the method and performed the matching manually (lines 412-416) and in this way I have been able to add the tracks I want to the scene. However the added tracks are not displayed during the animation loop, despite using gSystem->ProcessEvents(). Only when I hover with the mouse on top of the “Scenes” folder in the Eve Browser, do the tracks appear. Is there a way to make Eve display each added track as the animation loop executes?

Or is there another approach that achieves the same goal?

Thanks!
Pietro

PS: a little update…

I have added the following two lines for (my hope at least) displaying the chosen product track to my scene:

//_end FindTrack

     if(track){
        track->SetRnrSelf(kTRUE);
        cout<< "++ itrk="<<itrk<<endl;
        sb->AddElement(track);          // update scene top track plot
1.         sb->Changed();
2.         sb->Repaint(kTRUE);
        //gEve->GetScenes()->RepaintChangedScenes(kFALSE);
        //gEve->GetScenes()->RepaintAllScenes(kTRUE);
        //gSystem->ProcessEvents();
     }

And it partially works for my first track in the list (small blue track lower middle):
image
But unless I hover on the Browser list or click on the partially displayed tracks in the frame which forces a “ProcessSceneChanges”, I can’t seem to make it display the rest of the tracks in the list:
image

Any recommendations on the correct thought process, or proper sequence required to control these rendering behaviors?

Thanks.
Pietro

Hey,

Sorry, I’m in a bit of a mess here, probably the easiest way to go on is for me to actually run your code … and I propose we go step by step, one issue at a time :slight_smile:

  1. does your qpbr_tracks.C run as is … or I need some input data files
  2. does it run with master
  3. can you create a github repo so I can checkout and make you PRs
  4. does it run in compiled mode, as in root.exe qpbr_tracks.C+ – this would help when running a debugger

Cheers,
Matevz