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

Make branch names for relations more legible for ROOT based I/O #405

Merged
merged 9 commits into from
Jun 5, 2023
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ project(podio)
#--- Version -------------------------------------------------------------------
SET( ${PROJECT_NAME}_VERSION_MAJOR 0 )
SET( ${PROJECT_NAME}_VERSION_MINOR 16 )
SET( ${PROJECT_NAME}_VERSION_PATCH 5 )
SET( ${PROJECT_NAME}_VERSION_PATCH 6 )

SET( ${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH}" )

Expand Down
2 changes: 2 additions & 0 deletions include/podio/CollectionBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ namespace podio {
// forward declarations
class ICollectionProvider;

struct RelationNames;

class CollectionBase {
protected:
/// default constructor
Expand Down
3 changes: 3 additions & 0 deletions include/podio/CollectionBranches.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "TBranch.h"

#include <string>
#include <vector>

namespace podio::root_utils {
Expand All @@ -15,6 +16,8 @@ struct CollectionBranches {
TBranch* data{nullptr};
std::vector<TBranch*> refs{};
std::vector<TBranch*> vecs{};
std::vector<std::string> refNames{}; ///< The names of the relation branches
std::vector<std::string> vecNames{}; ///< The names of the vector member branches
};

} // namespace podio::root_utils
Expand Down
1 change: 1 addition & 0 deletions include/podio/CollectionBuffers.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

Expand Down
40 changes: 39 additions & 1 deletion include/podio/DatamodelRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,39 @@

#include <string>
#include <string_view>
#include <tuple>
#include <unordered_map>
#include <utility>
#include <vector>

namespace podio {

/**
* Type alias for storing the names of all Relations and VectorMembers for all
* datatypes of an EDM. Populated for each EDM at code generation time.
* The structure is of each element in the outer vector is:
tmadlener marked this conversation as resolved.
Show resolved Hide resolved
* - get<0>: The name of the datatype
* - get<1>: The names of all Relations, where OneToManyRelations comes before
* OneToOneRelations (in the order as they appear in the YAML file)
* - get<2>: The names of all VectorMembers (in the order of the file YAML)
*/
using RelationNameMapping =
std::vector<std::tuple<std::string_view, std::vector<std::string_view>, std::vector<std::string_view>>>;

/**
* Information on the names of the OneTo[One|Many]Relations as well as the
* VectorMembers of a datatype
*
* The contents are populated by the code generation, where we simply generate
* static vectors that we make available as const& here.
*/
struct RelationNames {
/// The names of the relations (OneToMany before OneToOne)
const std::vector<std::string_view>& relations;
/// The names of the vector members
const std::vector<std::string_view>& vectorMembers;
};

/**
* Global registry holding information about datamodels and datatypes defined
* therein that are currently known by podio (i.e. which have been dynamically
Expand Down Expand Up @@ -85,14 +113,24 @@ class DatamodelRegistry {
* @param name The name of the EDM that should be registered
* @param definition The datamodel definition from which this EDM has been
* generated in JSON format
* @param relationNames the names of the relations and vector members for all
* datatypes that are defined for this EDM
*
*/
size_t registerDatamodel(std::string name, std::string_view definition);
size_t registerDatamodel(std::string name, std::string_view definition,
const podio::RelationNameMapping& relationNames);

/**
* Get the names of the relations and vector members of a datatype
*/
RelationNames getRelationNames(std::string_view typeName) const;

private:
DatamodelRegistry() = default;
/// The stored definitions
std::vector<std::pair<std::string, std::string_view>> m_definitions{};

std::unordered_map<std::string_view, RelationNames> m_relations{};
};
} // namespace podio

Expand Down
6 changes: 6 additions & 0 deletions python/podio_class_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,14 @@ def _write_edm_def_file(self):
'edm_definition': model_encoder.encode(self.datamodel),
'incfolder': self.incfolder,
'schema_version': self.datamodel.schema_version,
'datatypes': self.datamodel.datatypes,
}

def quoted_sv(string):
return f"\"{string}\"sv"

self.env.filters["quoted_sv"] = quoted_sv

self._write_file('DatamodelDefinition.h',
self._eval_template('DatamodelDefinition.h.jinja2', data))

Expand Down
4 changes: 4 additions & 0 deletions python/templates/Collection.h.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
#include <memory>
#include <cstddef>

namespace podio {
struct RelationNames;
}

{{ utils.namespace_open(class.namespace) }}


Expand Down
42 changes: 36 additions & 6 deletions python/templates/DatamodelDefinition.h.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,27 @@ namespace {{ package_name }}::meta {
*/
static constexpr auto {{ package_name }}__JSONDefinition = R"DATAMODELDEF({{ edm_definition }})DATAMODELDEF";


/**
* The names of all relations and vector members for all datatypes
*/
inline podio::RelationNameMapping {{ package_name }}__getRelationNames() {
using namespace std::string_view_literals;
return {
{% for typeName, type in datatypes.items() %}
{"{{ typeName }}"sv,
{ {{ (type.OneToManyRelations + type.OneToOneRelations) | map(attribute="name") | map("quoted_sv") | join(", ") }} },
{ {{ type.VectorMembers | map(attribute="name") | map("quoted_sv") | join(", ")}} },
},
{% endfor %}
};
}

/**
* The schema version at generation time
*/
static constexpr podio::SchemaVersionT schemaVersion = {{ schema_version }};

/**
* The helper class that takes care of registering the datamodel definition to
* the DatamodelRegistry and to provide the index in that registry.
Expand All @@ -19,18 +40,27 @@ static constexpr auto {{ package_name }}__JSONDefinition = R"DATAMODELDEF({{ edm
class DatamodelRegistryIndex {
public:
static size_t value() {
static auto index = DatamodelRegistryIndex(podio::DatamodelRegistry::mutInstance().registerDatamodel("{{ package_name }}", {{ package_name }}__JSONDefinition));
static const auto relationNames = {{ package_name }}__getRelationNames();
static auto index = DatamodelRegistryIndex(podio::DatamodelRegistry::mutInstance().registerDatamodel("{{ package_name }}", {{ package_name }}__JSONDefinition, relationNames));
return index.m_value;
}

private:
DatamodelRegistryIndex(size_t v) : m_value(v) {}
size_t m_value{podio::DatamodelRegistry::NoDefinitionAvailable};
};

/**
* The schema version at generation time
*/
static constexpr podio::SchemaVersionT schemaVersion = {{ schema_version }};

namespace static_registration {
// The usual trick via an IIFE and a const variable that we assign to, to
// ensure that we populate this before everything starts
inline bool ensureRegistration() {
const static auto reg = []() {
return {{ package_name }}::meta::DatamodelRegistryIndex::value() != podio::DatamodelRegistry::NoDefinitionAvailable;
}();
return reg;
}

const auto registrationEnsured = ensureRegistration();
}

} // namespace {{ package_name }}::meta
26 changes: 25 additions & 1 deletion src/DatamodelRegistry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@ DatamodelRegistry& DatamodelRegistry::mutInstance() {
return registryInstance;
}

size_t DatamodelRegistry::registerDatamodel(std::string name, std::string_view definition) {
size_t DatamodelRegistry::registerDatamodel(std::string name, std::string_view definition,
const podio::RelationNameMapping& relationNames) {
const auto it = std::find_if(m_definitions.cbegin(), m_definitions.cend(),
[&name](const auto& kvPair) { return kvPair.first == name; });

if (it == m_definitions.cend()) {
int index = m_definitions.size();
m_definitions.emplace_back(name, definition);

for (const auto& [typeName, relations, vectorMembers] : relationNames) {
m_relations.emplace(typeName, RelationNames{relations, vectorMembers});
}

return index;
}

Expand Down Expand Up @@ -60,4 +66,22 @@ const std::string& DatamodelRegistry::getDatamodelName(size_t index) const {
return m_definitions[index].first;
}

RelationNames DatamodelRegistry::getRelationNames(std::string_view typeName) const {
static std::vector<std::string_view> emptyVec{};
if (typeName.substr(0, 24) == "podio::UserDataCollection") {
return {emptyVec, emptyVec};
}

// Strip Collection if necessary
if (typeName.size() > 10 && typeName.substr(typeName.size() - 10) == "Collection") {
typeName = typeName.substr(0, typeName.size() - 10);
}

if (const auto it = m_relations.find(typeName); it != m_relations.end()) {
return it->second;
}

return {emptyVec, emptyVec};
}

} // namespace podio
Loading