Page MenuHomeHEPForge

No OneTemporary

diff --git a/doc/sphinx/analyses.rst b/doc/sphinx/analyses.rst
index eab8ef0..d3e676e 100644
--- a/doc/sphinx/analyses.rst
+++ b/doc/sphinx/analyses.rst
@@ -1,166 +1,156 @@
.. _`Writing custom analyses`:
Writing custom analyses
=======================
-Both reversed HEJ and HEJ FOG can generate HepMC files, so you can
-always run a rivet analysis on these.
-
-If you want to write your own native analysis, the easiest way is to
-create a new .cc file, for example my_analysis.cc in the
-analysis-plugins/src folder.
+Reversed HEJ and the HEJ fixed-order generator can generate HepMC files,
+so you can always run a :ref:`rivet <https://rivet.hepforge.org/>` analysis
+on these. Alternatively, you can provide a custom analysis inside a C++
+library.
An analysis is a class that derives from the abstract :code:`Analysis`
base class provided by reversed HEJ. It has to implement two public
functions:
* The :code:`pass_cuts` member function return true if and only if the
given event (first argument) passes the analysis cuts
* The :code:`fill` member function adds an event to the analysis, which
- for example can be used to fill histograms. Reversed HEJ and HEJ FOG
- will only give you events for which :code:`pass_cuts` has returned
- true.
+ for example can be used to fill histograms. Reversed HEJ will only
+ pass events for which :code:`pass_cuts` has returned true.
Both functions take two arguments: the resummation event generated by
reversed HEJ and the original fixed-order input event. Usually, the
second argument can be ignored. It can be used, for example, for
implementing cuts that depend on the ratio of the weights between the
fixed-order and the resummation event.
In addition to the two member functions, there has to be a global
make_analysis function that takes the analysis parameters in the form of
a YAML :code:`Node` and returns a :code:`std::unique_ptr` to the
Analysis.
The following code creates the simplest conceivable analysis.::
#include <memory> // for std::unique_ptr
#include "RHEJ/Analysis.hh"
class MyAnalysis: public RHEJ::Analysis {
public:
MyAnalysis(YAML::Node const & /* config */) {}
void fill(
RHEJ::Event const & /* event */,
RHEJ::Event const & /* FO_event */
) override{
};
bool pass_cuts(
RHEJ::Event const & /* event */,
RHEJ::Event const & /* FO_event */
) override{
return true;
};
};
extern "C"
- __attribute__((visibility("default")))
std::unique_ptr<RHEJ::Analysis> make_analysis(
YAML::Node const & config
){
return std::make_unique<MyAnalysis>(config);
}
-Reversed HEJ and HEJ FOG load analyses dynamically at run time. Since
-the loader cannot deal with the name mangling which is usually done by
-compilers, we have to specify :code:`extern "C"`.
-
-The standard compiler settings for analyses ensure that symbols (for
-example your class name) are not visible in the compiled analysis. This
-ensures that there can be no name clashes with the remaining
-code. However, since reversed HEJ and HEJ FOG have to be able to call
-:code:`make_analysis`, we use
-:code:`__attribute__((visibility("default")))` to ensure its visibility.
+You can save this code to a file, for example :code:`myanalysis.cc`, and
+compile it into a shared library. Using the :code:`g++` compiler, the
+library can be built with
-To build the analysis go to some build directory and run
+.. code-block:: sh
-.. code-block:: Bash
+ g++ -fPIC -shared -Wl,-soname,libmyanalysis.so -o libmyanalysis.so myanalysis.cc
- cmake some/directory/analysis-plugins
- make my_analysis
+With :code:`g++` it is also good practice to add
+:code:`__attribute__((visibility("default")))` after :code:`extern "C"`
+in the above code snippet and then compile with the additional flag
+:code:`-fvisibility=hidden` to prevent name clashes.
-This will create the analysis library libmy_analysis.so in the src
-subdirectory. You can then use it in reversed HEJ or HEJ FOG by adding
+You can use the analysis in reversed HEJ or the HEJ fixed-order
+generator by adding
.. code-block:: YAML
analysis:
- plugin: analysis/build/directory/src/libmy_analysis.so
+ plugin: /path/to/libmyanalysis.so
to the .yml configuration file.
As a more interesting example, here is the code for an analysis that
sums up the total cross section and prints the result to both standard
output and a file specified in the .yml config with
.. code-block:: YAML
analysis:
plugin: analysis/build/directory/src/libmy_analysis.so
output: outfile
To access the configuration at run time, reversed HEJ uses the yaml-cpp
library; for more details see the `yaml-cpp tutorial
<https://github.com/jbeder/yaml-cpp/wiki/Tutorial>`_. The analysis code
itself is::
#include <memory>
#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
#include "RHEJ/Analysis.hh"
#include "RHEJ/Event.hh"
#include "yaml-cpp/yaml.h"
class MyAnalysis: public RHEJ::Analysis {
public:
MyAnalysis(YAML::Node const & config):
xsection_{0.}, xsection_error_{0.},
outfile_{config["output"].as<std::string>()}
{}
void fill(
RHEJ::Event const & event,
RHEJ::Event const & /* FO_event */
) override{
const double wt = event.central().weight;
xsection_ += wt;
xsection_error_ += wt*wt;
};
bool pass_cuts(
RHEJ::Event const & /* event */,
RHEJ::Event const & /* FO_event */
) override{
return true;
};
~MyAnalysis(){
std::cout << "cross section: " << xsection_ << " +- "
<< std::sqrt(xsection_error_) << "\n";
std::ofstream fout{outfile_};
fout << "cross section: " << xsection_ << " +- "
<< std::sqrt(xsection_error_) << "\n";
}
private:
double xsection_, xsection_error_;
std::string outfile_;
};
extern "C"
- __attribute__((visibility("default")))
std::unique_ptr<RHEJ::Analysis> make_analysis(
YAML::Node const & config
){
return std::make_unique<MyAnalysis>(config);
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Nov 19, 7:00 PM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3805724
Default Alt Text
(6 KB)

Event Timeline