FERS 1.0.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
hdf5_handler.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-only
2//
3// Copyright (c) 2006-2008 Marc Brooker and Michael Inggs
4// Copyright (c) 2008-present FERS Contributors (see AUTHORS.md).
5//
6// See the GNU GPLv2 LICENSE file in the FERS project root for more information.
7
8/**
9 * @file hdf5_handler.cpp
10 * @brief Source file for HDF5 data export and import functions.
11 */
12
13#include "hdf5_handler.h"
14
15#include <algorithm>
16#include <complex>
17#include <filesystem>
18#include <format>
19#include <highfive/highfive.hpp>
20#include <stdexcept>
21
22#include "core/logging.h"
23#include "core/parameters.h"
24
25using logging::Level;
26
27namespace serial
28{
29 void readPulseData(const std::string& name, std::vector<ComplexType>& data)
30 {
31 if (!std::filesystem::exists(name))
32 {
33 LOG(Level::FATAL, "File '{}' not found", name);
34 throw std::runtime_error("File " + name + " not found.");
35 }
36
37 LOG(Level::TRACE, "Opening file '{}'", name);
38 const HighFive::File file(name, HighFive::File::ReadOnly);
39
40 // Helper lambda to open group and read dataset
41 auto read_dataset = [&file](const std::string& groupName, std::vector<double>& buffer) -> size_t
42 {
43 const auto group = file.getGroup("/" + groupName);
44
45 const auto dataset = group.getDataSet("value");
46
47 const auto dimensions = dataset.getSpace().getDimensions();
48 const auto size = dimensions[0];
49
50 buffer.resize(size);
51 dataset.read(buffer);
52
53 return size;
54 };
55
56 LOG(Level::TRACE, "Reading dataset 'I' from file '{}'", name);
57 std::vector<double> buffer_i;
58 const auto size = read_dataset("I", buffer_i);
59
60 std::vector<double> buffer_q;
61 LOG(Level::TRACE, "Reading dataset 'Q' from file '{}'", name);
62 if (read_dataset("Q", buffer_q) != size)
63 {
64 LOG(Level::FATAL, "Dataset 'Q' is not the same size as dataset 'I' in file '{}'", name);
65 throw std::runtime_error(R"(Dataset "Q" is not the same size as dataset "I" in file )" + name);
66 }
67
68 data.resize(size);
69 for (size_t i = 0; i < size; ++i)
70 {
71 data[i] = ComplexType(buffer_i[i], buffer_q[i]);
72 }
73 LOG(Level::TRACE, "Read dataset successfully");
74 }
75
76 void addChunkToFile(HighFive::File& file, const std::vector<ComplexType>& data, const RealType time,
77 const RealType fullscale, const unsigned count)
78 {
79 const unsigned size = data.size();
80
81 const std::string base_chunk_name = "chunk_" + std::format("{:06}", count);
82 const std::string i_chunk_name = base_chunk_name + "_I";
83 const std::string q_chunk_name = base_chunk_name + "_Q";
84
85 std::vector<RealType> i(size), q(size);
86 std::ranges::transform(data, i.begin(), [](const ComplexType& c) { return c.real(); });
87 std::ranges::transform(data, q.begin(), [](const ComplexType& c) { return c.imag(); });
88
89 auto write_chunk = [&](const std::string& chunkName, const std::vector<RealType>& chunkData)
90 {
91 try
92 {
93 HighFive::DataSet dataset =
94 file.createDataSet<RealType>(chunkName, HighFive::DataSpace::From(chunkData));
95 dataset.write(chunkData);
96 }
97 catch (const HighFive::Exception& err)
98 {
99 LOG(Level::FATAL, "Error while writing data to HDF5 file: {}", err.what());
100 throw std::runtime_error("Error while writing data to HDF5 file: " + chunkName + " - " + err.what());
101 }
102 };
103
104 auto set_chunk_attributes = [&](const std::string& chunkName)
105 {
106 try
107 {
108 HighFive::DataSet dataset = file.getDataSet(chunkName);
109 dataset.createAttribute("time", time);
110 dataset.createAttribute("rate", params::rate());
111 dataset.createAttribute("fullscale", fullscale);
112 }
113 catch (const HighFive::Exception& err)
114 {
115 LOG(Level::FATAL, "Error while setting attributes on chunk: {}", err.what());
116 throw std::runtime_error("Error while setting attributes on chunk: " + chunkName + " - " + err.what());
117 }
118 };
119
120 write_chunk(i_chunk_name, i);
121 write_chunk(q_chunk_name, q);
122
123 set_chunk_attributes(i_chunk_name);
124 set_chunk_attributes(q_chunk_name);
125 }
126
127 std::vector<std::vector<RealType>> readPattern(const std::string& name, const std::string& datasetName)
128 {
129 try
130 {
131 LOG(Level::TRACE, "Reading dataset '{}' from file '{}'", datasetName, name);
132 const HighFive::File file(name, HighFive::File::ReadOnly);
133
134 const auto dataset = file.getDataSet(datasetName);
135
136 const auto dataspace = dataset.getSpace();
137 const auto dims = dataspace.getDimensions();
138
139 if (dims.size() != 2)
140 {
141 LOG(Level::FATAL, "Invalid dataset dimensions for '{}' in file '{}'", datasetName, name);
142 throw std::runtime_error(
143 std::format(R"(Invalid dataset dimensions for "{}" in file "{}")", datasetName, name));
144 }
145
146 LOG(Level::TRACE, "Reading dataset with dimensions {}x{}", dims[0], dims[1]);
147
148 std::vector data(dims[0], std::vector<RealType>(dims[1]));
149 dataset.read(data);
150
151 LOG(Level::TRACE, "Read dataset successfully");
152
153 return data;
154 }
155 catch (const HighFive::Exception& err)
156 {
157 LOG(Level::FATAL, "Error handling HDF5 file: {}", err.what());
158 throw std::runtime_error("Error handling HDF5 file: " + std::string(err.what()));
159 }
160 }
161}
double RealType
Type for real numbers.
Definition config.h:27
std::complex< RealType > ComplexType
Type for complex numbers.
Definition config.h:35
Header file for HDF5 data export and import functions.
Header file for the logging system.
#define LOG(level,...)
Definition logging.h:19
RealType rate() noexcept
Get the rendering sample rate.
Definition parameters.h:109
void readPulseData(const std::string &name, std::vector< ComplexType > &data)
Reads pulse data from an HDF5 file.
void addChunkToFile(HighFive::File &file, const std::vector< ComplexType > &data, const RealType time, const RealType fullscale, const unsigned count)
Adds a chunk of data to an HDF5 file.
std::vector< std::vector< RealType > > readPattern(const std::string &name, const std::string &datasetName)
Reads a 2D pattern dataset from an HDF5 file.
Defines the Parameters struct and provides methods for managing simulation parameters.