ATLAS Offline Software
Loading...
Searching...
No Matches
Merger.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "HDF5Utils/Merger.h"
9#include <exception>
10#include <iostream>
11
12namespace H5Utils {
13
15 hsize_t mergeAxis,
16 int chunkSize,
17 bool requireSameFormat,
18 std::size_t bufferSize,
19 bool bufferInRows) :
20 m_mergeAxis(mergeAxis),
21 m_chunkSize(chunkSize),
22 m_requireSameFormat(requireSameFormat),
23 m_bufferSize(bufferSize),
24 m_measureBufferInRows(bufferInRows),
25 m_histMerger(std::make_unique<H5Utils::hist::HistogramMerger>()) {}
26
28
30 H5::Group& target,
31 const H5::Group& source)
32 {
33 // Check if this group was empty before we started
34 bool isEmpty = target.getNumObjs() == 0;
35
36 // Iterate through each child of the source group
37 for (hsize_t ii = 0; ii < source.getNumObjs(); ++ii) {
38 H5G_obj_t childType = source.getObjTypeByIdx(ii);
39 std::string childName = source.getObjnameByIdx(ii);
40 // Find the correct index in the target
41 hsize_t targetIdx = 0;
42 for (; targetIdx < target.getNumObjs(); ++targetIdx)
43 if (target.getObjnameByIdx(targetIdx) == childName)
44 break;
45 bool found = targetIdx != target.getNumObjs();
46 if (found) {
47 // Make sure these are the same type!
48 if (target.getObjTypeByIdx(targetIdx) != childType)
49 throw std::invalid_argument(
50 "Both target and source contain " + childName +
51 " but they have different types!");
52 }
53 else if (m_requireSameFormat && !isEmpty) {
54 throw std::invalid_argument(
55 "Target and source have different formats!");
56 }
57 switch (childType) {
58 case H5G_GROUP:
59 {
60 H5::Group sg = source.openGroup(childName);
61 // UHI histogram groups are accumulated separately and written
62 // once all source files have been processed.
63 if (sg.attrExists("uhi_schema")) {
64 m_histMerger->add(sg.getObjName(), sg);
65 continue;
66 }
67 H5::Group tg = found ?
68 target.openGroup(childName) :
69 createFrom(target, sg);
70 try {
71 merge(tg, sg);
72 }
73 catch (...) {
74 std::cerr << "Encountered an error merging child " << childName << std::endl;
75 throw;
76 }
77 }
78 break;
79 case H5G_DATASET:
80 {
81 H5::DataSet sd = source.openDataSet(childName);
82 if (sd.getSpace().getSimpleExtentNdims() == 0) {
83 std::cerr << "WARNING: skipping scalar '"
84 << childName << "'" << std::endl;
85 break;
86 }
87 H5::DataSet td = found ?
88 target.openDataSet(childName) :
89 createFrom(target, sd);
90 try {
91 merge(td, sd);
92 }
93 catch (...) {
94 std::cerr << "Encountered an error merging child " << childName << std::endl;
95 throw;
96 }
97 }
98 break;
99 default:
100 break;
101 }
102 } //> end loop over children
103 // TODO - this did no check to see if target contained something source
104 // didn't, this is probably fine though.
105 } //> end function merge(group)
106
108 H5::DataSet& target,
109 const H5::DataSet& source)
110 {
111 std::size_t bufferSize = m_bufferSize;
113 // Need to calculate the actual buffer size
114 std::size_t rowSize = getRowSize(source, m_mergeAxis);
115 if (std::size_t(-1) / m_bufferSize < rowSize)
116 std::overflow_error("Requested buffer would overflow the register!");
117 bufferSize = rowSize * m_bufferSize;
118 }
119 mergeDatasets(target, source, m_mergeAxis, bufferSize);
120 }
121
123 H5::H5Location& targetLocation,
124 const H5::Group& source)
125 {
126 H5::Group newGroup = targetLocation.createGroup(source.getObjName());
127 merge(newGroup, source);
128 return newGroup;
129 }
130
132 H5::H5Location& targetLocation,
133 const H5::DataSet& source)
134 {
135 return createDataSet(targetLocation, source, m_mergeAxis, m_chunkSize);
136 }
137
138 void Merger::flush(H5::Group& dst)
139 {
140 m_histMerger->write(dst);
141 }
142} //> end namespace H5Utils
Merger(hsize_t mergeAxis=0, int chunkSize=-1, bool requireSameFormat=true, std::size_t bufferSize=-1, bool bufferInRows=false)
Create the merger.
Definition Merger.cxx:14
int m_chunkSize
The chunk size to apply.
Definition Merger.h:89
bool m_measureBufferInRows
Whether to measure the buffer in bytes or rows.
Definition Merger.h:95
std::unique_ptr< H5Utils::hist::HistogramMerger > m_histMerger
Accumulator for UHI histogram groups.
Definition Merger.h:97
void flush(H5::Group &dst)
Write all accumulated histogram data to the output.
Definition Merger.cxx:138
void merge(H5::Group &target, const H5::Group &source)
Merge a source group into a target group.
Definition Merger.cxx:29
hsize_t m_mergeAxis
The axis to merge along.
Definition Merger.h:87
std::size_t m_bufferSize
The size of the buffer.
Definition Merger.h:93
H5::Group createFrom(H5::H5Location &targetLocation, const H5::Group &source)
Make a new group from information in a source group.
Definition Merger.cxx:122
bool m_requireSameFormat
Whether to require the same group structure.
Definition Merger.h:91
HDF5 Tuple Writer.
std::size_t getRowSize(const H5::DataSet &ds, hsize_t axis)
Calculate the size of a row of a dataset in bytes.
H5::DataSet createDataSet(H5::H5Location &targetLocation, const H5::DataSet &source, hsize_t mergeAxis, int chunkSize=-1, int mergeExtent=-1)
Make a new dataset using the properties of another.
void mergeDatasets(H5::DataSet &target, const H5::DataSet &source, hsize_t mergeAxis, std::size_t bufferSize=-1)
Merge two datasets.
Definition merge.py:1
STL namespace.