Coder Social home page Coder Social logo

heavyionanalysis / analysistree Goto Github PK

View Code? Open in Web Editor NEW
4.0 4.0 8.0 21.61 MB

AnalysisTree data format

Home Page: https://heavyionanalysis.github.io/AnalysisTree/

License: GNU General Public License v3.0

CMake 6.65% Dockerfile 0.26% C++ 92.10% C 0.92% Shell 0.06%
heavy-ion-collisions data-format analysistree

analysistree's Introduction

AnalysisTree

Workflow status GitHub tag (latest SemVer) GitHub release (latest SemVer)

Important note on AnalysisTree versions

Current version is development version!

Last tested version: v2.3.2

Last release version: v.2.3.2

Different MAJOR version means incompatible API changes. Neither API nor data compatibility is preserved between MAJOR versions.

Since v2.2.1 old infra implementation is kept for the sake of code compatibility until the next MAJOR infra release.

Doxygen documentation:

https://heavyionanalysis.github.io/AnalysisTree/

General information

This is a dataformat to store information in configurable objects. Basic objects are:

  • Track (momentum)
  • Particle (momentum and PID)
  • Hit (position and signal)
  • Module (id and signal)
    Four mentioned objects are so-called channelized: they contain set of channels (namely tracks, prticles, hits or modules) in each event
  • EventHeader (vertex position) - contains information related to specific event
  • DataHeader - contains common information for all events
  • Matching - establishes a correspondence between channels in channelized objects (e.g. between simulated particle and reconstructed track).

Additionaly to mandatory information specified in round brackets (a.k.a. "default fileds"), each object can contain any number of integer, floating or boolean fields (a.k.a. "user-defined fields"). Information about all fields in all branches is stored in Configuration object.

Installation

ROOT6 is needed for installation. Follow CERN ROOT instructions to install it. Version compiled with c++17 flag is preferred, otherwise CMAKE_CXX_STANDARD flag needs to be explicitly specified (see below).

git clone https://github.com/HeavyIonAnalysis/AnalysisTree.git
cd AnalysisTree
mkdir build install
cd build
source path-to-root-installation/bin/thisroot.sh
cmake -DCMAKE_INSTALL_PREFIX=../install ../
make -j install

path-to-root-installation must be replaced with your actual location of Root install directory.

List of CMake options:

To apply the flag use -D{Name}={value}, for example, if you want to compile using c++11:

cmake -DCMAKE_CXX_STANDARD=11 ../
Name Default value Possible values
CMAKE_BUILD_TYPE RELEASE RELEASE/DEBUG
CMAKE_CXX_STANDARD 17 11/14/17
AnalysisTree_BUILD_TESTS OFF ON/OFF
AnalysisTree_BUILD_EXAMPLES OFF ON/OFF
AnalysisTree_BUILD_INFRA_1 OFF ON/OFF

Operating with AnalysisTree

Setting AnalysisTree environment

Whatever you are going to do with AnalysisTree - read the file, perform analysis based on information stored in it or create your own file, first of all you need to set up environment variables. It can be done in a single command:

source path-to-analysis_tree-installation/bin/AnalysisTreeConfig.sh

Reading files from ROOT session

An example of AnalysisTree ROOT file can be downloaded by this link

Open a ROOT-file

root -l 1.analysistree.root

Check its content

.ls

You will obtain something like this:

TFile**		1.analysistree.root
 TFile*		1.analysistree.root
  KEY: TTree	rTree;1	AnalysisTree
  KEY: AnalysisTree::Configuration	Configuration;1
  KEY: AnalysisTree::DataHeader	DataHeader;1

So, file contains ROOT::TTree object named rTree, AnalysisTree::Configuration object named Configuration describing the structure and hierarchy of the tree and thus needed for proper reading the tree and, finally, AnalysisTree::DataHeader object named DataHeader containing information common for all events.

Reading the configuration

In order to know the structure of the tree, perform following command:

Configuration->Print()

An output will contain plenty of branches and matchings between them. Let us look at one of them:

There are listed integer, floating and boolean fields of this branch (boolean are empty in this particular case). In the left column there is a unique id of the field. Pay attention that the numeration of fields is separate for integers, floats and bools. Negative ids belong to default fields of branches while positive ids and 0 - to user-defined fields. Middle column contains string name of the field, and right column - a description of it.

Digesting the tree content

Configuration->GetBranchConfig("SimParticles").GetType()
// to know to which type (Hit, Track, Module, Particle or EventHeader belongs SimParticles branch)

rTree->Draw("SimParticles.channels_.GetPx()")
// draw distribution of the value contained in the default field (has its own getter, namely
// GetPx(), names of getters can be found in doxygen documentation)

rTree->Draw("SimParticles.channels_.GetField<int>(2)")
// draw distribution of the value contained in the user-defined field (specify int, float or bool
// in angular brackets and field's id as an argument in round brackets)

// Note that access to default fields is also possible via id, not only via getters:
rTree->Draw("SimParticles.channels_.GetField<float>(-7)")

// If the branch contains non-channelized objects, but is an EventHeader, the word "channels_"
// is not needed in the command:
rTree->Draw("SimEventHeader.GetVertexY()")
rTree->Draw("RecEventHeader.GetField<int>(0)")

// The Draw() method allows usage of ROOT::TTree-specific drawing features such as:

rTree->Draw("SimParticles.channels_.GetPx() : SimParticles.channels_.GetPy()")
// drawing a 2D histogram, but only for fields from the same branch.

rTree->Draw("SimParticles.channels_.GetPx()", "SimParticles.channels_.GetPid()==211")
// drawing with some additional condition (px for positive pions only)

rTree->Draw("SimParticles.channels_.GetPx()", "", "same")
// drawing with user-specified draw options

rTree->Draw("SimParticles.channels_.GetPx()>>hist(1000,-10,10)")
// drawing a histogram with user-defined binning and ranges.

rTree->Draw("TMath::Log(TMath::Abs(SimParticles.channels_.GetPx()))")
// drawing a distribution of derived quantites calculated by formula

Moreover, for default fields which are explicitly present in Container (i.e. px is OK, but not pt, which is not stored but calculated on fly) there is a possibility to draw them using TTree::Draw syntax:

rTree->Draw("SimParticles.px_")
rTree->Draw("TMath::Log(TMath::Abs(SimParticles.px_))")
rTree->Draw("TMath::Log(TMath::Abs(SimParticles.px_)) * TMath::Cos(SimParticles.py_)")

Also you can open a ROOT interactive session and create an AnalysisTree::Chain:

AnalysisTree::Chain t("1.analysistree.root", "rTree") // Chain constructor with a single file
// or
AnalysisTree::Chain t({"filelist.txt"}, {"rTree"})  // Chain constructor with a file list

and then build any fields including user-defined and implicitly present fields (such as phi or pt):

t.Draw("SimParticles.px")
t.Draw("SimParticles.pid")
t.Draw("VtxTracks.chi2")
// 2D histograms, cuts, drawing options and math formulas mentioned above are also available

Reading file with a macro

Building of distributions in interactive mode is a good approach only if the commands are simple, and the number of events to be analized is not so big. However it is not common to do it interactively if formulae you want to use are complicated, and you can easely introduce a typo. Or if your logic includes a matching between branches - then interactive building distributions is totally impossible. For this case a good solution is usage of macros. A comprehensive example of reading the AnalysisTree ROOT file is shown in examples/ReadingMacro.C.

Creating your own AnalysisTree file

A comprehensive example of creating the AnalysisTree ROOT file is shown in examples/WritingMacro.C.

Reading and writing with executable

Usage of compiled code instead of macros has some advantachges, in first turn computation speed, and also syntax check in compile time. Macros can be re-qritten into executables. For this purpose one needs:

1. Put necessary headers with #include command
2. Create an int main() function - an entry point of any C++ program
3. Add an executable into CMakeLists

An example how to do it is shown with examples/UserTaskRead.cpp and examples/UserTaskWrite.cpp.

Note: these examples use a little bit different syntax from one shown in examples above. It is a so-called syntax sugar - attempt to make syntax more user-friendly. However it has its own price in terms of performance - it is slower by factor of few units than one shown above.

QA of files

For a QA of the file(s) please use the dedicated package AnalysisTreeQA:
https://github.com/HeavyIonAnalysis/AnalysisTreeQA

Known problems (features)

  • BranchConfig::GetFieldId() is slow -> should not be used for every event/track/hit/module
  • In some systems (e.g. at MacOS) there is a linking problem when using AnalysisTree::Infra objects in interactive mode or in macros. However it is easely fixable by silent call an AnalysisTree::Base object, e.g. AnalysisTree::Hit() - without doing nothing with it, just call.

analysistree's People

Contributors

eugene274 avatar fjlinz avatar fuhlig1 avatar kreisl avatar lubynets avatar viktorklochkov avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

analysistree's Issues

Data Type uint

In the code the data type uint is used a several places. I assume that an unsigned int is meant here. This type uint must be a typedef which somehow is implicitly included by one of the header files.

Please check also

HeavyIonAnalysis/AnalysisTreeQA#10

BranchView development

  • [#21 ] Deep copy for AnalysisTreeBranch
    IMPORTANT: AnalysisTreeBranch::Clone make SHALLOW copy => Same TTree for all derivatives of this object
    Now each instance of BranchView reads TTree independently
  • [#20 ] RenameFields - renames fields of the BranchView according to specified conversion map
    AddPrefix - Done
    AddSuffix I think, AddPrefix would be well enough to cover all our needs. AddSuffix could be implemented at any moment.
  • PlainMerge - horizontal channel-by-channel Merge
  • [#22 ] CombiningMerge - horizontal merge, but channels of two views are combined (each is paired with each). This operation is equal to join operation
  • Concat - concatenates channels of two views of the same structure (same set of fields)
  • BranchView::ToDataFrame()
  • Snapshot - save branch view (to PlainTree)
  • Convenient way of reading matched entities
  • Dedicated object for BranchViewPtr

Improvement of FillTask and TaskManager

Requirements:

  • pass data object (together with configuration) from task to task and let user to modify it
  • let user interfere into task flow (reject event, etc), keep per-task statistics on rejected events

Fix AnalysisTree::Detector<T>

AnalysisTree::Detector<T> owns pointer to the vector.
Default copy-constructor (assignment op-r) makes both Detector-s invalid, because they keep one shared instance of std::vector.

Exception specification causes error during compilation

Hi,

I've got some compilation errors when I try to install the new version of AnalysisTree (specifically, the core part). Tried with gcc ver. 4.8.5 and 7.5.0 - both produce the same error.

The error log:

AnalysisTree/core/BranchConfig.hpp:21:17: error: exception specification of explicitly defaulted move assignment operator does not match the calculated one
VectorConfig& operator=(VectorConfig&&) noexcept = default;
^
AnalysisTree/core/BranchConfig.hpp:51:29: note: in instantiation of template class 'AnalysisTree::VectorConfig' requested here
class BranchConfig : public VectorConfig, public VectorConfig, public VectorConfig {
^
AnalysisTree/core/BranchConfig.hpp:21:17: error: exception specification of explicitly defaulted move assignment operator does not match the calculated one
VectorConfig& operator=(VectorConfig&&) noexcept = default;
^
AnalysisTree/core/BranchConfig.hpp:51:55: note: in instantiation of template class 'AnalysisTree::VectorConfig' requested here
class BranchConfig : public VectorConfig, public VectorConfig, public VectorConfig {
^
AnalysisTree/core/BranchConfig.hpp:21:17: error: exception specification of explicitly defaulted move assignment operator does not match the calculated one
VectorConfig& operator=(VectorConfig&&) noexcept = default;
^
AnalysisTree/core/BranchConfig.hpp:51:83: note: in instantiation of template class 'AnalysisTree::VectorConfig' requested here
class BranchConfig : public VectorConfig, public VectorConfig, public VectorConfig {

If no exception specification is set (like it was in the previous commits: VectorConfig(VectorConfig &&) = default;), compilation is successful.

Add theta and eta fields

@viktorklochkov,
Please, add name theta to the list of reserved names of fields in track and hit detectors, and name eta to the list of reserved names of fields in hit detectors.

Matching needs refactor

Hi!

I revised AnalysisTree::Matching object and found few issues.

  1. Branch ids are redundant and should be AT LEAST transient fields (//!). All meta information about the matched branches are stored in the corresponding object inside the AnalysisTree::Configuration
  2. Storing direct and inverted maps is redundant. I propose to store more universal (and much less constrained) structure: std::list<std::pair<Integer, Integer>> and build direct and inverted maps on loading (inside Streamer) or if we fight for optimal performance on demand (when user calls GetMatch{Direct,Inverted}). With this strategy one can use even boost::bimap since we do not need to store it.

misleading readme

You propose to build root from scratch which takes lots of and does not differ from the package you can download in a minute for the most popular linux distributions. The only added value could be specifying the cxx17 flag but there is no mention about it. Moreover AnalysisTree will not compile if you use root installation built with cxx11 if you do not state this explicitly. Again, it is not mentioned in the readme.

Warning about deprecated function

Hi,

when compiling the CbmRoot interface to AnalysisTree I get the following warnings abou a deprecated function

In file included from /Users/uhlig/software/fair/cbm/cbmroot_git/analysis/common/analysis_tree_converter/CbmConverterManager.cxx:4:
/opt/cbmroot/build/git_fairroot-v18.2.1_fairsoft-jun19p2/include/AnalysisTree/TaskManager.hpp:52:43: warning: 'GetBranchName' is deprecated [-Wdeprecated-declarations]
    cuts_map_.insert(std::make_pair(cuts->GetBranchName(), cuts));
                                          ^
/opt/cbmroot/build/git_fairroot-v18.2.1_fairsoft-jun19p2/include/AnalysisTree/Cuts.hpp:63:5: note: 'GetBranchName' has been explicitly marked deprecated here
  [[deprecated]]
    ^

Could you have a look and see if you can fix it.

Variabl::GetValue relies on branch_id-s which can change under specific circumstances

Dear Viktor,

double Variable::GetValue(const A& a, int a_id, const B& b, int b_id) const {

This function takes two data objects (e.g. EventHeaders) and two branch id-s to take value from either one branch or from another. As far as I understood, it makes sense for composite variables which can have (in principle) more than one branch.

How the AT::Field gets branch_id:

AT::Field gets branch_id during the call AT::Field::Init(AT::Configuration) from the corresponding BranchConfig. In turn, index of BranchConfig is selected by the AT::Configuration during Configuration::AddBranchConfig

What is a_id (b_id):

These arguments are taken from data pointers. Data pointers are taking their index at creation.

What goes wrong

AnalysisTree::TaskManager allows to take several input files (filelists) and merge branches of AT. Configuration is merged also. BranchConfig-s from many other configurations are added to the first one via Configuration::AddBranchConfig.

So what happens:
Indexing of BranchConfig-s changed after merge.
Indexing in the data pointers doesn't change.

Surprisingly, this bug appears only when two branches are participating on one AnalysisTree::VarManagerEntry. In this case Field::GetValue decides, from which pointer it takes the value basing on branch ids. And throws:

throw std::runtime_error("Variable::Fill - Cannot fill value from branch " + field.GetBranchName());

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.