frog is hosted by Hepforge, IPPP Durham

FROG

FROG Logo

Home

Tutorials

Download

UserManual

FAQ

SVN (deprecated)
Github

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++) {
    // we get the nuclear interactions from the event
edm::Handle<std::vector<reco::NuclearInteraction> > h_NIs;
iEvent.getByLabel(NIProducers[i], h_NIs);
std::vector<reco::NuclearInteraction> NIs = *h_NIs.product();
// we define the collection which will contain all the nuclear interactions FROG_Element_Base_With_DetId* frogNIColl = new FROG_Element_Base_With_DetId(C_FEB_DETID, EVTID_NUCLINT + i);
// this collection is added to the event event->addDaughter(frogNIColl);

for(unsigned int h=0; h<NIs.size();h++){
// we get the vertex position and the likelihood of the nuclear interaction 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();
// the Frog nuclear interaction object is created FROG_Element_Event_NuclInt* frogNI = new FROG_Element_Event_NuclInt(vtx_x, vtx_y, vtx_z, like );
// the nuclear interaction is added to the collection 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 !