Warning, /EICrecon/docs/tutorial/03-end-user-plugin.md is written in an unsupported language. File is not indexed.
0001
0002
0003 | title | teaching | exercises | questions | objectives | keypoints |
0004 |---------------------------------------------------|----------|-----------|----------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
0005 | Creating a plugin to make custom histograms/trees | 15 | 20 | Why should a I make a custom plugin? <br/><br/> How do I create a custom plugin? | Understand when one should make a plugin and when they should just use a ROOT macro. <br/><br/>Understand how to create a new, stand-alone plugin with your own custom histograms. | Plugins can be used to generate custom histograms by attaching directly to the reconstruction process. <br/><br/> Plugins can be used for monitoring or custom analysis. |
0006
0007
0008
0009 Plugins are the basic building blocks when it comes to analyzing data. They request objects and perform actions, such as making histograms, or writing out certain objects to files. When your plugin requests objects (e.g. clusters) the factory responsible for the requested object is loaded and run (We will dive into factories in the next exciting episode of how to use JANA). When running EICrecon you will configure it to use some number of plugins (each potentially with their own set of configuration parameters). Now, let us begin constructing a new plugin.
0010
0011 To do this we will use the eicmkplugin.py script that comes with EICrecon. This utility should be your "go-to" for jumpstarting your work with EICrecon/JANA when it comes to data. To put eicmkplugin.py in your path, you can do the following:
0012 ~~~
0013 source EICrecon/bin/eicrecon-this.sh
0014 ~~~
0015
0016 The eickmkplugin script can be called simply by typing: "eicmkplugin.py" followed by the name of the plugin. Let's begin by calling:
0017 ~~~
0018 eicmkplugin.py myFirstPlugin
0019 ~~~
0020
0021 You should now have terminal output that looks like this:
0022 ~~~
0023 Writing myFirstPlugin/CMakeLists.txt ...
0024 Writing myFirstPlugin/myFirstPluginProcessor.h ...
0025 Writing myFirstPlugin/myFirstPluginProcessor.cc ...
0026
0027 Created plugin myFirstPlugin.
0028 Build with:
0029
0030 cmake -S myFirstPlugin -B myFirstPlugin/build
0031 cmake --build myFirstPlugin/build --target install
0032 ~~~
0033 There should now exist a new folder labeled "myPlugin". That directory contains 2 files: a CMakelists.txt file (needed for compiling our new plugin) and the source code for the plugin itself.
0034
0035 Inside the source code for your plugin is a fairly simple class. The private data members should contain the necessary variables to successfully run your plugin; this will likely include any histograms, canvases, fits or other accoutrement. The public section contains the required Constructor, Init, Process, and Finish functions. In init we get the application, as well as initialize any variables or histograms, etc. The Process function typically gets objects from the event and does something with them (e.g. fill the histogram of cluster energy). And finally Finish is called where we clean up and do final things before ending the run of our plugin.
0036
0037 Before we compile our plugins we need to tell JANA about where the plugins will be found. Start by setting your EICrecon_MY environment variable to a directory where you have write permission. The build instructions will install the plugin to that directory. When eicrecon is run, it will also look for plugins in the $EICrecon_MY directory and the EICrecon build you are using. This step is easy to overlook but necessary for the plugin to be found once compiled. Let's do this now before we forget:
0038
0039 ~~~
0040 mkdir EICrecon_MY
0041 export EICrecon_MY=${PWD}/EICrecon_MY
0042 ~~~
0043
0044 To compile your plugin, let's follow the guidance given and type:
0045 ~~~
0046 cmake -S myFirstPlugin -B myFirstPlugin/build
0047 cmake --build myFirstPlugin/build --target install
0048 ~~~
0049
0050 You can test plugin installed and can load correctly by running eicrecon with it:
0051 ~~~
0052 eicrecon -Pplugins=myFirstPlugin,JTest -Pjana:nevents=10
0053 ~~~
0054
0055 The second plugin, JTest, just supplies dummy events, ensuring your plugin is properly compiled and found. To generate your first histograms, let's edit the myFirstPluginProcessor.cc and myFirstPluginProcessor.h files (located in the myFirstPlugin directory). Start by modifying myFirstPluginProcessor.h. In the end it should look similar to the one below:
0056
0057 ```c++
0058 #include <JANA/JEventProcessorSequentialRoot.h>
0059 #include <TH2D.h>
0060 #include <TFile.h>
0061
0062 #include <edm4hep/SimCalorimeterHit.h>
0063
0064 class myFirstPluginProcessor: public JEventProcessorSequentialRoot {
0065 private:
0066
0067 // Declare histogram and tree pointers here. e.g.
0068 TH1D* hEraw = nullptr;
0069
0070 public:
0071 myFirstPluginProcessor() { SetTypeName(NAME_OF_THIS); }
0072
0073 void InitWithGlobalRootLock() override;
0074 void ProcessSequential(const std::shared_ptr<const JEvent>& event) override;
0075 void FinishWithGlobalRootLock() override;
0076 };
0077 ```
0078 Next, edit the myFirstPluginProcessor.cc file to the following:
0079 ```c++
0080 #include "myFirstPluginProcessor.h"
0081 #include <services/rootfile/RootFile_service.h>
0082
0083 // The following just makes this a JANA plugin
0084 extern "C" {
0085 void InitPlugin(JApplication *app) {
0086 InitJANAPlugin(app);
0087 app->Add(new myFirstPluginProcessor);
0088 }
0089 }
0090
0091 //-------------------------------------------
0092 // InitWithGlobalRootLock
0093 //-------------------------------------------
0094 void myFirstPluginProcessor::InitWithGlobalRootLock(){
0095
0096 // This ensures the histograms created here show up in the same root file as
0097 // other plugins attached to the process. Place them in dedicated directory
0098 // to avoid name conflicts.
0099 auto rootfile_svc = GetApplication()->GetService<RootFile_service>();
0100 auto rootfile = rootfile_svc->GetHistFile();
0101 rootfile->mkdir("myFirstPlugin")->cd();
0102
0103 hEraw = new TH1D("Eraw", "BEMC hit energy (raw)", 100, 0, 0.075);
0104 }
0105
0106 //-------------------------------------------
0107 // ProcessSequential
0108 //-------------------------------------------
0109 void myFirstPluginProcessor::ProcessSequential(const std::shared_ptr<const JEvent>& event) {
0110 const auto &rawhits = *static_cast<const edm4hep::SimCalorimeterHitCollection*>(event->GetCollectionBase("EcalBarrelScFiHits"));
0111 for (auto hit : rawhits) hEraw->Fill(hit.getEnergy());
0112 }
0113
0114 //-------------------------------------------
0115 // FinishWithGlobalRootLock
0116 //-------------------------------------------
0117 void myFirstPluginProcessor::FinishWithGlobalRootLock() {
0118
0119 // Do any final calculations here.
0120 }
0121 ```
0122 Before we continue, stop for a moment and remember that plugins are compiled objects. Thus it is imperative we rebuild our plugin after making any changes. To do this, we can simply run the same commands we used to build the plugin in the first place:
0123
0124 ~~~
0125 cmake -S myFirstPlugin -B myFirstPlugin/build
0126 cmake --build myFirstPlugin/build --target install
0127 ~~~
0128
0129 You can test the plugin using the following simulated data file:
0130
0131 ~~~bash
0132 wget https://eicaidata.s3.amazonaws.com/2022-09-26_ncdis10x100_minq2-1_200ev.edm4hep.root
0133 eicrecon -Pplugins=myFirstPlugin 2022-09-26_ncdis10x100_minq2-1_200ev.edm4hep.root
0134 ~~~
0135
0136 You should now have a root file, eicrecon.root, with a single directory: "myFirstPlugin" containing the resulting hEraw histogram.
0137
0138
0139 _____________________________________________________________________________________________________________
0140
0141 As exercises try (make sure you rebuild every time you change your plugin):
0142
0143 1) Plot the X,Y positions of all the hits.
0144
0145 2) Repeat only for hits with energy greater than 0.005 GeV.
0146
0147 3) Try to plot similar histograms from the EcalEndcapN.
0148
0149 Feel free to play around with other objects and their properties (hint: when you ran eicrecon, you should have seen a list of all the objects that were available to you. You can also see this list by typing: eicrecon -Pplugins=myFirstPlugin -Pjana:nevents=0)
0150
0151 Note: very shortly you will be adding a factory. After you do come back to this plugin and access your newly created objects
0152
0153
0154 {% include links.md %}