Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 74 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ In any Processor:
// float x1,float y1,float z1,
// unsigned type,unsigned width,unsigned color);

// hit rendering is delayed by the time "t" (in seconds). Produce animation effect. "Show FPS" must be switched on.
// void ced_hit_ID_animate(float x,float y,float z, float t, unsigned type, unsigned size, unsigned color, unsigned id);


to define colors is better use gimp - it gives that crasy numbers easily

Expand Down Expand Up @@ -178,9 +181,79 @@ to define colors is better use gimp - it gives that crasy numbers easily
// at the end of event
ced_draw_event(); // Make clean up screen before drawing

## Using the CED client library with EDM4hep files in python:

One must use key4hep environment, e.g.:
```bash
source /cvmfs/sw.hsf.org/key4hep/setup.sh
# or
# source /cvmfs/sw-nightlies.hsf.org/key4hep/setup.sh
```

```python
import os
import cppyy
from podio import root_io

# User Config
COMPACT_PATH="<path-to-compact-file>"
EDM4HEP_FILE = "<path-to-edm4hep-file>"
TRACKER_HIT_COLS = ["<name-of-tracker-hit-col-1>", "<name-of-tracker-hit-col-2>", "<...>"]
CALO_HIT_COLS = ["<name-of-calo-hit-col-1>", "<name-of-calo-hit-col-2>", "<...>"]

# Load dependencies
for path in os.environ["CMAKE_PREFIX_PATH"].split(":"):
inlcude_dir = os.path.join(path, "include")
if os.path.isdir(inlcude_dir):
cppyy.add_include_path( inlcude_dir )

if "/marlinutil/" in path:
cppyy.add_include_path( os.path.join(path, "include", "marlinutil") )
Comment on lines +205 to +211
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably don't need all of them, I would assume, but writing that filtering in this example is probably too much details.

Copy link
Member Author

@dudarboh dudarboh Jan 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we definitely don't need all of them. I, actually would love to filter them here, but if I start from a small subset of libs, the seg. faults are quite cryptic so, for me it is even hard to add libs one-by-one...

Ideally, if drawDD4hepDetector() would be local, then all required dependencies would be only ["ced", "dd4hep"].

The fact that the drawDD4hepDetector() is in DDMarlinCED.h, and that the header includes so many other headers that are not even used for this example makes loading so many dependencies, including LCIO ones, necessary... But if we find the set of libs that are necessary, I think filtering can be easily added with:

# Load dependencies
libs = ["ced", "dd4hep", "marlinutil", "<libs-DDMarlinCED-depends-on>"]
for path in os.environ["CMAKE_PREFIX_PATH"].split(":"):
    if not any(lib in path for lib in libs):
        continue
    inlcude_dir = os.path.join(path, "include")
    if os.path.isdir(inlcude_dir):
        cppyy.add_include_path( inlcude_dir )

    if "/marlinutil/" in path:
        cppyy.add_include_path( os.path.join(path, "include", "marlinutil") )


cppyy.include("ced_cli.h")
cppyy.include("DDMarlinCED.h")
from cppyy.gbl import ced_client_init, ced_register_elements
from cppyy.gbl import ced_new_event, ced_send_event, ced_selected_id_noblock
from cppyy.gbl import ced_hit_ID, ced_hit_ID_animate, CED_HIT_POINT
std = cppyy.gbl.std
DDMarlinCED = cppyy.gbl.DDMarlinCED

det_compact_file = os.path.join( os.environ["k4geo_DIR"], COMPACT_PATH )
detector = cppyy.gbl.dd4hep.Detector.getInstance()
detector.fromCompact(det_compact_file)

ced_client_init("localhost", 7286)
ced_register_elements()

reader = root_io.Reader(EDM4HEP_FILE)
for event in reader.get("events"):
ced_new_event()

DDMarlinCED.drawDD4hepDetector( detector, False, std.vector[std.string]() )

layer = 1 # layer under which hits are displayed
animated_layer = 2
size = 5 # size of the hits
color = 0x000000 # hex color of the hits
# Draw all reconstructed hits in layer #1 and animate them in layer #2
for col in TRACKER_HIT_COLS + CALO_HIT_COLS:
for hit in event.get(col):
pos = hit.getPosition()
t = hit.getTime()
ced_hit_ID(pos.x, pos.y, pos.z, CED_HIT_POINT, layer, size, color, 0)
ced_hit_ID_animate(pos.x, pos.y, pos.z, t, CED_HIT_POINT, animated_layer, size, color, 0)

ced_send_event()

# ced_selected_id_noblock() can be used to return id of the picked object.
# A more involved example with kbhit instead of pyhton's input() would be needed to use it.
# picked_id = ced_selected_id_noblock()

input("Press enter to draw next event")
```

## License and Copyright
Copyright (C) 2005-2017, CED Authors
Copyright (C) 2005-2026, CED Authors

CED is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Expand Down
3 changes: 3 additions & 0 deletions include/ced_cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ typedef enum {

typedef struct {
CED_Point p;
float time; // allows event animation
unsigned type; // point, star, etc
unsigned layer; //layer
unsigned color; // in ARGB form (so, 0xff0000 is RED)
Expand All @@ -144,6 +145,8 @@ void ced_hit_ID_old(float x,float y,float z,unsigned type, unsigned size,unsigne

void ced_hit_ID(float x,float y,float z,unsigned type,unsigned layer, unsigned size,unsigned color, unsigned lcioID);

void ced_hit_ID_animate(float x,float y,float z,float t, unsigned type,unsigned layer, unsigned size,unsigned color, unsigned lcioID);

/*
* Line element
*/
Expand Down
2 changes: 2 additions & 0 deletions src/ced.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ struct CEDsettings{
int autoshot_scale; // If true, generate screencapture in every new event
};

extern int animation_start_time; // in ms
extern int animate_layer;
/*
//important:
// - sum of all layers must be smaler than max_layer!
Expand Down
17 changes: 17 additions & 0 deletions src/client/ced_cli.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ void ced_hit_ID(float x,float y,float z,unsigned type,unsigned layer, unsigned s
h->p.x=x;
h->p.y=y;
h->p.z=z;
h->time=0;
h->type=type;
// if(layer > 255){ //downward compability
// h->layer=layer >> CED_LAYER_SHIFT;
Expand All @@ -45,6 +46,22 @@ void ced_hit_ID(float x,float y,float z,unsigned type,unsigned layer, unsigned s
h->lcioID=lcioID;
}

void ced_hit_ID_animate(float x,float y,float z,float t, unsigned type,unsigned layer, unsigned size,unsigned color, unsigned lcioID){
CED_Hit *h=(CED_Hit *)ced_add(HIT_ID);
if(!h) return;
h->p.x=x;
h->p.y=y;
h->p.z=z;
h->time=t;
h->type=type;
h->layer=layer;
h->size=size;
h->color=color;
h->lcioID=lcioID;
}



/*
* Line element
*/
Expand Down
17 changes: 17 additions & 0 deletions src/server/ced_srv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1290,11 +1290,28 @@ static void ced_draw_hit(CED_Hit *h){
}

//printf("hit on layer: %i\n", h->layer);

// time is passed to the hit data and is expected to be animated
bool to_animate = h->time > 0.f;
if ( to_animate && animate_layer == -1 ) animation_start_time = glutGet(GLUT_ELAPSED_TIME);

if(!IS_VISIBLE(h->layer)){
if (to_animate && animate_layer == int(h->layer) ) animate_layer = -1;
return;
}

// printf("Draw hit at : %f %f %f type = %d and ced_visible_layers = %d \n",h->p.x,h->p.y,h->p.z,h->type,ced_visible_layers);
if (to_animate){
if ( animate_layer == -1 ) animate_layer = h->layer;
else if ( animate_layer != int(h->layer) ){
setting.layer[animate_layer] = false;
animate_layer = h->layer;
animation_start_time = glutGet(GLUT_ELAPSED_TIME);
}
float elapsed_time = 0.001*( glutGet(GLUT_ELAPSED_TIME) - animation_start_time); // in seconds
if ( elapsed_time < h->time ) return ;
}


ced_color(h->color);

Expand Down
41 changes: 41 additions & 0 deletions src/server/glced.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ int ced_picking(int x,int y,GLfloat *wx,GLfloat *wy,GLfloat *wz); //from ced_srv


//*************** global variables ***************************************//
int animation_start_time = 0;
int animate_layer = -1;
//for new angles add the new angle to this list and to define in ced_menu.h
static int available_cutangles[]={0,30,45,90,100,135,120,150,170,180,190,200,220,240,260,270,280,290,310,330,340};
int last_selected_layer;
Expand Down Expand Up @@ -560,6 +562,41 @@ std::string formatShortcut(int iLayer, const char key, const char *description,

return truncateTo(sstr.str(), max_len);
}
void printEventTime(void){
if( animate_layer < 0 ) return;

//calculate event time:
float elapsed_time = 0.001*( glutGet(GLUT_ELAPSED_TIME) - animation_start_time); // in seconds, but physicswise should be in ns
char text[42];
sprintf(text, "Event time: %.3f ns", elapsed_time);
double dark = 1.-(setting.bgcolor[0]+setting.bgcolor[1]+setting.bgcolor[2]) / 3.0;

//print on screen:
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
GLfloat w=glutGet(GLUT_SCREEN_WIDTH);
GLfloat h=glutGet(GLUT_SCREEN_HEIGHT);
glOrtho(-WORLD_SIZE*w/h,WORLD_SIZE*w/h,-WORLD_SIZE,WORLD_SIZE, -15*WORLD_SIZE,15*WORLD_SIZE);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glColor3f(dark,dark,dark);
drawHelpString(text, -600, -950);


glEnd();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}


void printShortcuts(void){

Expand Down Expand Up @@ -776,6 +813,7 @@ static void display(void){
ced_menu->draw();
popupmenu->draw();
printFPS();
printEventTime();

if(setting.light==true){
glEnable(GL_LIGHTING);
Expand Down Expand Up @@ -4524,6 +4562,9 @@ int main(int argc,char *argv[]){



//future calls give time relative to this.
glutGet(GLUT_ELAPSED_TIME); // time since glutInit()
animation_start_time = glutGet(GLUT_ELAPSED_TIME); // time since first glutGet(GLUT_ELAPSED_TIME)

glutMainLoop();
return 0;
Expand Down
Loading