Page MenuHomeHEPForge

main.cpp
No OneTemporary

main.cpp

This document is not UTF8. It was detected as Shift JIS and converted to UTF8 for display.
#include "main.h"
void DrawTrack(int i, MySimVertex* vertex1, MySimVertex* vertex2)
{
MySimTrack* track = event->MySimTrackCollection[i];
if(track == NULL) return;
if(vertex1 == NULL) return;
if(sqrt(vertex1->x*vertex1->x+vertex1->y*vertex1->y)>TRACKING_RADIUS)return;
if(fabs(vertex1->z)>TRACKING_LENGTH)return;
// printf("Track %f --> Vertex1 : %10.5f %10.5f %10.5f\n",track->Type,vertex1->x,vertex1->y,vertex1->z);
double q = track->charge;
double Px = track->Px / 0.003;
double Py = track->Py / 0.003;
double Pz = track->Pz / 0.003;
double Pt = sqrt(Px*Px+Py*Py);
double P = sqrt(Px*Px+Py*Py+Pz*Pz);
if(q!=0){
double E = track->E / 0.003;
double M = sqrt(E*E - (Px*Px + Py*Py + Pz*Pz) );
double Bz = 4;
double vx = Px/M;
double vy = Py/M;
double vz = Pz/M;
double ax = (q/M)*Bz*vy;
double ay = -(q/M)*Bz*vx;
double az = 0;
double dt = 1/P;
if(Pt<266 && vz < 0.0012){
dt = fabs(0.001/vz);
}
double x=vertex1->x;
double y=vertex1->y;
double z=vertex1->z;
double xold,yold,zold;
double VTold = sqrt(vx*vx+vy*vy);
double DVertex;
if(vertex2!=NULL)DVertex = ((x-vertex2->x)*(x-vertex2->x)) + ((y-vertex2->y)*(y-vertex2->y)) + ((z-vertex2->z)*(z-vertex2->z)) ;
for(int k=0;k<100000;k++)
{
vx += ax*dt;
vy += ay*dt;
vz += az*dt;
double VTratio = VTold/sqrt(vx*vx+vy*vy);
vx *= VTratio;
vy *= VTratio;
ax = (q/M)*Bz*vy;
ay = -(q/M)*Bz*vx;
az = 0;
xold = x;
yold = y;
zold = z;
x += vx*dt;
y += vy*dt;
z += vz*dt;
if(vertex2!=NULL){
double newDVertex = ((x-vertex2->x)*(x-vertex2->x)) + ((y-vertex2->y)*(y-vertex2->y)) + ((z-vertex2->z)*(z-vertex2->z)) ;
if(newDVertex<DVertex){
DVertex = newDVertex;
}else{
x = vertex2->x;
y = vertex2->y;
z = vertex2->z;
k = 100000;
}
}
if( (x*x+y*y) > TRACKING_RADIUS*TRACKING_RADIUS ){ x /= (x*x+y*y)/(TRACKING_RADIUS*TRACKING_RADIUS); y /= (x*x+y*y)/(TRACKING_RADIUS*TRACKING_RADIUS); k = 100000; continue;}
if( fabs(z)>TRACKING_LENGTH){k = 100000;continue;}
glBegin (GL_LINES);
glVertex3d (xold,yold,zold);
glVertex3d (x,y,z);
glEnd();
}
}else{
if(vertex2!=NULL && sqrt(vertex2->x*vertex2->x+vertex2->y*vertex2->y)<TRACKING_RADIUS && fabs(vertex2->z)<TRACKING_LENGTH ){
glBegin (GL_LINES);
glVertex3d (vertex1->x,vertex1->y,vertex1->z);
glVertex3d (vertex2->x,vertex2->y,vertex2->z);
glEnd();
}else{
double t1 = TRACKING_RADIUS/sqrt(Px*Px+Py*Py);
double t2 = TRACKING_LENGTH/fabs(Pz);
if(t2<t1)t1=t2;
glBegin (GL_LINES);
glVertex3d (vertex1->x,vertex1->y,vertex1->z);
glVertex3d (Px*t1,Py*t1,Pz*t1);
glEnd();
}
}
}
void reshape (int w, int h)
{
if (h == 0) h = 1;
WINDOW_WIDTH = w;
WINDOW_HEIGHT = h;
glViewport (0, 0, (GLsizei)w, (GLsizei)h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (45.0, (GLfloat)w/(GLfloat)h, 0.1, 5000.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glutPostRedisplay ();
}
void display()
{
if(mLoading)
{
switch(mLoading_I)
{
case 0:
start = time ( NULL );
LoadingInProgress(WINDOW_WIDTH,WINDOW_HEIGHT,LogoTexture,0.f, "Reading config.txt");
printf("Reading config.txt\n");
glutSwapBuffers();
break;
case 1:
LoadCard("config.txt");
break;
case 10:
{
printf("Loading %s\n", inputVisFile.c_str() );
LoadingInProgress(WINDOW_WIDTH,WINDOW_HEIGHT,LogoTexture,10.f, (char*)inputVisFile.c_str());
glutSwapBuffers();
}
break;
case 11:
events = new MySimEvents();
events->Load(inputVisFile.c_str());
events->GoToEvent(eventNumber-1);
break;
case 20:
LoadingInProgress(WINDOW_WIDTH,WINDOW_HEIGHT,LogoTexture,30.f, (char*)inputTrackerGeom.c_str());
printf("Loading Tracker\n");
glutSwapBuffers();
break;
case 21:
geom = new Geometry();
geom->Load((char*)inputTrackerGeom.c_str());
break;
case 22:
printf("Loading Ecal\n");
LoadingInProgress(WINDOW_WIDTH,WINDOW_HEIGHT,LogoTexture,50.f, (char*)inputEcalGeom.c_str());
glutSwapBuffers();
break;
case 23:
geom->Load((char*)inputEcalGeom.c_str());
break;
case 24:
printf("Loading Hcal\n");
LoadingInProgress(WINDOW_WIDTH,WINDOW_HEIGHT,LogoTexture,80.f, (char*)inputHcalGeom.c_str());
glutSwapBuffers();
break;
case 25:
geom->Load((char*)inputHcalGeom.c_str());
break;
case 26:
printf("Loading Muon\n");
LoadingInProgress(WINDOW_WIDTH,WINDOW_HEIGHT,LogoTexture,90.f, (char*)inputMuonGeom.c_str());
glutSwapBuffers();
break;
case 27:
geom->Load((char*)inputMuonGeom.c_str());
break;
case 30:
LoadingInProgress(WINDOW_WIDTH,WINDOW_HEIGHT,LogoTexture,95.00f, "Initialisation");
glutSwapBuffers();
break;
case 31:
init();
break;
case 32:
LoadingInProgress(WINDOW_WIDTH,WINDOW_HEIGHT,LogoTexture,99.00f, "Creation of Contextual Menu");
glutSwapBuffers();
break;
case 33:
menu_create();
break;
case 100:
mLoading_I = 0;
mLoading = false;
end = time ( NULL );
printf("Loading Time = %isec\n",end-start);
//events->Save("test.vis");
return;
default:
break;
}
mLoading_I++;
return;
}
glClearColor(WaC_BackGround.R,WaC_BackGround.G,WaC_BackGround.B,1.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Reset le buffer de couleur et de profondeur
glMatrixMode (GL_MODELVIEW); // On se met dans le rep鑽e du model (rep鑽e 3D)
glLoadIdentity (); // Reinitialise la matrice du rep鑽e
//gluLookAt (-1*CAM_R*cos(t+CAM_tx), 0, -1*CAM_R*sin(t+CAM_tx),0,0,0,0,1,0); // Defini la camera (pos.x, pos.y, poz.z, view.x, view.y, view.z, vert.x, vert.y vert.z) pos est la position de la camera, view est l'endroit ou elle regarde, et vert est le vecteur qui indique la verticale de la camera
gluLookAt (-1*CAM_R*cos(t+CAM_tx)*cos(CAM_ty), CAM_R*sin(CAM_ty), -1*CAM_R*sin(t+CAM_tx)*cos(CAM_ty),0,0,0,0,1,0); // Defini la camera (pos.x, pos.y, poz.z, view.x, view.y, view.z, vert.x, vert.y vert.z) pos est la position de la camera, view est l'endroit ou elle regarde, et vert est le vecteur qui indique la verticale de la camera
if(mRotate) t+= mDt;
glEnable(GL_BLEND) ;
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glColor4d (WaC_CMS_Framework.R,WaC_CMS_Framework.G,WaC_CMS_Framework.B,WaC_CMS_Framework.A);
glLineWidth(WaC_CMS_Framework.W);
DrawCylinder(CMS_TRACKER_RADIUS, 13, 2*CMS_TRACKER_LENGTH, 0, 0, 0);
glColor4d (WaC_LHC_Axis.R,WaC_LHC_Axis.G,WaC_LHC_Axis.B,WaC_LHC_Axis.A);
glLineWidth(WaC_LHC_Axis.W);
glBegin (GL_LINES);
glVertex3d (0,0,-1*CMS_TRACKER_LENGTH);
glVertex3d (0,0,CMS_TRACKER_LENGTH);
glEnd();
glLineWidth(1);
if(gTracker && theGeomTracker[0]==0) initGeomTracker();
if(gEcal && theGeomEcal[0] ==0) initGeomEcal();
if(gHcal && theGeomHcal[0] ==0) initGeomHcal();
if(gMuon && theGeomMuon[0] ==0) initGeomMuon();
if(gTracker&1) glCallList(theGeomTracker[0]);
if(gTracker&2) glCallList(theGeomTracker[1]);
if(gTracker&4) glCallList(theGeomTracker[2]);
if(gTracker&8) glCallList(theGeomTracker[3]);
if(gTracker&16)glCallList(theGeomTracker[4]);
if(gTracker&32)glCallList(theGeomTracker[5]);
if(gEcal &1) glCallList(theGeomEcal[0]);
if(gEcal &2) glCallList(theGeomEcal[1]);
if(gEcal &4) glCallList(theGeomEcal[2]);
if(gHcal &1) glCallList(theGeomHcal[0]);
if(gHcal &2) glCallList(theGeomHcal[1]);
if(gHcal &4) glCallList(theGeomHcal[2]);
if(gHcal &8) glCallList(theGeomHcal[3]);
if(gMuon &1) glCallList(theGeomMuon[0]);
if(gMuon &2) glCallList(theGeomMuon[1]);
if(gMuon &4) glCallList(theGeomMuon[2]);
glColor3d (0.5,0.5,0);
if(gReco&1){glCallList(theGeomTrackerInEvent);}
if(gReco&2){glCallList(theGeomEcalInEvent);}
if(gReco&4){glCallList(theGeomHcalInEvent);}
if(gReco&8){glCallList(theGeomMuonInEvent);}
if(mColl_I == ObjectsColl::HCAL_HIT){
glLineWidth(8);
CaloDet* cell = geom->Find_CaloDet(event->MyHcalCaloHitCollection[mObj_I]->DetId);
if(cell!=NULL)DrawDet(cell);
glLineWidth(1);
}
unsigned int i;
if(event!=NULL){
if(gSim&1){
for(i=0;i<event->MyPSimHitCollection.size();i++){
if(event->MyPSimHitCollection[i]->ProcessType==3){glColor3d (1,1,1);}else{glColor3d (1,0,0);}
DrawSquare(1000*event->MyPSimHitCollection[i]->dEdX,event->MyPSimHitCollection[i]->x, event->MyPSimHitCollection[i]->y, event->MyPSimHitCollection[i]->z);
}
}
if(gSim&2){
for(i=0;i<event->MySimTrackCollection.size();i++){
defineColorForSimTrack(i);
glCallList(theSimTracks[i]);
}
glLineWidth(1);
}
if(gSim&4){
for(i=0;i<event->MySimVertexCollection.size();i++){
glColor3d (0,1,0);
DrawSquare(2,event->MySimVertexCollection[i]->x, event->MySimVertexCollection[i]->y, event->MySimVertexCollection[i]->z);
}
}
}
glColor4d (WaC_Txt.R,WaC_Txt.G,WaC_Txt.B,WaC_Txt.A);
if(mHelpScreen){
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/10,WINDOW_HEIGHT - 50 ,GLUT_BITMAP_9_BY_15,"F5 = SimTrack : ON/OFF");
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/10,WINDOW_HEIGHT - 75 ,GLUT_BITMAP_9_BY_15,"F6 = SimVertex : ON/OFF");
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/10,WINDOW_HEIGHT - 100,GLUT_BITMAP_9_BY_15,"F7 = PSimHits : ON/OFF");
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/10,WINDOW_HEIGHT - 125,GLUT_BITMAP_9_BY_15,"F8 = RecoTrack : ON/OFF");
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/2,WINDOW_HEIGHT - 50 ,GLUT_BITMAP_9_BY_15,"LEFT = Previous Event");
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/2,WINDOW_HEIGHT - 75 ,GLUT_BITMAP_9_BY_15,"RIGHT = Next Event");
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/2,WINDOW_HEIGHT - 100,GLUT_BITMAP_9_BY_15,"UP = Increase Rotation");
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/2,WINDOW_HEIGHT - 125,GLUT_BITMAP_9_BY_15,"DOWN = Decrease Rotation");
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/2,WINDOW_HEIGHT - 150,GLUT_BITMAP_9_BY_15,"p = Zoom In");
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/2,WINDOW_HEIGHT - 175,GLUT_BITMAP_9_BY_15,"m = Zoom Out");
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/10,WINDOW_HEIGHT - 300,GLUT_BITMAP_9_BY_15,"You can scan the SimTrack collection using : ");
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/10,WINDOW_HEIGHT - 320,GLUT_BITMAP_9_BY_15,"a = next SimTrack");
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/10,WINDOW_HEIGHT - 340,GLUT_BITMAP_9_BY_15,"q = previous SimTrack");
char temp[255];sprintf(temp,"The Current SimTrack is drawn in white (only if PT>%3.1f)",PT_CUTOFF);
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/10,WINDOW_HEIGHT - 360,GLUT_BITMAP_9_BY_15,temp);
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/10,WINDOW_HEIGHT - 400,GLUT_BITMAP_9_BY_15,"ScreenShot can be done with 'ENTER', the file name is ScreenShot.bmp");
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/10,100,GLUT_BITMAP_9_BY_15,"SPACE = Rotation : ON/OFF");
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH/10,75,GLUT_BITMAP_9_BY_15,"ESCAPE = Exit");
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, 5,5,GLUT_BITMAP_9_BY_15,"This program has been created by Loic Quertenmont, loic.quertenmont@cern.ch");
}else{
// renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, 5,WINDOW_HEIGHT - 25,GLUT_BITMAP_9_BY_15,"If you need some Help, Press F1");
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, 5,WINDOW_HEIGHT - 25,GLUT_BITMAP_9_BY_15,"Need Help? Press F1");
char temp[255]; sprintf(temp,"Event %02i / %02i",events->Current_Event+1, (int)events->Events.size());
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH-150,WINDOW_HEIGHT - 25,GLUT_BITMAP_9_BY_15,temp);
if(mColl_I == ObjectsColl::SIM_TRACK && mObj_I >= 0){
if(mObj_I>=(int) event->MySimTrackCollection.size())mObj_I=0;
MySimTrack* track = event->MySimTrackCollection[mObj_I];
sprintf(temp,"SimTrack%03i : Charge=%+1.0f",mObj_I,track->charge);
sprintf(temp,"%s E=% 7.2f",temp,track->E);
sprintf(temp,"%s P=(%5.2f,%5.2f,%5.2f)",temp,track->Px,track->Py,track->Pz);
sprintf(temp,"%s Pt=% 6.2f",temp, sqrt(track->Px*track->Px + track->Py*track->Py) );
sprintf(temp,"%s Type=%i",temp, (int)track->Type );
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, 5,5,GLUT_BITMAP_9_BY_15,temp);
}
else if(mColl_I == ObjectsColl::HCAL_HIT && mObj_I >= 0){
if(mObj_I>=(int) event->MyHcalCaloHitCollection.size())mObj_I=0;
MyCaloHit* hit = event->MyHcalCaloHitCollection[mObj_I];
sprintf(temp,"HCal Hit%04i : ",mObj_I);
sprintf(temp,"%s E=% 6.2f",temp,hit->E);
sprintf(temp,"%s DetId = %i",temp,hit->DetId);
renderBitmapString(WINDOW_WIDTH, WINDOW_HEIGHT, 5,5,GLUT_BITMAP_9_BY_15,temp);
}
}
DrawLogo(WINDOW_WIDTH, WINDOW_HEIGHT,5,20,120,80,LogoTexture);
glutSwapBuffers();
}
void defineColorForSimTrack(unsigned int i) {
if(mColl_I == ObjectsColl::SIM_TRACK && i==mObj_I){
glLineWidth(WaC_Selected_SimTrack.W);
glColor4d (WaC_Selected_SimTrack.R,WaC_Selected_SimTrack.G,WaC_Selected_SimTrack.B,WaC_Selected_SimTrack.A);
}else{
bool has_been_found = false;
for(unsigned int j=0;j<WaC_SimTracks.size() && !has_been_found ; j++){
if(event->MySimTrackCollection[i]->Type == WaC_SimTracks[j]->Id){
glLineWidth(WaC_SimTracks[j]->W);
glColor4d (WaC_SimTracks[j]->R,WaC_SimTracks[j]->G,WaC_SimTracks[j]->B,WaC_SimTracks[j]->A);
has_been_found = true;
}
}
int charge = (int)event->MySimTrackCollection[i]->charge;
if(abs(charge)>1)charge/=abs(charge);
for(unsigned int j=0;j<WaC_SimTracks.size() && !has_been_found ; j++){
if(charge*97 == WaC_SimTracks[j]->Id){
glLineWidth(WaC_SimTracks[j]->W);
glColor4d (WaC_SimTracks[j]->R,WaC_SimTracks[j]->G,WaC_SimTracks[j]->B,WaC_SimTracks[j]->A);
has_been_found = true;
}
}
if(!has_been_found){
glLineWidth(WaC_Default_SimTrack.W);
glColor4d (WaC_Default_SimTrack.R,WaC_Default_SimTrack.G,WaC_Default_SimTrack.B,WaC_Default_SimTrack.A);
}
}
}
void initGeomEcal(){
for(unsigned d=0;d<3;d++){
theGeomEcal[d] = glGenLists (1);
glNewList(theGeomEcal[d], GL_COMPILE);
std::map<unsigned int,CaloDet*, std::less<unsigned int> >::iterator it;
for(it=geom->Det_ECAL_ALL.begin();it!=geom->Det_ECAL_ALL.end();it++){
unsigned int SubDet = (it->second->DetId>>25)&0x7;
if(SubDet != d+1) continue;
if(SubDet == 1) glColor4d (0.5,0,1,0.05);
if(SubDet == 2) glColor4d (1,0.5,1,0.05);
if(SubDet == 3) glColor4d (0.5,0.5,0.5,0.05);
CaloDet* cell = it->second;
DrawDet(cell);
}
glEndList();
}
}
void initGeomEcalInEvent(){
theGeomEcalInEvent = glGenLists (1);
glNewList(theGeomEcalInEvent, GL_COMPILE);
for(unsigned int i=0;i<event->MyEcalCaloHitCollection.size();i++)
{
int SubDet = (event->MyEcalCaloHitCollection[i]->DetId>>25)&0x7;
double E = event->MyEcalCaloHitCollection[i]->E;
if(E<EECAL_CUTOFF[SubDet-1])continue;
CaloDet* cell = geom->Find_CaloDet(event->MyEcalCaloHitCollection[i]->DetId);
if(cell!=NULL){
glColor4d (1,1,0,0.75*log10(E/EECAL_CUTOFF[SubDet-1]));
glLoadName( (ObjectsColl::ECAL_HIT<<25) | i );
DrawDet(cell);
}
}
glEndList();
}
void initGeomHcal() {
for(unsigned d=0;d<4;d++){
theGeomHcal[d] = glGenLists (1);
glNewList(theGeomHcal[d], GL_COMPILE);
std::map<unsigned int,CaloDet*, std::less<unsigned int> >::iterator it;
for(it=geom->Det_HCAL_ALL.begin();it!=geom->Det_HCAL_ALL.end();it++){
unsigned int SubDet = (it->second->DetId>>25)&0x7;
if(SubDet != d+1) continue;
if(SubDet == 1) glColor4d (0.5,0,1,0.05);
if(SubDet == 2) glColor4d (1,0.5,1,0.05);
if(SubDet == 3) glColor4d (0.5,0.5,0.5,0.05);
if(SubDet == 4) glColor4d (1,1,1,0.05);
CaloDet* cell = it->second;
DrawDet(cell);
}
glEndList();
}
}
void initGeomHcalInEvent() {
theGeomHcalInEvent = glGenLists (1);
glNewList(theGeomHcalInEvent, GL_COMPILE);
for(unsigned int i=0;i<event->MyHcalCaloHitCollection.size();i++)
{
int SubDet = (event->MyHcalCaloHitCollection[i]->DetId>>25)&0x7;
double E = event->MyHcalCaloHitCollection[i]->E;
if(E<EHCAL_CUTOFF[SubDet-1])continue;
CaloDet* cell = geom->Find_CaloDet(event->MyHcalCaloHitCollection[i]->DetId);
if(cell!=NULL){
glColor4d (1,0,0,0.75*log10(E/EHCAL_CUTOFF[SubDet-1]));
glLoadName( (ObjectsColl::HCAL_HIT<<25) | i );
DrawDet(cell);
}
}
glEndList();
}
void initGeomMuon() {
for(unsigned d=0;d<3;d++){
theGeomMuon[d] = glGenLists (1);
glNewList(theGeomMuon[d], GL_COMPILE);
std::map<unsigned int,TrackerDet*, std::less<unsigned int> >::iterator it;
for(it=geom->Det_Muon_ALL.begin();it!=geom->Det_Muon_ALL.end();it++){
unsigned int SubDet = (it->second->DetId>>25)&0x7;
if(SubDet != d+1) continue;
if(SubDet == 1) glColor4d (1,0,0,0.05);
if(SubDet == 2) glColor4d (1,0.5,0,0.05);
if(SubDet == 3) glColor4d (1,0 ,0.5,0.05);
TrackerDet* det = it->second;
DrawSquare(det->PosX,det->PosY,det->PosZ,det->WidthX,det->WidthY,det->WidthZ,
det->LengthX,det->LengthY,det->LengthZ,det->ThickX,det->ThickY,det->ThickZ,
det->TrapezoidalParam);
}
glEndList();
}
}
void initGeomMuonInEvent(){
theGeomMuonInEvent = glGenLists (1);
glNewList(theGeomMuonInEvent, GL_COMPILE);
for(unsigned int i=0;i<event->MyMuonSegmentCollection.size();i++)
{
TrackerDet* det = geom->Find_TrackerDet(event->MyMuonSegmentCollection[i]->DetId);
if(det!=NULL){
glColor4d (1,0.5,0.5,1);
DrawSquare(det->PosX,det->PosY,det->PosZ,det->WidthX,det->WidthY,det->WidthZ,
det->LengthX,det->LengthY,det->LengthZ,det->ThickX,det->ThickY,det->ThickZ,
det->TrapezoidalParam);
}
glColor4d (1,1,0,1);
glLoadName( (ObjectsColl::MUON_SEG<<25) | i );
DrawSeg(event->MyMuonSegmentCollection[i]);
}
for(unsigned int i=0;i<event->MyMuonHitCollection.size();i++)
{
TrackerDet* det = geom->Find_TrackerDet(event->MyMuonHitCollection[i]->DetId);
if(det!=NULL){
glColor4d (0.5,0.5,1,1);
DrawSquare(det->PosX,det->PosY,det->PosZ,det->WidthX,det->WidthY,det->WidthZ,
det->LengthX,det->LengthY,det->LengthZ,det->ThickX,det->ThickY,det->ThickZ,
det->TrapezoidalParam);
}
glColor4d (1,1,0,1);
glLoadName( (ObjectsColl::MUON_HIT<<25) | i );
DrawSquare(3.0,event->MyMuonHitCollection[i]->x,event->MyMuonHitCollection[i]->y,event->MyMuonHitCollection[i]->z);
}
glEndList();
}
void initGeomTracker(){
for(unsigned d=0;d<6;d++){
theGeomTracker[d] = glGenLists (1);
glNewList(theGeomTracker[d], GL_COMPILE);
std::map<unsigned int,TrackerDet*, std::less<unsigned int> >::iterator it;
for(it=geom->Det_Tracker_ALL.begin();it!=geom->Det_Tracker_ALL.end();it++){
unsigned int SubDet = (it->second->DetId>>25)&0x7;
if(SubDet != (d+1)) continue;
if(SubDet == 1) glColor4d (1,0,0,0.05);
if(SubDet == 2) glColor4d (0,1,0,0.05);
if(SubDet == 3) glColor4d (1,1,1,0.05);
if(SubDet == 4) glColor4d (1,1,0,0.05);
if(SubDet == 5) glColor4d (1,0,1,0.05);
if(SubDet == 6) glColor4d (0,1,1,0.05);
TrackerDet* det = it->second;
DrawSquare(det->PosX,det->PosY,det->PosZ,det->WidthX,det->WidthY,det->WidthZ,
det->LengthX,det->LengthY,det->LengthZ,det->ThickX,det->ThickY,det->ThickZ,
det->TrapezoidalParam);
}
glEndList();
}
}
void initGeomTrackerInEvent() {
theGeomTrackerInEvent = glGenLists (1);
glNewList(theGeomTrackerInEvent, GL_COMPILE);
for(unsigned int i=0;i<event->MyRecoTrackCollection.size();i++){
MyRecoTrack* track = event->MyRecoTrackCollection[i];
if(track==NULL)continue;
glColor3d (0.5,0.5,0);
glBegin (GL_LINE_STRIP);
for( unsigned int j=0; j < (track->Hits.size()); j++ ){
glVertex3d (track->Hits[j]->x,track->Hits[j]->y,track->Hits[j]->z);
}
glEnd();
for( unsigned int j=0; j < (track->Hits.size()); j++ ){
glColor3d (0.8,0.8,0);
DrawSquare(1.0,track->Hits[j]->x,track->Hits[j]->y,track->Hits[j]->z);
TrackerDet* det = geom->Find_TrackerDet(track->Hits[j]->DetId);
if(det!=NULL){
//printf("DetId = %i<>%i %f %f %f\n",track->Hits[j].DetId,det->DetId,det->PosX,det->PosY,det->PosZ);
glColor4d (1,1,1,1);
DrawSquare(det->PosX,det->PosY,det->PosZ,det->WidthX,det->WidthY,det->WidthZ,
det->LengthX,det->LengthY,det->LengthZ,det->ThickX,det->ThickY,det->ThickZ,
det->TrapezoidalParam);
}else{printf("TrackerDetNull\n");}
}
}
glEndList();
}
void initSimTrack()
{
if(mColl_I == ObjectsColl::SIM_TRACK && mObj_I >=(int) event->MySimTrackCollection.size())mObj_I=-1;
theSimTracks.clear();
for(unsigned int i=0;i<event->MySimTrackCollection.size();i++) {
theSimTracks.push_back(glGenLists(1));
glNewList(theSimTracks[i], GL_COMPILE);
MySimTrack* track = event->MySimTrackCollection[i];
//if(track->parent_vertex==0)continue;
//if(track->charge!=0 && sqrt( track->Px * track->Px + track->Py * track->Py ) < 0.9)continue;
if(sqrt( track->Px * track->Px + track->Py * track->Py ) < PT_CUTOFF){
glEndList();
continue;
}
if((unsigned int)(track->parent_vertex)>=event->MySimVertexCollection.size()){
continue;
glEndList();
continue;
}
MySimVertex* vertex1 = event->MySimVertexCollection[track->parent_vertex];
MySimVertex* vertex2 = NULL;
for(unsigned int j=0; j<event->MySimVertexCollection.size();j++){
if(event->MySimVertexCollection[j]->parentTrack_id == track->track_id){
vertex2 = event->MySimVertexCollection[j];
j = event->MySimVertexCollection.size();
}
}
DrawTrack(i, vertex1, vertex2);
glEndList();
}
}
void init()
{
event = events->GetEvent();
if(gSim & 2) initSimTrack();
if(gReco & 1) initGeomTrackerInEvent();
if(gReco & 2) initGeomEcalInEvent();
if(gReco & 4) initGeomHcalInEvent();
if(gReco & 8) initGeomMuonInEvent();
}
void processNormalKeys(unsigned char key, int x, int y)
{
int Mod = glutGetModifiers();
if(Mod==GLUT_ACTIVE_CTRL)key+=96;
switch(key){
case 27 :
exit(0);
break;
#ifndef linux
case 13 :
char temp[255]; sprintf(temp,"screenshot%02i.bmp",SCREENSHOT);
SaveBMPScreenshot(temp,WINDOW_WIDTH,WINDOW_HEIGHT);
SCREENSHOT++;
break;
#endif
case ' ':
mRotate = ! mRotate;
break;
case 'a' :
// mTrackI++;
// if(mTrackI>=(int) event->MySimTrackCollection.size())mTrackI=-1;
break;
case 'q' :
// mTrackI--;
// if(mTrackI<-1)mTrackI=event->MySimTrackCollection.size()-1;
break;
case 'p' :
CAM_R*=0.95;
break;
case 'm' :
CAM_R*=1.05;
break;
case 't' :
gTracker++;
if(gTracker==64)gTracker=0;
break;
case 'e' :
gEcal++;
if(gEcal==16)gEcal=0;
break;
case 'h' :
gHcal++;
if(gHcal==32)gHcal=0;
break;
case 'R' :
LoadCard("config.txt");
events->GoToEvent(eventNumber-1);
init();
break;
case 'l':
if(Mod == GLUT_ACTIVE_CTRL){
if(FULLSCREEN){
glutReshapeWindow(SAVE_WINDOW_W, SAVE_WINDOW_H);
glutPositionWindow(SAVE_WINDOW_X,SAVE_WINDOW_Y);
}else{
SAVE_WINDOW_W = glutGet(GLUT_WINDOW_WIDTH);
SAVE_WINDOW_H = glutGet(GLUT_WINDOW_HEIGHT);
SAVE_WINDOW_X = glutGet(GLUT_WINDOW_X);
SAVE_WINDOW_Y = glutGet(GLUT_WINDOW_Y);
glutFullScreen();
}
FULLSCREEN = !FULLSCREEN;
}
break;
case 'n':
TEMP_I++;
if(TEMP_I == (int)geom->Det_HCAL_ALL.size())TEMP_I=0;
break;
case 'b':
TEMP_I--;
if(TEMP_I<0)TEMP_I = geom->Det_HCAL_ALL.size()-1;
break;
}
}
void processSpecialKeys(int key, int x, int y)
{
switch(key) {
case GLUT_KEY_F1 :
mHelpScreen = !mHelpScreen;
break;
case GLUT_KEY_F5 :
gSim = gSim ^ 2;
if( gSim&2 ) initSimTrack();
break;
case GLUT_KEY_F6 :
gSim = gSim ^ 4;
break;
case GLUT_KEY_F7 :
gSim = gSim ^ 1;
break;
case GLUT_KEY_F8 :
gReco = gReco ^ 1;
if(gReco&1)initGeomTrackerInEvent();
break;
case GLUT_KEY_F9 :
gReco = gReco ^ 2;
if(gReco&2)initGeomEcalInEvent();
break;
case GLUT_KEY_F10 :
gReco = gReco ^ 4;
if(gReco&4)initGeomHcalInEvent();
break;
case GLUT_KEY_F11 :
gReco = gReco ^ 8;
if(gReco&8)initGeomMuonInEvent();
break;
case GLUT_KEY_RIGHT :
events->NextEvent();
init();
break;
case GLUT_KEY_LEFT :
events->PreviousEvent();
init();
break;
case GLUT_KEY_UP :
mDt += 0.005f;
break;
case GLUT_KEY_DOWN :
mDt -= 0.005f;
break;
}
}
void processMouse(int button, int state, int x, int y)
{
int K = 0;
if(button == GLUT_LEFT_BUTTON){
K = 0;
if(state == GLUT_DOWN) gl_select(x,WINDOW_HEIGHT-y);
}else if(button == GLUT_MIDDLE_BUTTON ){
K = 1;
}else if(button == GLUT_RIGHT_BUTTON){
K = 2;
}else{
}
if(state == GLUT_DOWN) MouseStates[K] = true;
if(state == GLUT_UP) MouseStates[K] = false;
}
void gl_select(int x, int y)
{
GLuint buff[64] = {0};
GLint hits, view[4];
glSelectBuffer(64, buff);
glGetIntegerv(GL_VIEWPORT, view);
glRenderMode(GL_SELECT);
glInitNames();
glPushName(0);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPickMatrix(x-3, y-3, 6.0, 6.0, view);
gluPerspective (45.0, (GLfloat)WINDOW_WIDTH/(GLfloat)WINDOW_HEIGHT, 0.1, 5000.0);
glMatrixMode(GL_MODELVIEW);
glutSwapBuffers();
if(gReco&1){glCallList(theGeomTrackerInEvent);}
if(gReco&2){glCallList(theGeomEcalInEvent);}
if(gReco&4){glCallList(theGeomHcalInEvent);}
if(gReco&8){glCallList(theGeomMuonInEvent);}
if(gSim &2){
for(unsigned int i=0;i<event->MySimTrackCollection.size();i++) {
glLoadName( (ObjectsColl::SIM_TRACK<<25) | i);
glCallList(theSimTracks[i]);
}
glLineWidth(1);
}
glMatrixMode(GL_PROJECTION);
glPopMatrix();
hits = glRenderMode(GL_RENDER);
list_hits(hits, buff);
glMatrixMode(GL_MODELVIEW);
}
void list_hits(GLint hits, GLuint *names)
{
int i;
// names[i * 4 + 0] = 1 names[i * 4 + 1] = MinZ
// names[i * 4 + 3] = Name names[i * 4 + 2] = MaxZ
//get Min in Z;
unsigned int MinZ = (unsigned int)-1;
unsigned int NearestHit = 0;
for (i = 0; i < hits; i++){
if( names[i*4+1]<MinZ ){MinZ=names[i*4+1]; NearestHit = i;}
}
for (i = 0; i < hits; i++) {
if(i == NearestHit){
unsigned int tmp = names[i * 4 + 3];
mColl_I = tmp >> 25;
mObj_I = tmp & ((1<<25)-1);
//printf("%i - %i\n",mColl_I,mObj_I);
}
}
}
void processMotion(int x, int y) {
if(MouseStates[2]){
static int xold=x, yold=y;
CAM_tx = CAM_tx+10.0*((float)(xold-x)/(float)CAM_R);
CAM_ty = CAM_ty+10.0*((float)(yold-y)/(float)CAM_R);
xold=x; yold=y;
}
}
void menu_callback(int value)
{
switch(value){
case 111: gTracker = gTracker^ 1; menu_create();break;
case 112: gTracker = gTracker^ 2; menu_create();break;
case 113: gTracker = gTracker^ 4; menu_create();break;
case 114: gTracker = gTracker^ 8; menu_create();break;
case 115: gTracker = gTracker^16; menu_create();break;
case 116: gTracker = gTracker^32; menu_create();break;
case 121: gMuon = gMuon ^ 1; menu_create();break;
case 122: gMuon = gMuon ^ 2; menu_create();break;
case 123: gMuon = gMuon ^ 4; menu_create();break;
case 131: gEcal = gEcal ^ 1; menu_create();break;
case 132: gEcal = gEcal ^ 2; menu_create();break;
case 133: gEcal = gEcal ^ 4; menu_create();break;
case 141: gHcal = gHcal ^ 1; menu_create();break;
case 142: gHcal = gHcal ^ 2; menu_create();break;
case 143: gHcal = gHcal ^ 4; menu_create();break;
case 144: gHcal = gHcal ^ 8; menu_create();break;
case 21: gSim = gSim ^ 1; menu_create();break;
case 22: gSim = gSim ^ 2; menu_create();initSimTrack(); break;
case 23: gSim = gSim ^ 4; menu_create();break;
case 31: gReco = gReco ^ 1; menu_create();initGeomTrackerInEvent();break;
case 32: gReco = gReco ^ 2; menu_create();initGeomEcalInEvent(); break;
case 33: gReco = gReco ^ 4; menu_create();initGeomHcalInEvent(); break;
case 34: gReco = gReco ^ 8; menu_create();initGeomMuonInEvent(); break;
}
return;
}
void menu_create()
{
Menu_Geom_Tracker = glutCreateMenu(menu_callback);
if(gTracker&1){ glutAddMenuEntry("PIB : ON" , 111);
}else{ glutAddMenuEntry("PIB : OFF" , 111);}
if(gTracker&2){ glutAddMenuEntry("PIE : ON" , 112);
}else{ glutAddMenuEntry("PIE : OFF" , 112);}
if(gTracker&4){ glutAddMenuEntry("TIB : ON" , 113);
}else{ glutAddMenuEntry("TIB : OFF" , 113);}
if(gTracker&8){ glutAddMenuEntry("TID : ON" , 114);
}else{ glutAddMenuEntry("TID : OFF" , 114);}
if(gTracker&16){ glutAddMenuEntry("TOB : ON" , 115);
}else{ glutAddMenuEntry("TOB : OFF" , 115);}
if(gTracker&32){ glutAddMenuEntry("TEC : ON" , 116);
}else{ glutAddMenuEntry("TEC : OFF" , 116);}
Menu_Geom_Muon = glutCreateMenu(menu_callback);
if(gMuon&1){ glutAddMenuEntry("DT : ON" , 121);
}else{ glutAddMenuEntry("DT : OFF" , 121);}
if(gMuon&2){ glutAddMenuEntry("CSC : ON" , 122);
}else{ glutAddMenuEntry("CSC : OFF" , 122);}
if(gMuon&4){ glutAddMenuEntry("RPC : ON" , 123);
}else{ glutAddMenuEntry("RPC : OFF" , 123);}
Menu_Geom_Ecal = glutCreateMenu(menu_callback);
if(gEcal&1){ glutAddMenuEntry("EB : ON" , 131);
}else{ glutAddMenuEntry("EB : OFF" , 131);}
if(gEcal&2){ glutAddMenuEntry("EE : ON" , 132);
}else{ glutAddMenuEntry("EE : OFF" , 132);}
if(gEcal&4){ glutAddMenuEntry("PS : ON" , 133);
}else{ glutAddMenuEntry("PS : OFF" , 133);}
Menu_Geom_Hcal = glutCreateMenu(menu_callback);
if(gHcal&1){ glutAddMenuEntry("HB : ON" , 141);
}else{ glutAddMenuEntry("HB : OFF" , 141);}
if(gHcal&2){ glutAddMenuEntry("HE : ON" , 142);
}else{ glutAddMenuEntry("HE : OFF" , 142);}
if(gHcal&4){ glutAddMenuEntry("HO : ON" , 143);
}else{ glutAddMenuEntry("HO : OFF" , 143);}
if(gHcal&8){ glutAddMenuEntry("HF : ON" , 144);
}else{ glutAddMenuEntry("HF : OFF" , 144);}
Menu_Geom = glutCreateMenu(menu_callback);
glutAddSubMenu("Tracker" , Menu_Geom_Tracker);
glutAddSubMenu("ECAL" , Menu_Geom_Ecal);
glutAddSubMenu("HCAL" , Menu_Geom_Hcal);
glutAddSubMenu("Muon" , Menu_Geom_Muon);
Menu_SimEvent = glutCreateMenu(menu_callback);
if(gSim&1) glutAddMenuEntry("SimHit : ON" , 21);
else glutAddMenuEntry("SimHit : OFF" , 21);
if(gSim&2) glutAddMenuEntry("SimTrack : ON" , 22);
else glutAddMenuEntry("SimTrack : OFF" , 22);
if(gSim&4) glutAddMenuEntry("SimVertex : ON" , 23);
else glutAddMenuEntry("SimVertex : OFF" , 23);
Menu_RecoEvent = glutCreateMenu(menu_callback);
if(gReco&1) glutAddMenuEntry("Track : ON" , 31);
else glutAddMenuEntry("Track : OFF" , 31);
if(gReco&2) glutAddMenuEntry("Ecal Hit : ON" , 32);
else glutAddMenuEntry("Ecal Hit : OFF" , 32);
if(gReco&4) glutAddMenuEntry("Hcal Hit : ON" , 33);
else glutAddMenuEntry("Hcal Hit : OFF" , 33);
if(gReco&8) glutAddMenuEntry("Muon Hit : ON" , 34);
else glutAddMenuEntry("Muon Hit : OFF" , 34);
Menu_Main = glutCreateMenu(menu_callback);
glutAddSubMenu("Geometry" , Menu_Geom);
glutAddSubMenu("SimEvent" , Menu_SimEvent);
glutAddSubMenu("RecoEvent", Menu_RecoEvent);
glutAttachMenu(GLUT_MIDDLE_BUTTON);
return;
}
void LoadCard(const char* inputCard ) {
printf("-----------------------------------------------------------------------\n");
ReadCards r(inputCard);
printf("-----------------------------------------------------------------------\n\n\n");
if(r.IsTagPresent("InputVisFile")){
inputVisFile = r.GetString("InputVisFile");
}else{
printf("There is No Input file in the Config card\n");
exit(0);
}
if(r.IsTagPresent("InputTrackerGeom")) inputTrackerGeom = r.GetString("InputTrackerGeom");
if(r.IsTagPresent("InputEcalGeom")) inputEcalGeom = r.GetString("InputEcalGeom");
if(r.IsTagPresent("InputHcalGeom")) inputHcalGeom = r.GetString("InputHcalGeom");
if(r.IsTagPresent("InputMuonGeom")) inputMuonGeom = r.GetString("InputMuonGeom");
if(r.IsTagPresent("eventNumber")) eventNumber = (int)r.GetInt("eventNumber");
if(r.IsTagPresent("Pt_cutoff")) PT_CUTOFF = r.GetFloat("Pt_cutoff");
if(r.IsTagPresent("Eecal_cutoff")){
std::vector<double> tmp = r.GetFloatVector("Eecal_cutoff");
if(tmp.size()>=3){
EECAL_CUTOFF[0] = tmp[0];
EECAL_CUTOFF[1] = tmp[1];
EECAL_CUTOFF[2] = tmp[2];
}else{
EECAL_CUTOFF[0] = tmp[0];
EECAL_CUTOFF[1] = tmp[0];
EECAL_CUTOFF[2] = tmp[0];
}
}
if(r.IsTagPresent("Ehcal_cutoff")){
std::vector<double> tmp = r.GetFloatVector("Ehcal_cutoff");
if(tmp.size()>=4){
EHCAL_CUTOFF[0] = tmp[0];
EHCAL_CUTOFF[1] = tmp[1];
EHCAL_CUTOFF[2] = tmp[2];
EHCAL_CUTOFF[3] = tmp[3];
}else{
EHCAL_CUTOFF[0] = tmp[0];
EHCAL_CUTOFF[1] = tmp[0];
EHCAL_CUTOFF[2] = tmp[0];
EHCAL_CUTOFF[3] = tmp[0];
}
}
if(r.IsTagPresent("WaC_BackGround")) WaC_BackGround = r.GetWidthAndColor("WaC_BackGround");
if(r.IsTagPresent("WaC_Txt")) WaC_Txt = r.GetWidthAndColor("WaC_Txt");
if(r.IsTagPresent("WaC_CMS_Framework")) WaC_CMS_Framework = r.GetWidthAndColor("WaC_CMS_Framework");
if(r.IsTagPresent("WaC_LHC_Axis")) WaC_LHC_Axis = r.GetWidthAndColor("WaC_LHC_Axis");
if(r.IsTagPresent("WaC_Default_SimTrack")) WaC_Default_SimTrack = r.GetWidthAndColor("WaC_Default_SimTrack");
if(r.IsTagPresent("WaC_Selected_SimTrack"))WaC_Selected_SimTrack = r.GetWidthAndColor("WaC_Selected_SimTrack");
if(r.IsTagPresent("WaC_Particular_SimTracks")){
for(unsigned int i=0;i<WaC_SimTracks.size();i++){delete WaC_SimTracks[i];}
WaC_SimTracks.clear();
WaC_SimTracks = r.GetIdAndWidthAndColorVector("WaC_Particular_SimTracks");
for(unsigned int i=0;i<WaC_SimTracks.size();i++){
WidthAndColor* WaC_temp = NULL;
if(WaC_SimTracks[i]->Id == 99) WaC_temp = &WaC_Default_SimTrack;
if(WaC_SimTracks[i]->Id == 98) WaC_temp = &WaC_Selected_SimTrack;
if(WaC_temp!=NULL){
WaC_temp->W = WaC_SimTracks[i]->W;
WaC_temp->R = WaC_SimTracks[i]->R;
WaC_temp->G = WaC_SimTracks[i]->G;
WaC_temp->B = WaC_SimTracks[i]->B;
WaC_temp->A = WaC_SimTracks[i]->A;
}
}
}
}
int main (int argc, char *argv[])
{
// initialisation de GLUT
glutInit (&argc, argv);
// cr饌tion d'une fen黎re OpenGL RVBA avec en simple m駑oire tampon
// avec un tampon de profondeur
glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize (WINDOW_WIDTH, WINDOW_HEIGHT);
glutCreateWindow ("FROG Displayer");
stTexture* Temp = new stTexture;
LoadBMP(Temp, "Logo.bmp", 255,255,255);
glGenTextures(1,&LogoTexture); //G駭鑽e un nー de texture
glBindTexture(GL_TEXTURE_2D,LogoTexture); //S駘ectionne ce nー
glTexImage2D ( GL_TEXTURE_2D, 0, Temp->internalFormat,Temp->width, Temp->height,
0, Temp->format, GL_UNSIGNED_BYTE, Temp->texels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D,0);
// initialisation des fonctions callback appel馥s par glut
// pour respectivement le redimensionnement de la fen黎re
// et le rendu de la sc鈩e
glutReshapeFunc (reshape);
glutDisplayFunc (display);
glutIdleFunc (display);
// here are the new entries
glutKeyboardFunc (processNormalKeys);
glutSpecialFunc (processSpecialKeys);
glutMouseFunc(processMouse);
glutMotionFunc(processMotion);
// entre dans la boucle d'騅鈩ements
glutMainLoop ();
return 0;
}

File Metadata

Mime Type
text/x-c
Expires
Sun, Feb 23, 2:27 PM (15 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4481471
Default Alt Text
main.cpp (35 KB)

Event Timeline