Skip to content

Commit

Permalink
Add a parameter cloneRelations for clone to be able not to clone …
Browse files Browse the repository at this point in the history
…the collections (#609)

* Fix the equal comparison for relations of cloned objects

* Fix pre-commit

* Revert previous commits

This reverts commit e8b962a.

* Add a parameter to clone with empty relations

* Add tests adding to the relations of cloned objects

* Change from emptyRelations to cloneRelations

* Remove std::cout in the test case

* Add short documentation for cloning

---------

Co-authored-by: jmcarcell <[email protected]>
Co-authored-by: tmadlener <[email protected]>
  • Loading branch information
3 people authored Jun 4, 2024
1 parent ec1b8be commit a4e684f
Show file tree
Hide file tree
Showing 6 changed files with 262 additions and 10 deletions.
10 changes: 10 additions & 0 deletions doc/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,16 @@ and via direct object access:
}
```

### Cloneing objects

In order to clone objects it is necessary to use the `clone` method which
returns a `Mutable` object again. `clone` takes a parameter `cloneRelations`
which is defaulted to `true`. By default the relation information of the
original object is simply copied over, changing this to `false` only copies the
data but none of the relations.

![](figures/object_clone.svg)

### Support for Notebook-Pattern

The `notebook pattern` uses the assumption that it is better to create a small
Expand Down
194 changes: 194 additions & 0 deletions doc/figures/object_clone.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion python/templates/MutableObject.cc.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

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

{{ macros.constructors_destructors(class.bare_type, Members, prefix='Mutable') }}
{{ macros.constructors_destructors(class.bare_type, Members, multi_relations=OneToManyRelations + VectorMembers, prefix='Mutable') }}

{{ macros.member_getters(class, Members, use_get_syntax, prefix='Mutable') }}
{{ macros.single_relation_getters(class, OneToOneRelations, use_get_syntax, prefix='Mutable') }}
Expand Down
3 changes: 2 additions & 1 deletion python/templates/macros/declarations.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@
{{ full_type }}& operator=({{ full_type }} other);

/// create a mutable deep-copy of the object with identical relations
Mutable{{ type }} clone() const;
/// if cloneRelations=false, the relations are not cloned and will be empty
Mutable{{ type }} clone(bool cloneRelations=true) const;

/// destructor
~{{ full_type }}() = default;
Expand Down
35 changes: 27 additions & 8 deletions python/templates/macros/implementations.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,41 @@
return *this;
}

Mutable{{ type }} {{ full_type }}::clone() const {
Mutable{{ type }} {{ full_type }}::clone(bool cloneRelations) const {
{% if prefix %}
if (!cloneRelations) {
auto tmp = new {{ type }}Obj(podio::ObjectID{}, m_obj->data);
{% for relation in multi_relations %}
tmp->m_{{ relation.name }} = new std::vector<{{ relation.full_type }}>();
tmp->data.{{ relation.name }}_begin = 0;
tmp->data.{{ relation.name }}_end = 0;
{% endfor %}
return Mutable{{ type }}(podio::utils::MaybeSharedPtr(tmp, podio::utils::MarkOwned));
}
return Mutable{{ type }}(podio::utils::MaybeSharedPtr(new {{ type }}Obj(*m_obj), podio::utils::MarkOwned));
{% else %}
auto tmp = new {{ type }}Obj(podio::ObjectID{}, m_obj->data);
{% for relation in multi_relations %}
tmp->m_{{ relation.name }} = new std::vector<{{ relation.full_type }}>();
// If the current object has been read from a file, then the object may only have a slice of the relation vector
// so this slice has to be copied in case we want to modify it
tmp->m_{{ relation.name }}->reserve(m_obj->m_{{ relation.name }}->size());
for (size_t i = m_obj->data.{{ relation.name }}_begin; i < m_obj->data.{{ relation.name }}_end; i++) {
tmp->m_{{ relation.name }}->emplace_back((*m_obj->m_{{ relation.name }})[i]);
{% endfor %}
if (cloneRelations) {
{% for relation in multi_relations %}
// If the current object has been read from a file, then the object may only have a slice of the relation vector
// so this slice has to be copied in case we want to modify it
tmp->m_{{ relation.name }}->reserve(m_obj->m_{{ relation.name }}->size());
for (size_t i = m_obj->data.{{ relation.name }}_begin; i < m_obj->data.{{ relation.name }}_end; i++) {
tmp->m_{{ relation.name }}->emplace_back((*m_obj->m_{{ relation.name }})[i]);
}
tmp->data.{{ relation.name }}_begin = 0;
tmp->data.{{ relation.name }}_end = tmp->m_{{ relation.name }}->size();
{% endfor %}
}
tmp->data.{{ relation.name }}_begin = 0;
tmp->data.{{ relation.name }}_end = tmp->m_{{ relation.name }}->size();
else {
{% for relation in multi_relations %}
tmp->data.{{ relation.name }}_begin = 0;
tmp->data.{{ relation.name }}_end = 0;
{% endfor %}
}
return Mutable{{ type }}(podio::utils::MaybeSharedPtr(tmp, podio::utils::MarkOwned));
{% endif %}
}
Expand Down
28 changes: 28 additions & 0 deletions tests/unittests/unittest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1385,3 +1385,31 @@ TEST_CASE("Relations after cloning with SIO", "[relations][basics]") {
}

#endif

TEST_CASE("Clone empty relations", "[relations][basics]") {
auto coll = ExampleClusterCollection();
coll.create();
coll.create();
coll[0].addHits(ExampleHit());
coll[0].addHits(ExampleHit());
auto newColl = ExampleClusterCollection();
newColl.push_back(coll.at(0).clone(false));
newColl.push_back(coll.at(1).clone(false));
REQUIRE(newColl[0].Hits().empty());
REQUIRE(newColl[1].Hits().empty());
newColl[0].addHits(ExampleHit());
REQUIRE(newColl[0].Hits().size() == 1);
newColl[0].addHits(ExampleHit());
REQUIRE(newColl[0].Hits().size() == 2);

auto immCluster = ExampleCluster(coll.at(0));
auto immCluster2 = ExampleCluster(coll.at(1));
auto clonedImmCluster = immCluster.clone(false);
auto clonedImmCluster2 = immCluster2.clone(false);
REQUIRE(clonedImmCluster.Hits().empty());
REQUIRE(clonedImmCluster2.Hits().empty());
clonedImmCluster.addHits(ExampleHit());
REQUIRE(clonedImmCluster.Hits().size() == 1);
clonedImmCluster.addHits(ExampleHit());
REQUIRE(clonedImmCluster.Hits().size() == 2);
}

0 comments on commit a4e684f

Please sign in to comment.