Back to home page

EIC code displayed by LXR

 
 

    


Warning, /EICrecon/docs/howto/make_plugin.md is written in an unsupported language. File is not indexed.

0001 # JANA plugins in EICrecon
0002 
0003 Here are instructions for creating your own user plugin that can create
0004 custom histograms/trees that will be added to the output ROOT histograms
0005 file. This covers just the most common use-case of making a plugin with
0006 a _JEventProcessor_.
0007 
0008 These instructions can be used to build a plugin that is kept outside of
0009 the `EICrecon` source tree, but that compiles against it. Thus, if you have
0010 access to a read-only `EICrecon` build, you can still use it to make a plugin
0011 that can install to a directory you do have write access to.
0012 
0013 ## EICrecon_MY
0014 The `EICrecon_MY` environment variable is useful for building plugins outside
0015 the `EICrecon` source tree. Set this to a directory where you have write
0016 permission. The build instructions below will install the plugin to that
0017 directory. When `eicrecon` is run, it will also look for plugins in the
0018 `$EICrecon_MY` directory (as well as the central `EICrecon` build you are using.)
0019 
0020 ~~~bash
0021 mkdir EICrecon_MY
0022 export EICrecon_MY=${PWD}/EICrecon_MY
0023 ~~~
0024 
0025 
0026 ## Creating a plugin with _eicmkplugin.py_
0027 EICrecon installs a script called _eicmkplugin.py_ that will generate all
0028 of the boilerplate code for a new plugin. This includes a directory, a
0029 _CMakeLists.txt_ file, and some skeleton code. The instructions below create
0030 a plugin called _DaveTest_ and then compile it. It will be installed in
0031 the directory pointed to by your `EICrecon_MY` environment variable (if set).
0032 
0033 ~~~bash
0034 eicmkplugin.py DaveTest
0035 cmake -S DaveTest -B DaveTest/build
0036 cmake --build DaveTest/build --target install
0037 ~~~
0038 
0039 You can test that the plugin installed and can load correctly by running
0040 `eicrecon` with it.
0041 
0042 ~~~bash
0043 eicrecon -Pplugins=DaveTest,JTest -Pjana:nevents=10
0044 ~~~
0045 
0046 <details>
0047     <summary>Click here to see full output of above command</summary>
0048 
0049 ~~~
0050      ____      _     ___      ___       _
0051      `MM'     dM.    `MM\     `M'      dM.
0052       MM     ,MMb     MMM\     M      ,MMb
0053       MM     d'YM.    M\MM\    M      d'YM.      ____
0054       MM    ,P `Mb    M \MM\   M     ,P `Mb     6MMMMb
0055       MM    d'  YM.   M  \MM\  M     d'  YM.   MM'  `Mb
0056       MM   ,P   `Mb   M   \MM\ M    ,P   `Mb        ,MM
0057       MM   d'    YM.  M    \MM\M    d'    YM.      ,MM'
0058 (8)   MM  ,MMMMMMMMb  M     \MMM   ,MMMMMMMMb    ,M'
0059 ((   ,M9  d'      YM. M      \MM   d'      YM. ,M'
0060  YMMMM9 _dM_     _dMM_M_      \M _dM_     _dMM_MMMMMMMM
0061 
0062 [INFO] Creating pipe named "/tmp/jana_status" for status info.
0063 [INFO] Setting signal handlers
0064 [INFO] JPluginLoader: Initializing plugin "/work/eic2/users/davidl/2022.08.29.eic-shell/EICwork/EICrecon_MY/plugins/DaveTest.so"
0065 [INFO] JPluginLoader: Initializing plugin "/usr/local/plugins/JTest.so"
0066 [INFO] JPluginLoader: Initializing plugin "/w/eic-scshelf2104/users/davidl/2022.08.29.eic-shell/EICwork/EICrecon/lib/EICrecon/plugins/podio.so"
0067 [INFO] JPluginLoader: Initializing plugin "/w/eic-scshelf2104/users/davidl/2022.08.29.eic-shell/EICwork/EICrecon/lib/EICrecon/plugins/dd4hep.so"
0068 [INFO] JPluginLoader: Initializing plugin "/w/eic-scshelf2104/users/davidl/2022.08.29.eic-shell/EICwork/EICrecon/lib/EICrecon/plugins/acts.so"
0069 [INFO] JPluginLoader: Initializing plugin "/w/eic-scshelf2104/users/davidl/2022.08.29.eic-shell/EICwork/EICrecon/lib/EICrecon/plugins/log.so"
0070 [INFO] JPluginLoader: Initializing plugin "/w/eic-scshelf2104/users/davidl/2022.08.29.eic-shell/EICwork/EICrecon/lib/EICrecon/plugins/rootfile.so"
0071 [INFO] JPluginLoader: Initializing plugin "/w/eic-scshelf2104/users/davidl/2022.08.29.eic-shell/EICwork/EICrecon/lib/EICrecon/plugins/BEMC.so"
0072 [INFO] JPluginLoader: Initializing plugin "/w/eic-scshelf2104/users/davidl/2022.08.29.eic-shell/EICwork/EICrecon/lib/EICrecon/plugins/EEMC.so"
0073 [INFO] JArrowProcessingController: NUMA Configuration
0074 
0075   Affinity strategy: compute-bound (favor fewer hyperthreads)
0076   Locality strategy: global
0077   Location count: 1
0078   +--------+----------+-------+--------+-----------+--------+
0079   | worker | location |  cpu  |  core  | numa node | socket |
0080   +--------+----------+-------+--------+-----------+--------+
0081   |      0 |        0 |     0 |      0 |         0 |      0 |
0082   |      1 |        0 |     1 |      1 |         0 |      0 |
0083   |      2 |        0 |     2 |      2 |         0 |      0 |
0084   |      3 |        0 |     3 |      3 |         1 |      0 |
0085   |      4 |        0 |     4 |      4 |         1 |      0 |
0086   |      5 |        0 |     5 |      5 |         0 |      0 |
0087   |      6 |        0 |     6 |      6 |         0 |      0 |
0088   |      7 |        0 |     7 |      7 |         1 |      0 |
0089   |      8 |        0 |     8 |      8 |         1 |      0 |
0090   |      9 |        0 |     9 |      9 |         1 |      0 |
0091   |     10 |        0 |    10 |     10 |         0 |      0 |
0092   |     11 |        0 |    11 |     11 |         0 |      0 |
0093   |     12 |        0 |    12 |     12 |         0 |      0 |
0094   |     13 |        0 |    13 |     13 |         1 |      0 |
0095   |     14 |        0 |    14 |     14 |         1 |      0 |
0096   |     15 |        0 |    15 |     15 |         0 |      0 |
0097   |     16 |        0 |    16 |     16 |         0 |      0 |
0098   |     17 |        0 |    17 |     17 |         1 |      0 |
0099   |     18 |        0 |    18 |     18 |         1 |      0 |
0100   |     19 |        0 |    19 |     19 |         1 |      0 |
0101   |     20 |        0 |    20 |     20 |         2 |      1 |
0102   |     21 |        0 |    21 |     21 |         2 |      1 |
0103   |     22 |        0 |    22 |     22 |         2 |      1 |
0104   |     23 |        0 |    23 |     23 |         3 |      1 |
0105   |     24 |        0 |    24 |     24 |         3 |      1 |
0106   |     25 |        0 |    25 |     25 |         2 |      1 |
0107   |     26 |        0 |    26 |     26 |         2 |      1 |
0108   |     27 |        0 |    27 |     27 |         3 |      1 |
0109   |     28 |        0 |    28 |     28 |         3 |      1 |
0110   |     29 |        0 |    29 |     29 |         3 |      1 |
0111   |     30 |        0 |    30 |     30 |         2 |      1 |
0112   |     31 |        0 |    31 |     31 |         2 |      1 |
0113   |     32 |        0 |    32 |     32 |         2 |      1 |
0114   |     33 |        0 |    33 |     33 |         3 |      1 |
0115   |     34 |        0 |    34 |     34 |         3 |      1 |
0116   |     35 |        0 |    35 |     35 |         2 |      1 |
0117   |     36 |        0 |    36 |     36 |         2 |      1 |
0118   |     37 |        0 |    37 |     37 |         3 |      1 |
0119   |     38 |        0 |    38 |     38 |         3 |      1 |
0120   |     39 |        0 |    39 |     39 |         3 |      1 |
0121   |     40 |        0 |    40 |      0 |         0 |      0 |
0122   |     41 |        0 |    41 |      1 |         0 |      0 |
0123   |     42 |        0 |    42 |      2 |         0 |      0 |
0124   |     43 |        0 |    43 |      3 |         1 |      0 |
0125   |     44 |        0 |    44 |      4 |         1 |      0 |
0126   |     45 |        0 |    45 |      5 |         0 |      0 |
0127   |     46 |        0 |    46 |      6 |         0 |      0 |
0128   |     47 |        0 |    47 |      7 |         1 |      0 |
0129   |     48 |        0 |    48 |      8 |         1 |      0 |
0130   |     49 |        0 |    49 |      9 |         1 |      0 |
0131   |     50 |        0 |    50 |     10 |         0 |      0 |
0132   |     51 |        0 |    51 |     11 |         0 |      0 |
0133   |     52 |        0 |    52 |     12 |         0 |      0 |
0134   |     53 |        0 |    53 |     13 |         1 |      0 |
0135   |     54 |        0 |    54 |     14 |         1 |      0 |
0136   |     55 |        0 |    55 |     15 |         0 |      0 |
0137   |     56 |        0 |    56 |     16 |         0 |      0 |
0138   |     57 |        0 |    57 |     17 |         1 |      0 |
0139   |     58 |        0 |    58 |     18 |         1 |      0 |
0140   |     59 |        0 |    59 |     19 |         1 |      0 |
0141   |     60 |        0 |    60 |     20 |         2 |      1 |
0142   |     61 |        0 |    61 |     21 |         2 |      1 |
0143   |     62 |        0 |    62 |     22 |         2 |      1 |
0144   |     63 |        0 |    63 |     23 |         3 |      1 |
0145   |     64 |        0 |    64 |     24 |         3 |      1 |
0146   |     65 |        0 |    65 |     25 |         2 |      1 |
0147   |     66 |        0 |    66 |     26 |         2 |      1 |
0148   |     67 |        0 |    67 |     27 |         3 |      1 |
0149   |     68 |        0 |    68 |     28 |         3 |      1 |
0150   |     69 |        0 |    69 |     29 |         3 |      1 |
0151   |     70 |        0 |    70 |     30 |         2 |      1 |
0152   |     71 |        0 |    71 |     31 |         2 |      1 |
0153   |     72 |        0 |    72 |     32 |         2 |      1 |
0154   |     73 |        0 |    73 |     33 |         3 |      1 |
0155   |     74 |        0 |    74 |     34 |         3 |      1 |
0156   |     75 |        0 |    75 |     35 |         2 |      1 |
0157   |     76 |        0 |    76 |     36 |         2 |      1 |
0158   |     77 |        0 |    77 |     37 |         3 |      1 |
0159   |     78 |        0 |    78 |     38 |         3 |      1 |
0160   |     79 |        0 |    79 |     39 |         3 |      1 |
0161   +--------+----------+-------+--------+-----------+--------+
0162 
0163 [INFO] Configuration Parameters
0164   ----------------------------
0165       Name          Value
0166   ------------  --------------
0167   csv:dest_dir  .
0168   jana:nevents  10
0169        plugins  DaveTest,JTest
0170   ----------------------------
0171 
0172 [INFO] Component Summary
0173 
0174   SOURCES
0175   -----------------------------------
0176    Plugin      Name         Source
0177   --------  -----------  ------------
0178   JTest.so  JTestParser  dummy_source
0179   -----------------------------------
0180   PROCESSORS
0181   ---------------------------------------
0182     Plugin                Name
0183   -----------  --------------------------
0184   DaveTest.so  DaveTestProcessor
0185   JTest.so     JTestPlotter
0186   JTest.so     JCsvWriter<JTestTrackData>
0187   ---------------------------------------
0188   FACTORIES
0189   --------------------------------------------------------------------
0190    Plugin          Object name                       Tag
0191   --------  --------------------------  ------------------------------
0192   JTest.so  JTestEventData
0193   JTest.so  JTestTrackData
0194   EEMC.so   edm4eic::ProtoCluster       EcalEndcapNIslandProtoClusters
0195   EEMC.so   edm4eic::ProtoCluster       EcalEndcapNTruthProtoClusters
0196   EEMC.so   edm4eic::CalorimeterHit     EcalEndcapNRecHits
0197   EEMC.so   edm4eic::Cluster            EcalEndcapNClusters
0198   EEMC.so   edm4eic::Cluster            EcalEndcapNMergedClusters
0199   BEMC.so   edm4hep::RawCalorimeterHit  EcalBarrelNRawHits
0200   EEMC.so   edm4hep::RawCalorimeterHit  EcalEndcapNRawHits
0201   --------------------------------------------------------------------
0202 
0203 [INFO] Starting processing with 1 threads requested...
0204 [INFO] JArrowProcessingController: run(): Launching 1 workers
0205 [INFO] JArrow: Initializing JEventProcessor 'DaveTestProcessor'
0206 [INFO] JArrow: Initializing JEventProcessor 'JTestPlotter'
0207 [INFO] JArrow: Initializing JEventProcessor 'JCsvWriter<JTestTrackData>'
0208 [INFO] JArrow: Initializing JEventSource 'dummy_source' (JTestParser)
0209 [INFO] Status: 5 events processed  10.0 Hz (10.0 Hz avg)
0210 [INFO] JArrow: Finalizing JEventSource 'dummy_source' (JTestParser)
0211 [INFO] Status: 10 events processed  13.2 Hz (11.4 Hz avg)
0212 [INFO] All workers have stopped.
0213 [INFO] Merging threads ...
0214 [INFO] JArrow: Finalizing JEventProcessor 'DaveTestProcessor'
0215 [INFO] JArrow: Finalizing JEventProcessor 'JTestPlotter'
0216 [INFO] JArrow: Finalizing JEventProcessor 'JCsvWriter<JTestTrackData>'
0217 [INFO] Event processing ended.
0218 [INFO] JArrowProcessingController: Final Report
0219   Thread team size [count]:    1
0220   Total uptime [s]:            0.8802
0221   Uptime delta [s]:            0.3781
0222   Completed events [count]:    10
0223   Inst throughput [Hz]:        13.2
0224   Avg throughput [Hz]:         11.4
0225   Sequential bottleneck [Hz]:  212
0226   Parallel bottleneck [Hz]:    12.1
0227   Efficiency [0..1]:           0.94
0228 
0229   +--------------------------+------------+--------+-----+---------+-------+--------+---------+-------------+
0230   |           Name           |   Status   |  Type  | Par | Threads | Chunk | Thresh | Pending |  Completed  |
0231   +--------------------------+------------+--------+-----+---------+-------+--------+---------+-------------+
0232   | dummy_source             | Finished   | Source |  F  |       0 |    40 |      - |       - |          10 |
0233   | processors               | Finished   | Sink   |  T  |       0 |     1 |     80 |       0 |          10 |
0234   +--------------------------+------------+--------+-----+---------+-------+--------+---------+-------------+
0235   +--------------------------+-------------+--------------+----------------+--------------+----------------+
0236   |           Name           | Avg latency | Inst latency | Queue latency  | Queue visits | Queue overhead |
0237   |                          | [ms/event]  |  [ms/event]  |   [ms/visit]   |    [count]   |     [0..1]     |
0238   +--------------------------+-------------+--------------+----------------+--------------+----------------+
0239   | dummy_source             |        4.73 |         3.16 |       0.000174 |           11 |       4.05e-05 |
0240   | processors               |        82.8 |         88.4 |       0.000324 |           50 |       1.96e-05 |
0241   +--------------------------+-------------+--------------+----------------+--------------+----------------+
0242   +----+----------------------+-------------+------------+-----------+----------------+------------------+
0243   | ID | Last arrow name      | Useful time | Retry time | Idle time | Scheduler time | Scheduler visits |
0244   |    |                      |     [ms]    |    [ms]    |    [ms]   |      [ms]      |     [count]      |
0245   +----+----------------------+-------------+------------+-----------+----------------+------------------+
0246   |  0 | idle                 |      0.0357 |          0 |         0 |       0.000538 |               21 |
0247   +----+----------------------+-------------+------------+-----------+----------------+------------------+
0248 
0249 ~~~
0250 </details>
0251 
0252 Note that in the above command, a second plugin _JTest_ which supplies dummy events and
0253 the _jana_nevents_ configuration parameter is set to only process 10 events.
0254 
0255 For the plugin to be useful, you will need to edit the files in the `DaveTest`
0256 directory. There are two files: _DaveTestProcessor.cc_ and a _DaveTestProcessor.h_.
0257 Start with the _DaveTestProcessor.h_ file. Edit your file to look similar to the one
0258 below. You will need to add include lines for each data type you are interested
0259 in (see ```#include <edm4hep/Cluster.h>```), a Prefetch line for each collection
0260 type, and then pointer for every histogram or tree you wish to create.
0261 
0262 ```cpp
0263 #include <JANA/JEventProcessorSequentialRoot.h>
0264 #include <TH2D.h>
0265 #include <TFile.h>
0266 
0267 #include <edm4hep/Cluster.h>
0268 
0269 class DaveTestProcessor: public JEventProcessorSequentialRoot {
0270 private:
0271 
0272     // Declare histogram and tree pointers here. e.g.
0273     TH1D* hClusterEnergy = nullptr;
0274 
0275 public:
0276     DaveTestProcessor() { SetTypeName(NAME_OF_THIS); }
0277 
0278     void InitWithGlobalRootLock() override;
0279     void ProcessSequential(const std::shared_ptr<const JEvent>& event) override;
0280     void FinishWithGlobalRootLock() override;
0281 };
0282 ```
0283 Next, edit the _DaveTest.cc_ file to look similar to what is below. The key things
0284 you will need to add are the lines in the `InitWithGlobalRootLock` and
0285 `ProcessSequential` methods. See the comments in the`InitWithGlobalRootLock`
0286 method for an explanation of those.
0287 
0288 The one line in the `ProcessSequential` method will loop over the values
0289 in the `clusters` member. As a `Prefetch` object, _JANA_ will automatically
0290 call all algorithms needed to produce the `Cluster` objects prior to calling
0291 `ProcessSequential`. This works for objects created by algorithms or ones
0292 coming straight from the file.
0293 
0294 ```cpp
0295 #include "DaveTestProcessor.h"
0296 #include <services/rootfile/RootFile_service.h>
0297 
0298 // The following just makes this a JANA plugin
0299 extern "C" {
0300     void InitPlugin(JApplication *m_app) {
0301         InitJANAPlugin(m_app);
0302         m_app->Add(new DaveTestProcessor);
0303     }
0304 }
0305 
0306 //-------------------------------------------
0307 // InitWithGlobalRootLock
0308 //-------------------------------------------
0309 void DaveTestProcessor::InitWithGlobalRootLock(){
0310 
0311     // This ensures the histograms created here show up in the same root file as
0312     // other plugins attached to the process. Place them in dedicated directory
0313     // to avoid name conflicts.
0314     auto rootfile_svc = GetApplication()->GetService<RootFile_service>();
0315     auto rootfile = rootfile_svc->GetHistFile();
0316     rootfile->mkdir("DaveTest")->cd();
0317 
0318     hClusterEnergy  = new TH1D("hClusterEnergy",  "EcalEndcapNClusters energy (GeV)",  200, 0, 0.075);
0319 }
0320 
0321 //-------------------------------------------
0322 // ProcessSequential
0323 //-------------------------------------------
0324 void DaveTestProcessor::ProcessSequential(const std::shared_ptr<const JEvent>& event) {
0325     const auto &clusters = *static_cast<const edm4eic::ClusterCollection*>(event->GetCollectionBase("EcalEndcapNClusters"));
0326 
0327     for (auto cluster : clusters) hClusterEnergy->Fill(cluster.getEnergy());
0328 }
0329 
0330 //-------------------------------------------
0331 // FinishWithGlobalRootLock
0332 //-------------------------------------------
0333 void DaveTestProcessor::FinishWithGlobalRootLock() {
0334 
0335     // Do any final calculations here.
0336 }
0337 ```
0338 
0339 You can now test this using you favorite simulated data file or with the one in the
0340 following commands:
0341 
0342 ~~~bash
0343 wget https://eicaidata.s3.amazonaws.com/2022-09-04_pgun_e-_podio-0.15_edm4hep-0.6_0-30GeV_alldir_1k.edm4hep.root
0344 eicrecon -Pplugins=DaveTest 2022-09-04_pgun_e-_podio-0.15_edm4hep-0.6_0-30GeV_alldir_1k.edm4hep.root
0345 ~~~
0346 
0347 This should run through the events filling you histogram resulting in the file
0348 `eicrecon.root`. The histogram should look something like this:
0349 
0350 ![edm4eic::CalorimeterHit EcalEndcapNRecHits energy](hRecHitEnergy.png)
0351 
0352 
0353 
0354 ## Manually creating a plugin
0355 For people who really love to get their fingers dirty and feel the above
0356 instructions are just too easy, here are some more detailed instructions
0357 for creating a plugin from scratch without `eicmkplugin.py`.
0358 
0359 There is a copy/paste CMake file that should automatically create plugin out of sources.
0360 
0361 - plugin name is taken from a directory name
0362 - there should be /</plugin name/>/.cc file with `void InitPlugin(JApplication *m_app)` function
0363 
0364 
0365 ### Create a plugin:
0366 
0367 E.g. if you want to create a plugin named `my_plugin`
0368 
0369 - Create a directory `my_plugin`
0370 - Create a file `my_plugin.cc` which will have `InitPlugin` function
0371 - Create `CMakeLists.txt` with the content below
0372 - Add all others files (cmake GLOB is used)
0373 
0374 ### Recommended cmake:
0375 
0376 Recommended CMake for a plugin:
0377 
0378 ```cmake
0379 cmake_minimum_required(VERSION 3.16)
0380 
0381 # Automatically set plugin name the same as the directory name
0382 # Don't forget string(REPLACE " " "_" PLUGIN_NAME ${PLUGIN_NAME}) if this dir has spaces in its name
0383 get_filename_component(PLUGIN_NAME ${CMAKE_CURRENT_LIST_DIR} NAME)
0384 
0385 # Function creates ${PLUGIN_NAME}_plugin and ${PLUGIN_NAME}_library targets
0386 # Setting default includes, libraries and installation paths
0387 plugin_add(${PLUGIN_NAME})
0388 
0389 # Find dependencies
0390 find_package(JANA REQUIRED)
0391 find_package(EDM4HEP REQUIRED)
0392 find_package(podio REQUIRED)
0393 find_package(DD4hep REQUIRED)
0394 find_package(ROOT REQUIRED COMPONENTS Core Tree Hist RIO EG)
0395 
0396 # The macro grabs sources as *.cc *.cpp *.c and headers as *.h *.hh *.hpp
0397 # Then correctly sets sources for ${_name}_plugin and ${_name}_library targets
0398 # Adds headers to the correct installation directory
0399 plugin_glob_all(${PLUGIN_NAME})
0400 
0401 # Add include directories
0402 # (same as target_include_directories but for both plugin and library)
0403 plugin_include_directories(${PLUGIN_NAME} SYSTEM PUBLIC ${JANA_INCLUDE_DIR} ${podio_INCLUDE_DIR} ${EDM4HEP_INCLUDE_DIR} ${DD4hep_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS})
0404 
0405 # Add libraries
0406 # (same as target_include_directories but for both plugin and library)
0407 plugin_link_libraries(${PLUGIN_NAME} ${JANA_LIB})
0408 ```
0409 
0410 ### CMake macros:
0411 
0412 There are `plugin_...` macros that are slim wrappers trying to minimize an amount of boilerplate
0413 code of each plugin cmake scripts. Macros mimic CMake functions like `target_link_libraries` => `plugin_link_libraries`.