Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for the new RNTuple format #395

Merged
merged 42 commits into from
Jul 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
7f2826f
Add a RNTuple writer
jmcarcell Mar 17, 2023
78d1162
Cleanup and add a reader
jmcarcell Mar 20, 2023
69d50c8
Add compilation instructions for RNTuple
jmcarcell Mar 20, 2023
f4cc923
Add tests
jmcarcell Mar 20, 2023
4dbbf7f
Fix the reader and writer so that they pass most of the tests
jmcarcell Mar 22, 2023
49167c9
Commit missing changes in the header
jmcarcell Mar 22, 2023
4bc7ed7
Add support for Generic Parameters
jmcarcell Mar 22, 2023
9fc8da3
Add an ugly workaround to the unique_ptr issue
jmcarcell Mar 22, 2023
529dffc
Read also vector members and remove some comments
jmcarcell Mar 22, 2023
8dcdf5a
Do a bit of cleanup
jmcarcell Mar 22, 2023
27e7b87
Do more cleanup, also compiler warnings
jmcarcell Mar 22, 2023
5ea4a97
Add names in rootUtils.h, fix a few compiler warnings
jmcarcell Mar 24, 2023
bdf4335
Add a few minor changes
jmcarcell Mar 24, 2023
f119026
Add missing changes in the headers
jmcarcell Mar 24, 2023
2aa55ef
Change map -> unordered_map and use append in CMakeLists.txt
jmcarcell Apr 11, 2023
5edd00e
Simplify writing and reading of generic parameters
jmcarcell Apr 17, 2023
4d995e3
Only create the ID table once
jmcarcell Apr 17, 2023
647dd87
Add CollectionInfo structs
jmcarcell Apr 17, 2023
8fee8b3
Add a ROOT version check
jmcarcell Apr 17, 2023
a1d97ba
Add missing endif()
jmcarcell Apr 17, 2023
d8ab05a
Add Name at the end of some names
jmcarcell Apr 17, 2023
be74a35
Add missing Name at the end
jmcarcell Apr 17, 2023
53e1dd0
Cast to rvalue
jmcarcell Apr 17, 2023
7216c2d
Cache entries and reserve
jmcarcell Apr 17, 2023
01ccc64
Add comment and remove old comments
jmcarcell Apr 17, 2023
09cbd61
Remove a few couts
jmcarcell Apr 17, 2023
52b419d
Remove intermediate variables and use std::move
jmcarcell Apr 18, 2023
7379ade
Run clang-format
jmcarcell Apr 19, 2023
027925b
Use clang-format on tests too
jmcarcell Apr 19, 2023
2629d66
Enable RNTuple I/O in Key4hep CI
tmadlener Apr 25, 2023
f8c58d1
Check if dev3 workflows come with recent enough ROOT
tmadlener Apr 25, 2023
a4ecb55
Change MakeField to the new signature
jmcarcell Apr 25, 2023
beaf236
Update the RNTuple reader and writer to use the buffer factory
jmcarcell May 14, 2023
ab5cfb2
Run clang-format
jmcarcell May 15, 2023
1cd727e
Update the RNTuple writer to use a bare model
jmcarcell May 30, 2023
f34ebc7
Add friends for Generic Parameters
jmcarcell May 30, 2023
659e051
Update changes after the changes in the collectionID and string_view
jmcarcell Jun 27, 2023
a471949
Run clang-format
jmcarcell Jun 28, 2023
178e6a1
Update the reader and writer to conform to #405
jmcarcell Jul 10, 2023
5be7223
Reorganize and clean up code in the reader
jmcarcell Jul 11, 2023
ec5bcf3
Run clang-format
jmcarcell Jul 11, 2023
b0f654c
Simplify how the references are filled
jmcarcell Jul 11, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/key4hep.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ jobs:
-DCMAKE_INSTALL_PREFIX=../install \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_CXX_FLAGS=" -fdiagnostics-color=always -Werror -Wno-error=deprecated-declarations " \
-DUSE_EXTERNAL_CATCH2=AUTO \
-DUSE_EXTERNAL_CATCH2=ON \
-DENABLE_RNTUPLE=ON \
-G Ninja ..
echo "::endgroup::"
echo "::group::Build"
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ jobs:
-DCMAKE_INSTALL_PREFIX=../install \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_CXX_FLAGS=" -fdiagnostics-color=always -Werror -Wno-error=deprecated-declarations " \
-DUSE_EXTERNAL_CATCH2=OFF \
-DPODIO_SET_RPATH=ON \
-G Ninja ..
-DUSE_EXTERNAL_CATCH2=OFF \
-DPODIO_SET_RPATH=ON \
-DENABLE_RNTUPLE=ON \
-G Ninja ..
echo "::endgroup::"
echo "::group::Build"
ninja -k0
Expand Down
10 changes: 9 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,20 @@ ADD_CLANG_TIDY()
option(CREATE_DOC "Whether or not to create doxygen doc target." OFF)
option(ENABLE_SIO "Build SIO I/O support" OFF)
option(PODIO_RELAX_PYVER "Do not require exact python version match with ROOT" OFF)
option(ENABLE_RNTUPLE "Build with support for the new ROOT NTtuple format" OFF)


#--- Declare ROOT dependency ---------------------------------------------------
list(APPEND CMAKE_PREFIX_PATH $ENV{ROOTSYS})
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
find_package(ROOT REQUIRED COMPONENTS RIO Tree)
if(NOT ENABLE_RNTUPLE)
find_package(ROOT REQUIRED COMPONENTS RIO Tree)
else()
find_package(ROOT REQUIRED COMPONENTS RIO Tree ROOTNTuple)
if(${ROOT_VERSION} VERSION_LESS 6.28.02)
message(FATAL_ERROR "You are trying to build podio with support for the new ROOT NTuple format, but your ROOT version is too old. Please update ROOT to at least version 6.28.02")
endif()
endif()

# Check that root is compiled with a modern enough c++ standard
get_target_property(ROOT_COMPILE_FEATURES ROOT::Core INTERFACE_COMPILE_FEATURES)
Expand Down
1 change: 1 addition & 0 deletions include/podio/CollectionBuffers.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ using VectorMembersInfo = std::vector<std::pair<std::string, void*>>;
*/
struct CollectionWriteBuffers {
void* data{nullptr};
void* vecPtr{nullptr};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not entirely happy with this one. But at the moment we seem to not have any other option(?).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not yet, it's in my todo list

CollRefCollection* references{nullptr};
VectorMembersInfo* vectorMembers{nullptr};

Expand Down
8 changes: 8 additions & 0 deletions include/podio/GenericParameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ class write_device;
using version_type = uint32_t; // from sio/definitions
} // namespace sio

namespace podio {
class ROOTNTupleReader;
class ROOTNTupleWriter;
} // namespace podio

#define DEPR_NON_TEMPLATE \
[[deprecated("Non-templated access will be removed. Switch to templated access functionality")]]

Expand Down Expand Up @@ -145,6 +150,8 @@ class GenericParameters {

friend void writeGenericParameters(sio::write_device& device, const GenericParameters& parameters);
friend void readGenericParameters(sio::read_device& device, GenericParameters& parameters, sio::version_type version);
friend ROOTNTupleReader;
friend ROOTNTupleWriter;

/// Get a reference to the internal map for a given type
template <typename T>
Expand Down Expand Up @@ -187,6 +194,7 @@ class GenericParameters {
}
}

private:
/// Get the mutex that guards the map for the given type
template <typename T>
std::mutex& getMutex() const {
Expand Down
104 changes: 104 additions & 0 deletions include/podio/ROOTNTupleReader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#ifndef PODIO_ROOTNTUPLEREADER_H
#define PODIO_ROOTNTUPLEREADER_H

#include "podio/CollectionBranches.h"
#include "podio/ICollectionProvider.h"
#include "podio/ROOTFrameData.h"
#include "podio/SchemaEvolution.h"
#include "podio/podioVersion.h"
#include "podio/utilities/DatamodelRegistryIOHelpers.h"

#include <string>
#include <unordered_map>
#include <vector>

#include <ROOT/RNTuple.hxx>
#include <ROOT/RNTupleModel.hxx>

namespace podio {

/**
This class has the function to read available data from disk
and to prepare collections and buffers.
**/
class ROOTNTupleReader {

public:
ROOTNTupleReader() = default;
~ROOTNTupleReader() = default;

ROOTNTupleReader(const ROOTNTupleReader&) = delete;
ROOTNTupleReader& operator=(const ROOTNTupleReader&) = delete;

void openFile(const std::string& filename);
void openFiles(const std::vector<std::string>& filename);

/**
* Read the next data entry from which a Frame can be constructed for the
* given name. In case there are no more entries left for this name or in
* case there is no data for this name, this returns a nullptr.
*/
std::unique_ptr<podio::ROOTFrameData> readNextEntry(const std::string& name);

/**
* Read the specified data entry from which a Frame can be constructed for
* the given name. In case the entry does not exist for this name or in case
* there is no data for this name, this returns a nullptr.
*/
std::unique_ptr<podio::ROOTFrameData> readEntry(const std::string& name, const unsigned entry);

/// Returns number of entries for the given name
unsigned getEntries(const std::string& name);

/// Get the build version of podio that has been used to write the current file
podio::version::Version currentFileVersion() const {
return m_fileVersion;
}

void closeFile();

private:
/**
* Initialize the given category by filling the maps with metadata information
* that will be used later
*/
bool initCategory(const std::string& category);

/**
* Read and reconstruct the generic parameters of the Frame
*/
GenericParameters readEventMetaData(const std::string& name, unsigned entNum);

template <typename T>
void readParams(const std::string& name, unsigned entNum, GenericParameters& params);

std::unique_ptr<ROOT::Experimental::RNTupleReader> m_metadata{};

podio::version::Version m_fileVersion{};
DatamodelDefinitionHolder m_datamodelHolder{};

std::unordered_map<std::string, std::vector<std::unique_ptr<ROOT::Experimental::RNTupleReader>>> m_readers{};
std::unordered_map<std::string, std::unique_ptr<ROOT::Experimental::RNTupleReader>> m_metadata_readers{};
std::vector<std::string> m_filenames{};

std::unordered_map<std::string, int> m_entries{};
std::unordered_map<std::string, unsigned> m_totalEntries{};

struct CollectionInfo {
std::vector<unsigned int> id{};
std::vector<std::string> name{};
std::vector<std::string> type{};
std::vector<short> isSubsetCollection{};
std::vector<SchemaVersionT> schemaVersion{};
};

std::unordered_map<std::string, CollectionInfo> m_collectionInfo{};

std::vector<std::string> m_availableCategories{};

std::shared_ptr<podio::CollectionIDTable> m_table{};
};

} // namespace podio

#endif
74 changes: 74 additions & 0 deletions include/podio/ROOTNTupleWriter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#ifndef PODIO_ROOTNTUPLEWRITER_H
#define PODIO_ROOTNTUPLEWRITER_H

#include "podio/CollectionBase.h"
#include "podio/Frame.h"
#include "podio/GenericParameters.h"
#include "podio/SchemaEvolution.h"
#include "podio/utilities/DatamodelRegistryIOHelpers.h"

#include "TFile.h"
#include <ROOT/RNTuple.hxx>
#include <ROOT/RNTupleModel.hxx>

#include <string>
#include <unordered_map>
#include <vector>

namespace podio {

class ROOTNTupleWriter {
public:
ROOTNTupleWriter(const std::string& filename);
~ROOTNTupleWriter();

ROOTNTupleWriter(const ROOTNTupleWriter&) = delete;
ROOTNTupleWriter& operator=(const ROOTNTupleWriter&) = delete;

template <typename T>
void fillParams(GenericParameters& params, ROOT::Experimental::REntry* entry);

void writeFrame(const podio::Frame& frame, const std::string& category);
void writeFrame(const podio::Frame& frame, const std::string& category, const std::vector<std::string>& collsToWrite);
void finish();

private:
using StoreCollection = std::pair<const std::string&, podio::CollectionBase*>;
std::unique_ptr<ROOT::Experimental::RNTupleModel> createModels(const std::vector<StoreCollection>& collections);

std::unique_ptr<ROOT::Experimental::RNTupleModel> m_metadata{};
std::unordered_map<std::string, std::unique_ptr<ROOT::Experimental::RNTupleWriter>> m_writers{};
std::unique_ptr<ROOT::Experimental::RNTupleWriter> m_metadataWriter{};

std::unique_ptr<TFile> m_file{};

DatamodelDefinitionCollector m_datamodelCollector{};

struct CollectionInfo {
std::vector<unsigned int> id{};
std::vector<std::string> name{};
std::vector<std::string> type{};
std::vector<short> isSubsetCollection{};
std::vector<SchemaVersionT> schemaVersion{};
};

std::unordered_map<std::string, CollectionInfo> m_collectionInfo{};

std::set<std::string> m_categories{};

bool m_finished{false};

std::vector<std::string> m_intkeys{}, m_floatkeys{}, m_doublekeys{}, m_stringkeys{};

std::vector<std::vector<int>> m_intvalues{};
std::vector<std::vector<float>> m_floatvalues{};
std::vector<std::vector<double>> m_doublevalues{};
std::vector<std::vector<std::string>> m_stringvalues{};

template <typename T>
std::pair<std::vector<std::string>&, std::vector<std::vector<T>>&> getKeyValueVectors();
};

} // namespace podio

#endif // PODIO_ROOTNTUPLEWRITER_H
2 changes: 1 addition & 1 deletion include/podio/UserDataCollection.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class UserDataCollection : public CollectionBase {
/// Get the collection buffers for this collection
podio::CollectionWriteBuffers getBuffers() override {
_vecPtr = &_vec; // Set the pointer to the correct internal vector
return {&_vecPtr, &m_refCollections, &m_vecmem_info};
return {&_vecPtr, _vecPtr, &m_refCollections, &m_vecmem_info};
}

/// check for validity of the container after read
Expand Down
1 change: 1 addition & 0 deletions python/templates/CollectionData.cc.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ podio::CollectionWriteBuffers {{ class_type }}::getCollectionBuffers(bool isSubs

return {
isSubsetColl ? nullptr : (void*)&m_data,
isSubsetColl ? nullptr : (void*)m_data.get(),
&m_refCollections, // only need to store the ObjectIDs of the referenced objects
&m_vecmem_info
};
Expand Down
18 changes: 18 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ FUNCTION(PODIO_ADD_LIB_AND_DICT libname headers sources selection )
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
target_link_libraries(${dictname} PUBLIC podio::${libname} podio::podio ROOT::Core ROOT::Tree)
if(ENABLE_RNTUPLE)
target_link_libraries(${dictname} PUBLIC ROOT::ROOTNTuple)
endif()
PODIO_GENERATE_DICTIONARY(${dictname} ${headers} SELECTION ${selection}
OPTIONS --library ${CMAKE_SHARED_LIBRARY_PREFIX}${dictname}${CMAKE_SHARED_LIBRARY_SUFFIX}
)
Expand Down Expand Up @@ -82,15 +85,30 @@ SET(root_sources
ROOTFrameReader.cc
ROOTLegacyReader.cc
)
if(ENABLE_RNTUPLE)
list(APPEND root_sources
ROOTNTupleReader.cc
ROOTNTupleWriter.cc
)
endif()

SET(root_headers
${CMAKE_SOURCE_DIR}/include/podio/ROOTFrameReader.h
${CMAKE_SOURCE_DIR}/include/podio/ROOTLegacyReader.h
${CMAKE_SOURCE_DIR}/include/podio/ROOTFrameWriter.h
)
if(ENABLE_RNTUPLE)
list(APPEND root_headers
${CMAKE_SOURCE_DIR}/include/podio/ROOTNTupleReader.h
${CMAKE_SOURCE_DIR}/include/podio/ROOTNTupleWriter.h
)
endif()

PODIO_ADD_LIB_AND_DICT(podioRootIO "${root_headers}" "${root_sources}" root_selection.xml)
target_link_libraries(podioRootIO PUBLIC podio::podio ROOT::Core ROOT::RIO ROOT::Tree)
if(ENABLE_RNTUPLE)
target_link_libraries(podioRootIO PUBLIC ROOT::ROOTNTuple)
endif()


# --- Python EventStore for enabling (legacy) python bindings
Expand Down
Loading