Project

General

Profile

Actions

Development #2258

closed

Development #2256: Demonstrator for digi-based trigger, STS-only

Development #2257: Preparation of software infrastructure

ROOT-free digi classes

Added by Volker Friese 8 months ago. Updated 7 months ago.

Status:
Closed
Priority:
Normal
Assignee:
Target version:
Start date:
09/28/2021
Due date:
10/03/2021
% Done:

100%

Estimated time:
10.00 h
Spent time:

Description

We want to create a or several algo libraries which are not linked to ROOT. However, surely the algo classes have to link to the data classes (digis in the first place). So, we have to remove the ROOT dependence from the digis.

The digis already do not derive any longer from TObject, but use the ROOT ClassDef macro. This, to my knowledge, generates a streamer and an entry in the dictionary such that the class can be used from the ROOT prompt (interpreter).

The possibility to remove all ROOT functionality from the digis and the consequences shall be investigated: what are the implication for storage in ROOT files, for usage of the class from the ROOT prompt, and for usage of the class in TBrowser.


Related issues

Precedes Framework - Development #2260: Move CbmStsDigi to algo/data/stsClosedVolker Friese10/04/202110/05/2021

Actions
Actions #1

Updated by Volker Friese 8 months ago

Actions #2

Updated by Florian Uhlig 8 months ago

  • Status changed from Assigned to In Progress
  • Assignee changed from Florian Uhlig to Volker Friese
  • % Done changed from 0 to 20

To judge on the questions put on the table in this issue I have created a small example which can be found in my GitLab repository.
I add a project which puts together several small ROOT based examples I did recently. The project is at https://git.cbm.gsi.de/f.uhlig/root_examples and the actual example for this issue is in the directory RootFreeDigis. The directory also contains a small README.md which keeps some basic information as well as the installation instructions.

The example contains three branches which implements slightly different versions which I will explain in more detail below. The project builds a library which contains the data class and the streamer (if present) and two programs where one of them generates some data which is written into a ROOT file and the other program reads the data from file and fills some histograms.

The used data class is CbmStsDigi with and without changes to test different ROOT dependencies.

In the branch master the CbmStsDigi class is used as is in CbmRoot with the ROOT macros (ClassDef and ClassImp). When building the project a ROOT dictionary is generated and linked into the Data library. This allows to write the data into a ROOT file as well as to use the data class from the ROOT prompt.
The compilation of CbmStsDigi depend on some boost and ROOT header files. Linking the library depends on the Core library of ROOT. This dependency comes in through the generated ROOT dictionary.

In the branch no_macros the ROOT macros as well as one of the ROOT header files (Rtypes.h defining the macros) were removed from the class CbmStsDigi. When building the project still the ROOT dictionary is generated and linked into the Data library. This still allows to write the data into a ROOT file as well as to use the data class from the ROOT prompt. The compilation of CbmStsDigi depend on some boost and the ROOT header file which defines the ROOT data types. Linking the library still depends on the Core library of ROOT.

The last version implemented in the branch no_streamer removes besides the ROOT macros also the dependency of the Data library from ROOT's Core library. This is achieved by not building and linking a ROOT dictionary at all. The bad side effect is that now it isn't possible any longer to use the data class from the command line and even worse to write the data to a ROOT file.

The second version no_macros for me doesn't make sense for me. It is neither fish nor fowl, it doesn't remove the library dependency but it removes the versioning and the possibility to use the automatic schema evolution. In my opinion the two options we should further discuss is the current implementation which has a dependency on libCore and the the version without the ROOT dependency.

For me the advantage (if this is really an advantage) to not link against ROOT comes with the real disadvantage that we loose the ability to write our digis into ROOT file. For me this disadvantage is much more relevant than the small advantage we may gain. If the data library still depends on ROOT this doesn't mean that all the algorithm libraries depend on ROOT. They will need some ROOT header files for compilation but they need not to link any ROOT libraries, at least I don't see that need yet.

If it is really absolutely needed to have the data class without a ROOT dependency it should be possible to have the class with some preprocessor statements such that it can be compiled without the ROOT macros and the ROOT header file.
If we also want to get rid of the dependency on the ROOT data types there will be more work.

Actions #3

Updated by Volker Friese 8 months ago

Thanks! These are important lessons. I take away the following.

We have (in CbmStsDigi) three remaining ROOT features:

1. Usage of ROOT data types (inclusion of Rtypes.h)
Functionality: portable data types
Alternatives: probably similar safety can be obtained in modern C++ without ROOT
Removal: just use other data types in our code

2. Usage of the ClassDef macro (also defined in Rtypes.h)
Functionality: Schema evolution
Alternatives: Versioning in self-defined streamers (costly)
Removal: just not use the ClassDef statement in the header file

3. Creation of the dictionary (through LinkDef.h)
Functionality: Generation of a streamer; class can be used from the ROOT prompt
Alternatives: Self-defined streamer? Will we then be able to store in ROOT files?
Removal: No consequence in the user code; change in the build setup (CMakeLists.txt)

One lesson for me from what you state above is that 2. and 3. are independent, so you can have a dictionary without ClassDef macro - although I agree that this does not make much sense.

Important is that 2. and 3. can be easily removed on build level, without change in the user code (except the inclusion of ClassDef, which can be caught be a preprocessor directive). So we could imagine a build type with ROOT and a build type without ROOT.

Actions #4

Updated by Florian Uhlig 8 months ago

We have (in CbmStsDigi) three remaining ROOT features:

1. Usage of ROOT data types (inclusion of Rtypes.h)
Functionality: portable data types
Alternatives: probably similar safety can be obtained in modern C++ without ROOT
Removal: just use other data types in our code

In my opinion this is only relevant for the data classes since these could be used from file on several different patforms.
For the rest of the code there is no problem.
Anyway I am already looking into the issue.

2. Usage of the ClassDef macro (also defined in Rtypes.h)
Functionality: Schema evolution
Alternatives: Versioning in self-defined streamers (costly)
Removal: just not use the ClassDef statement in the header file

The macros are not defined in Rtypes.h but in RtypesCore.h.

3. Creation of the dictionary (through LinkDef.h)
Functionality: Generation of a streamer; class can be used from the ROOT prompt
Alternatives: Self-defined streamer? Will we then be able to store in ROOT files?
Removal: No consequence in the user code; change in the build setup (CMakeLists.txt)

I think if you want to store something in a ROOT file even the hand-made streamer will depend on the ROOT's libCore.

One lesson for me from what you state above is that 2. and 3. are independent, so you can have a dictionary without ClassDef macro - although I agree that this does not make much sense.

Important is that 2. and 3. can be easily removed on build level, without change in the user code (except the inclusion of ClassDef, which can be caught be a preprocessor directive). So we could imagine a build type with ROOT and a build type without ROOT.

This is also something I am currently investigating. We have to see if this is easily possible since the algorithm libraries will be used in future from the different frameworks. I don't know what happens if the framework uses a different CbmStsDigi than the algorithm.

For the time being I would opt to keep the dependency on libCore for the data classes.

Actions #5

Updated by Volker Friese 8 months ago

Let's discuss with Jan and the others in tomorrow's software meeting.

Actions #6

Updated by Jan de Cuveland 8 months ago

1. Usage of ROOT data types (inclusion of Rtypes.h)

I have looked at the different type definitions and prepared a few slides comparing them for tomorrow's meeting. (tl;dr: I found no disadvantage in removing the ROOT types.)

Important is that 2. and 3. can be easily removed on build level, without change in the user code (except the inclusion of ClassDef, which can be caught be a preprocessor directive). So we could imagine a build type with ROOT and a build type without ROOT.

I don't know what happens if the framework uses a different CbmStsDigi than the algorithm.

If feasible, Volker's suggestion of using the same source code for two library build flows (with and without ROOT dependency) seems attractive to me. The ClassDef/ClassImp macros, easily #define's away if used without ROOT, would not hurt.

I think we will need to test how the interaction between the worlds can work. But if the ROOT macros do not change the memory footprint of the class, as I assume, this should be feasible. If they changed the memory footprint, however, we wouldn't want the macros in anyway, because we don't want additional overhead in the lowest-level data types.

Actions #7

Updated by Florian Uhlig 8 months ago

1. Usage of ROOT data types (inclusion of Rtypes.h)

I have looked at the different type definitions and prepared a few slides comparing them for tomorrow's meeting. (tl;dr: I found no disadvantage in removing the ROOT types.)

I don't expect any. The ROOT types are only typedefs for the different systems.

If feasible, Volker's suggestion of using the same source code for two library build flows (with and without ROOT dependency) seems attractive to me. The ClassDef/ClassImp macros, easily #define's away if used without ROOT, would not hurt.

This is very easy to achieve.

I think we will need to test how the interaction between the worlds can work. But if the ROOT macros do not change the memory footprint of the class, as I assume, this should be feasible. If they changed the memory footprint, however, we wouldn't want the macros in anyway, because we don't want additional overhead in the lowest-level data types.

I don't expect that the memory footprint is changed but for sure this has to be checked.
My concern was more the linkage. What happens if you link a binary and the class exist in two different versions in two different libraries. Here I have no idea what will happen.

Actions #8

Updated by Florian Uhlig 8 months ago

  • % Done changed from 20 to 100
Actions #9

Updated by Florian Uhlig 8 months ago

  • Status changed from In Progress to Resolved

The new library libCbmOnlineData which contains a ROOT free version of CbmStsDigi will be implemented with https://git.cbm.gsi.de/computing/cbmroot/-/merge_requests/525.

Actions #10

Updated by Volker Friese 7 months ago

  • Status changed from Resolved to Closed
Actions #11

Updated by Volker Friese 7 months ago

  • Status changed from Closed to In Progress
  • Assignee changed from Volker Friese to Florian Uhlig

The last version implemented in the branch no_streamer removes besides the ROOT macros also the dependency of the Data library from ROOT's Core library. This is achieved by not building and linking a ROOT dictionary at all. The bad side effect is that now it isn't possible any longer to use the data class from the command line and even worse to write the data to a ROOT file.

I have to disagree with this statement. I have removed the ROOT includes and ClassDef from CbmStsDigi.h, the ClassImp macro from CbmStsDigi.cxx, and the entry in DataLinkDef.f for CbmStsDigi.

With these settings, I can perfectly run simulation and reconstruction, and see the StsDigis in the TBrowser and browse their members. In case of simulation (.raw.root), where the StsDigis are in a TClonesArray, I can even call the accessor functions (GetCharge, GetTime) from the TBrowser. For the reco data, where StsDigis are in a std::vector, this is not possible; the members can be directly browsed, but since the information is packed, this is not so meaningful.

Anyhow, TBrowser is a nice but probably dispensable feature. What's important here is that StsDigis can be written to and read from a ROOT file even without linking them to ROOT.

For the compilation to succeed, I have to remove fles, MQ and tutorials from the target list. Since sim and reco do compile and run, I assume that the others could be fixed as well.

Actions #12

Updated by Florian Uhlig 7 months ago

I disagree since this probably only comes by chance. At some place the needed streamer is created due to an implicit dependency (statement??).
If you write such a ROOT free digi in a very simple macro there is no meaningful data in the ROOT file.

The code is implemented in the branch no_streamer of my simple example which you can get from https://git.cbm.gsi.de/f.uhlig/root_examples.
The code is in the sub directory RootFreeDigis.

Actions #13

Updated by Volker Friese 7 months ago

That may be true (see our email exchange). So, at some place, streamer code is generated without you knowing where and why. Probably for each class which CbmStsDigi is a member.

Actions #14

Updated by Volker Friese 7 months ago

  • Status changed from In Progress to Closed
Actions

Also available in: Atom PDF