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 target.createGroup(sg.getObjName());
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) :
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
122 H5::Group Merger::convert(const H5::Group& group)
123 {
124 return group;
125 }
126
127 H5::Group Merger::convert(const H5::H5File& file)
128 {
129 return file.openGroup("/");
130 }
131
132 void Merger::flush(H5::Group& dst)
133 {
134 m_histMerger->write(dst);
135 }
136} //> 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:95
bool m_measureBufferInRows
Whether to measure the buffer in bytes or rows.
Definition Merger.h:101
std::unique_ptr< H5Utils::hist::HistogramMerger > m_histMerger
Accumulator for UHI histogram groups.
Definition Merger.h:103
void flush(H5::Group &dst)
Write all accumulated histogram data to the output.
Definition Merger.cxx:132
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:93
std::size_t m_bufferSize
The size of the buffer.
Definition Merger.h:99
bool m_requireSameFormat
Whether to require the same group structure.
Definition Merger.h:97
static H5::Group convert(const H5::Group &group)
convert() is a no-op for a Group, used by the merge() template
Definition Merger.cxx:122
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.
TFile * file