How to create your own object in FROG
1. Create your own class
This class has to inherit from FROG_Element_Base and has to have some specific data members and methods.
Let's see with an example. Imagine that we want to visualise a nuclear interaction. This object is simply a 3D position and a likelihood.
The class should look like this one :
#ifndef _FROG_ELEMENT_EVENT_NUCLINT_H__
#define _FROG_ELEMENT_EVENT_NUCLINT_H__
#include "FROG_Element_Base.h" #include "FROG_Objects_Extended.h"
class FROG_Element_Event_NuclInt : public FROG_Element_Base {
public :
// These are your own data members : float PosX; float PosY; float PosZ; float likelihood;
// These data members are required (but are not store) : FROG_Objects_Extended* frogObjects_; unsigned int nameId_;
//This method should stay like this
virtual bool isCompactible(){ return true; }
// method which returns the size (in bytes) of data to be written in the .vis or .geom file
static unsigned int sizeOf(){ return FROG_Element_Base::sizeOf() + 4*sizeof(float);}
// constructor used to define the object in the analyzer
FROG_Element_Event_NuclInt(float posX, float posY, float posZ, float likeli) : FROG_Element_Base(C_RECO_NUCL), PosX(posX), PosY(posY), PosZ(posZ), likelihood(likeli){
size_ = sizeOf();
}
// constructor used to read the data members in the .vis file
FROG_Element_Event_NuclInt(FILE* pFile) : FROG_Element_Base(C_RECO_NUCL){
size_ = sizeOf();
fread(&PosX ,sizeof(PosX) ,1,pFile);
fread(&PosY ,sizeof(PosY) ,1,pFile);
fread(&PosZ ,sizeof(PosZ) ,1,pFile);
fread(&likelihood ,sizeof(likelihood) ,1,pFile);
}
// method to write the data members in the .vis or .geom file
virtual void write(){
size_ = sizeOf();
data_ = new unsigned char[size_-6];
data_ = FillBuffer( data_, &PosX, sizeof(PosX));
data_ = FillBuffer( data_, &PosY, sizeof(PosY));
data_ = FillBuffer( data_, &PosZ, sizeof(PosZ));
data_ = FillBuffer( data_, &likelihood, sizeof(likelihood));
data_ = (unsigned char*)((unsigned long)data_ - (size_-6) ); }
#ifdef FROG_OPENGL
// method which display the object (specific to OPENGL)
virtual void display(bool UseDisplayList=true){
// first Init Colors & Style!
init(NULL);
// define name for selection mode
glLoadName( nameId_ );
// define the color
glColor4fv (style_->color_);
// draw the object
glBegin (GL_POINTS);
glVertex3d(PosX, PosY, PosZ);
glEnd(); }
#endif
// method used to print information when clicking on the object
virtual void printInfos(char* buffer){
sprintf(buffer,"Likelihood",likelihood);
}
// method called during initialisation of the object (don't change those lines)
virtual void init(void* frogObjects){
if(frogObjects!=NULL){
frogObjects_ = (FROG_Objects_Extended*) frogObjects;
nameId_ = frogObjects_->frogEvent_->name_map.size();
frogObjects_->frogEvent_->name_map.push_back(this);
}else if(frogObjects==NULL && frogObjects_ != NULL){
if(mother_ != NULL && mother_->style_ !=NULL){
style_ = mother_->style_;
}else{
style_ = new FROG_Objects_Style();
}
}
};
#endif
2. Definition of an identifiant for the created object type
You have to define an unique chunk id for the newly created object type. This id has to be defined in the file : soft/Includes/FROG/FROG_Chunk.h.
Example :
#define C_RECO_NUCL 12500 // Contains Chunks related to Nuclear interaction0
3. Tell Frog what to do when he finds the new object in the data file.
Now, You have to tell to Frog to create a new object of the type FROG_Element_Event_NuclInt when he find some data with a C_RECO_NUCL chunk ID . For this, In general, you only need to add a new case in the file : soft/Includes/FROG/FROG_Element_Tools.cpp.
Example :
case C_RECO_NUCL : NObjs = (chunk_size-chunk_read)/(FROG_Element_Event_NuclInt::sizeOf()-6); for(int i=0;i<NObjs;i++){ mother->addDaughter(new FROG_Element_Event_NuclInt(pFile)); chunk_read += FROG_Element_Event_NuclInt::sizeOf()-6; } break;
You also need to include your new class in soft/Includes/FROG/FROG_Element_Tools.h.
Example :
#include "FROG_Element_Event_NuclInt.h"
4. Definition of an identifiant for the created object
You have to define an unique id for the newly created object. This id has to be defined in the file : soft/Includes/FROG/FROG_DetId.h.
This Id and the ChunkId are completly different. The chunk Id allow Frog to identify an objects type from an other. While this Id (let's call it the DetId/EventId) are used to define a collection of physical stuff . For example a collection of NuclearInteraction.
So if you need to add a new collection of NuclearInteraction (e.g NuclearInteraction produced by a new algorithm), you only need to add a new EventId..., you don't need to create a new class. For track collection for example, because there is a lot of different algorithm, we just decided to increase the track EventId(EVTID_TRK) by 1 unit for each new track collection.
This Id will also allow you to configure your objects from the frog configuration file. (e.g display it, change color, and so on).
Example :
#define EVTID_NUCLINT 23200000
Remark that the id has to contain 8 digits.Please, try to follow same convention.
5. Modify the analyzer (The last step)
It is now possible to create your object and save it in a .vis file. This is basicaly a cast from one format to the new Frog format you just defined.
Here are the lines specific to the nuclear interaction in Frog_analyzer.cc :
for(unsigned int i=0;i<NIProducers.size();i++) {
edm::Handle<std::vector<reco::NuclearInteraction> > h_NIs; iEvent.getByLabel(NIProducers[i], h_NIs); std::vector<reco::NuclearInteraction> NIs = *h_NIs.product();
FROG_Element_Base_With_DetId* frogNIColl = new
FROG_Element_Base_With_DetId(C_FEB_DETID, EVTID_NUCLINT + i);
event->addDaughter(frogNIColl);
for(unsigned int h=0; h<NIs.size();h++){
reco::NuclearInteraction ni = NIs[i]; float vtx_x = ni.vertex().x();
float vtx_y = ni.vertex().y(); float vtx_z = ni.vertex().z(); float like = ni.likelihood();
FROG_Element_Event_NuclInt* frogNI = new FROG_Element_Event_NuclInt(vtx_x, vtx_y, vtx_z, like );
frogNIColl->addDaughter(frogNI);
}
]
6. Visualization
Now, the .vis file produced with the modified analyzer should contain the new objects.
Then you can change the file config.txt : you add the id of your new object in the vector EventToDisplay.
Finally you define the color (and other properties) of your objects in the file soft/Config/CMS_colors.txt. Example :
Id_23200000_Color = { 1.0 , 0.0 , 0.0 , 1.0 };
You are ready to see your object in 3D !
|