HOWTO add private code to a DANA application
hd_ana and other DApps, in and of themselves, will not call any user code. To introduce user code one needs to write a class which derives from JEventProcessor and then register that class with the DApplication.
The JEventProcessor-inheriting class, let's call it MyProcessor, contains methods which include:
- init called at initialization time
- fini called at end of processing
- brun called at the beginning of each run
- erun called at the end of each run
- evnt called for every event
Registration can be done with the AddProcessor method of the DApplication or by passing a pointer to the processor object to the Run method of DApplication. See examples below.
Adding a single processor
int main(int narg, char *argv[]) { // Instantiate an event loop object DApplication app(narg, argv); // Create object with private code MyProcessor myproc; // Register private code with application and run though all events app.Run(&myproc); return 0; }
Adding multiple processors
Any number of JEventProcessors can be added to the application. This is useful when one has multiple, independent analyses that may have overlapping requirements (e.g. both require track and photon reconstruction). This ensures that the CPU expensive parts are done once and shared by all processes.
int main(int narg, char *argv[]) { // Instantiate an event loop object DApplication app(narg, argv); // Create objects with private code MyProcessor1 myproc1; MyProcessor2 myproc2; MyProcessor3 myproc3; // Register private code with the application app.AddProcessor(&myproc1); app.AddProcessor(&myproc2); app.AddProcessor(&myproc3); // Run though all events app.Run(); // Processors already added so no arguments are needed for ''Run'' return 0; }
Each processor will be called for every event. Processors will be called in the order they are registered.
Advanced: Automatic object deletion
In the above examples, the processor objects are created on the stack and so are implicitly deleted when main returns. One tempting modification for the above code would be to simultaneously instantiate the processor objects on the heap and register them like this:
// Instantiating on the heap app.AddProcessor(new MyProcessor1(), true); app.AddProcessor(new MyProcessor2(), true); app.AddProcessor(new MyProcessor3(), true);
The second argument of "true" tells the framework to take ownership of the object and explicitly delete it before Run returns at the end of event processing. If "true" were not passed in the above example, then it becomes the responsibility of the DANA application author to delete the processor objects. (Note: one can get an STL vector of the JEventProcessor pointers using the DApplication::GetProcessors() method, but for most cases, authors will just want to pass the "true" argument.) The second boolean argument of AddProcessor is needed since the author can pass pointers to stack allocated objects as well as heap objects. Attempting to call delete on stack objects will cause program errors and no common mechanism exists across platforms for determining the nature of a pointer from the pointer itself.
See the section on Event Processors in the JANA manual for more details.