Skip to content

Commit

Permalink
Add overload to dat and cce get_data functions
Browse files Browse the repository at this point in the history
Now they can return either a Matrix or a vector<vector<double>>
  • Loading branch information
knelli2 committed Sep 27, 2024
1 parent aa42e7b commit e9f4bcf
Show file tree
Hide file tree
Showing 9 changed files with 279 additions and 188 deletions.
64 changes: 48 additions & 16 deletions src/IO/H5/Cce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <cstdint>
#include <hdf5.h>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <vector>
Expand All @@ -23,6 +24,7 @@
#include "Utilities/Algorithm.hpp"
#include "Utilities/ConstantExpressions.hpp"
#include "Utilities/ErrorHandling/Error.hpp"
#include "Utilities/GenerateInstantiations.hpp"
#include "Utilities/MakeString.hpp"
#include "Utilities/StdHelpers.hpp"

Expand Down Expand Up @@ -182,41 +184,44 @@ void Cce::append(
}
}

std::unordered_map<std::string, Matrix> Cce::get_data() const {
std::unordered_map<std::string, Matrix> result{};
template <typename T>
std::unordered_map<std::string, T> Cce::get_data() const {
std::unordered_map<std::string, T> result{};

for (const std::string& bondi_var : bondi_variables_) {
const DataSet& dataset = bondi_datasets_.at(bondi_var);
result[bondi_var] = h5::retrieve_dataset(dataset.id, dataset.size);
result[bondi_var] = h5::retrieve_dataset<T>(dataset.id, dataset.size);
}

return result;
}

Matrix Cce::get_data(const std::string& bondi_variable_name) const {
template <typename T>
T Cce::get_data(const std::string& bondi_variable_name) const {
check_bondi_variable(bondi_variable_name);

const DataSet& dataset = bondi_datasets_.at(bondi_variable_name);
return h5::retrieve_dataset(dataset.id, dataset.size);
return h5::retrieve_dataset<T>(dataset.id, dataset.size);
}

std::unordered_map<std::string, Matrix> Cce::get_data_subset(
template <typename T>
std::unordered_map<std::string, T> Cce::get_data_subset(
const std::vector<size_t>& these_ell, const size_t first_row,
const size_t num_rows) const {
std::unordered_map<std::string, Matrix> result{};
std::unordered_map<std::string, T> result{};

for (const std::string& bondi_var : bondi_variables_) {
result[bondi_var] =
get_data_subset(bondi_var, these_ell, first_row, num_rows);
get_data_subset<T>(bondi_var, these_ell, first_row, num_rows);
}

return result;
}

Matrix Cce::get_data_subset(const std::string& bondi_variable_name,
const std::vector<size_t>& these_ell,
const size_t first_row,
const size_t num_rows) const {
template <typename T>
T Cce::get_data_subset(const std::string& bondi_variable_name,
const std::vector<size_t>& these_ell,
const size_t first_row, const size_t num_rows) const {
check_bondi_variable(bondi_variable_name);

if (alg::any_of(these_ell,
Expand All @@ -226,7 +231,11 @@ Matrix Cce::get_data_subset(const std::string& bondi_variable_name,
}

if (these_ell.empty()) {
return {num_rows, 0, 0.0};
if constexpr (std::is_same_v<T, Matrix>) {
return {num_rows, 0, 0.0};
} else {
return std::vector<std::vector<double>>(num_rows);
}
}

// Always grab the time
Expand All @@ -252,12 +261,16 @@ Matrix Cce::get_data_subset(const std::string& bondi_variable_name,
}

if (num_rows == 0) {
return {0, these_columns.size(), 0.0};
if constexpr (std::is_same_v<T, Matrix>) {
return {0, these_columns.size(), 0.0};
} else {
return std::vector<std::vector<double>>{};
}
}

const DataSet& dataset = bondi_datasets_.at(bondi_variable_name);
return h5::retrieve_dataset_subset(dataset.id, these_columns, first_row,
num_rows, dataset.size);
return h5::retrieve_dataset_subset<T>(dataset.id, these_columns, first_row,
num_rows, dataset.size);
}

void Cce::check_bondi_variable(const std::string& bondi_variable_name) const {
Expand All @@ -273,4 +286,23 @@ const std::array<hsize_t, 2>& Cce::get_dimensions(

return bondi_datasets_.at(bondi_variable_name).size;
}

#define TYPE(data) BOOST_PP_TUPLE_ELEM(0, data)

#define INSTANTIATE(_, data) \
template std::unordered_map<std::string, TYPE(data)> Cce::get_data() const; \
template TYPE(data) Cce::get_data(const std::string& bondi_variable_name) \
const; \
template std::unordered_map<std::string, TYPE(data)> Cce::get_data_subset( \
const std::vector<size_t>& these_ell, const size_t first_row, \
const size_t num_rows) const; \
template TYPE(data) Cce::get_data_subset( \
const std::string& bondi_variable_name, \
const std::vector<size_t>& these_ell, const size_t first_row, \
const size_t num_rows) const;

GENERATE_INSTANTIATIONS(INSTANTIATE, (Matrix, std::vector<std::vector<double>>))

#undef INSTANTIATE
#undef TYPE
} // namespace h5
19 changes: 12 additions & 7 deletions src/IO/H5/Cce.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,14 @@ class Cce : public h5::Object {
/// @{
/*!
* \brief Return all currently stored data in the `h5::Cce` file in the form
* of a `Matrix` for each bondi variable
* of a `Matrix` or a `std::vector<std::vector<double>>` for each bondi
* variable
*/
std::unordered_map<std::string, Matrix> get_data() const;
template <typename T = Matrix>
std::unordered_map<std::string, T> get_data() const;

Matrix get_data(const std::string& bondi_variable_name) const;
template <typename T = Matrix>
T get_data(const std::string& bondi_variable_name) const;
/// @}

/// @{
Expand All @@ -119,13 +122,15 @@ class Cce : public h5::Object {
* l_max that this file was constructed with. Also both the first and last row
* requested must be less than or equal to the total number of rows.
*/
std::unordered_map<std::string, Matrix> get_data_subset(
template <typename T = Matrix>
std::unordered_map<std::string, T> get_data_subset(
const std::vector<size_t>& these_ell, size_t first_row = 0,
size_t num_rows = 1) const;

Matrix get_data_subset(const std::string& bondi_variable_name,
const std::vector<size_t>& these_ell,
size_t first_row = 0, size_t num_rows = 1) const;
template <typename T = Matrix>
T get_data_subset(const std::string& bondi_variable_name,
const std::vector<size_t>& these_ell, size_t first_row = 0,
size_t num_rows = 1) const;
/// @}

/*!
Expand Down
25 changes: 18 additions & 7 deletions src/IO/H5/Dat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <iosfwd>
#include <memory>
#include <ostream>
#include <vector>

#include "DataStructures/Matrix.hpp"
#include "IO/H5/CheckH5.hpp"
Expand Down Expand Up @@ -160,14 +161,24 @@ void Dat::append(const Matrix& data) {
data.rows(), size_);
}

Matrix Dat::get_data() const {
return h5::retrieve_dataset(dataset_id_, size_);
template <typename T>
T Dat::get_data() const {
return h5::retrieve_dataset<T>(dataset_id_, size_);
}

Matrix Dat::get_data_subset(const std::vector<size_t>& these_columns,
const size_t first_row,
const size_t num_rows) const {
return retrieve_dataset_subset(dataset_id_, these_columns, first_row,
num_rows, size_);
template <typename T>
T Dat::get_data_subset(const std::vector<size_t>& these_columns,
const size_t first_row, const size_t num_rows) const {
return retrieve_dataset_subset<T>(dataset_id_, these_columns, first_row,
num_rows, size_);
}

template Matrix Dat::get_data() const;
template std::vector<std::vector<double>> Dat::get_data() const;
template Matrix Dat::get_data_subset(const std::vector<size_t>& these_columns,
const size_t first_row,
const size_t num_rows) const;
template std::vector<std::vector<double>> Dat::get_data_subset(
const std::vector<size_t>& these_columns, const size_t first_row,
const size_t num_rows) const;
} // namespace h5
8 changes: 5 additions & 3 deletions src/IO/H5/Dat.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ class Dat : public h5::Object {
* \example
* \snippet Test_Dat.cpp h5dat_get_data
*/
Matrix get_data() const;
template <typename T = Matrix>
T get_data() const;

/*!
* \brief Get only some columns over a range of rows
Expand All @@ -97,8 +98,9 @@ class Dat : public h5::Object {
* \example
* \snippet Test_Dat.cpp h5dat_get_subset
*/
Matrix get_data_subset(const std::vector<size_t>& these_columns,
size_t first_row = 0, size_t num_rows = 1) const;
template <typename T = Matrix>
T get_data_subset(const std::vector<size_t>& these_columns,
size_t first_row = 0, size_t num_rows = 1) const;

/*!
* \returns the number of rows (first index) and columns (second index)
Expand Down
64 changes: 54 additions & 10 deletions src/IO/H5/Helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <string>
#include <type_traits>
#include <typeinfo>
#include <vector>

#include "DataStructures/BoostMultiArray.hpp"
#include "DataStructures/DataVector.hpp"
Expand Down Expand Up @@ -101,6 +102,21 @@ struct VectorTo<2, Matrix> {
}
};

template <>
struct VectorTo<2, std::vector<std::vector<double>>> {
static std::vector<std::vector<double>> apply(
const std::vector<double>& raw_data, const std::array<hsize_t, 2>& size) {
std::vector<std::vector<double>> temp(size[0]);
for (size_t i = 0; i < size[0]; ++i) {
temp[i].resize(size[1]);
for (size_t j = 0; j < size[1]; ++j) {
temp[i][j] = raw_data[j + i * size[1]];
}
}
return temp;
}
};

template <>
struct VectorTo<3, DataVector> {
static DataVector apply(DataVector raw_data,
Expand Down Expand Up @@ -375,8 +391,13 @@ std::array<hsize_t, 2> append_to_dataset(
return new_size;
}

Matrix retrieve_dataset(const hid_t file_id,
const std::array<hsize_t, 2>& file_size) {
template <typename T>
T retrieve_dataset(const hid_t file_id,
const std::array<hsize_t, 2>& file_size) {
static_assert(std::is_same_v<T, Matrix> or
std::is_same_v<T, std::vector<std::vector<double>>>,
"'retrieve_dataset' can only return a Matrix or a "
"std::vector<std::vector<double>>.");
const hid_t dataspace_id = H5Dget_space(file_id);
CHECK_H5(dataspace_id, "Failed to get dataspace");

Expand All @@ -402,21 +423,32 @@ Matrix retrieve_dataset(const hid_t file_id,
h5::h5p_default(), temp.data()),
"Failed to read data");
}
return VectorTo<2, Matrix>::apply(temp, size);
return VectorTo<2, T>::apply(temp, size);
}

Matrix retrieve_dataset_subset(const hid_t file_id,
const std::vector<size_t>& these_columns,
const size_t first_row, const size_t num_rows,
const std::array<hsize_t, 2>& file_size) {
template <typename T>
T retrieve_dataset_subset(const hid_t file_id,
const std::vector<size_t>& these_columns,
const size_t first_row, const size_t num_rows,
const std::array<hsize_t, 2>& file_size) {
static_assert(std::is_same_v<T, Matrix> or
std::is_same_v<T, std::vector<std::vector<double>>>,
"'retrieve_dataset_subset' can only return a Matrix or a "
"std::vector<std::vector<double>>.");
Expects(first_row + num_rows <= file_size[0]);
Expects(std::all_of(
these_columns.begin(), these_columns.end(),
[size = file_size](const auto& column) { return column < size[1]; }));

const auto num_cols = these_columns.size();
if (0 == num_cols * num_rows) {
return {num_rows, num_cols, 0.0};
if constexpr (std::is_same_v<T, Matrix>) {
return {num_rows, num_cols, 0.0};
} else {
// Columns don't matter because either there are 0 columns, or there are 0
// rows. Either way we don't size the columns
return std::vector<std::vector<double>>(num_rows);
}
}

const hid_t dataspace_id = H5Dget_space(file_id);
Expand Down Expand Up @@ -462,8 +494,8 @@ Matrix retrieve_dataset_subset(const hid_t file_id,

CHECK_H5(H5Sclose(memspace_id), "Failed to close memory space");
CHECK_H5(H5Sclose(dataspace_id), "Failed to close dataspace");
return VectorTo<2, Matrix>::apply(
raw_data, std::array<hsize_t, 2>{{num_rows, num_cols}});
return VectorTo<2, T>::apply(raw_data,
std::array<hsize_t, 2>{{num_rows, num_cols}});
}

std::vector<std::string> get_group_names(const hid_t file_id,
Expand Down Expand Up @@ -963,6 +995,18 @@ template void write_to_attribute(const hid_t location_id,
const std::string& name, const bool& value);
template bool read_value_attribute<bool>(const hid_t location_id,
const std::string& name);
template Matrix retrieve_dataset(const hid_t file_id,
const std::array<hsize_t, 2>& file_size);
template std::vector<std::vector<double>> retrieve_dataset(
const hid_t file_id, const std::array<hsize_t, 2>& file_size);
template Matrix retrieve_dataset_subset(
const hid_t file_id, const std::vector<size_t>& these_columns,
const size_t first_row, const size_t num_rows,
const std::array<hsize_t, 2>& file_size);
template std::vector<std::vector<double>> retrieve_dataset_subset(
const hid_t file_id, const std::vector<size_t>& these_columns,
const size_t first_row, const size_t num_rows,
const std::array<hsize_t, 2>& file_size);

#define DIM(data) BOOST_PP_TUPLE_ELEM(1, data)

Expand Down
15 changes: 9 additions & 6 deletions src/IO/H5/Helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,17 @@ std::array<hsize_t, 2> append_to_dataset(
/// @{
/*!
* \ingroup HDF5Group
* \brief Convert the data in a dataset to a Matrix
* \brief Convert the data in a dataset to a Matrix or a
* std::vector<std::vector<double>>
*/
Matrix retrieve_dataset(hid_t file_id, const std::array<hsize_t, 2>& file_size);
template <typename T>
T retrieve_dataset(hid_t file_id, const std::array<hsize_t, 2>& file_size);

Matrix retrieve_dataset_subset(hid_t file_id,
const std::vector<size_t>& these_columns,
size_t first_row, size_t num_rows,
const std::array<hsize_t, 2>& file_size);
template <typename T>
T retrieve_dataset_subset(hid_t file_id,
const std::vector<size_t>& these_columns,
size_t first_row, size_t num_rows,
const std::array<hsize_t, 2>& file_size);
/// @}

/*!
Expand Down
17 changes: 10 additions & 7 deletions src/IO/H5/Python/Cce.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,21 @@ void bind_h5cce(py::module& m) {
py::class_<h5::Cce>(m, "H5Cce")
.def("append", &h5::Cce::append, py::arg("data"))
.def("get_legend", &h5::Cce::get_legend)
.def("get_data", py::overload_cast<>(&h5::Cce::get_data, py::const_))
.def(
"get_data",
py::overload_cast<const std::string&>(&h5::Cce::get_data, py::const_),
py::arg("bondi_variable_name"))
// Use the matrix overload because it all gets converted to numpy arrays
// anways
.def("get_data",
py::overload_cast<>(&h5::Cce::get_data<Matrix>, py::const_))
.def("get_data",
py::overload_cast<const std::string&>(&h5::Cce::get_data<Matrix>,
py::const_),
py::arg("bondi_variable_name"))
.def("get_data_subset",
py::overload_cast<const std::vector<size_t>&, size_t, size_t>(
&h5::Cce::get_data_subset, py::const_),
&h5::Cce::get_data_subset<Matrix>, py::const_),
py::arg("ell"), py::arg("first_row") = 0, py::arg("num_rows") = 1)
.def("get_data_subset",
py::overload_cast<const std::string&, const std::vector<size_t>&,
size_t, size_t>(&h5::Cce::get_data_subset,
size_t, size_t>(&h5::Cce::get_data_subset<Matrix>,
py::const_),
py::arg("bondi_variable_name"), py::arg("ell"),
py::arg("first_row") = 0, py::arg("num_rows") = 1)
Expand Down
Loading

0 comments on commit e9f4bcf

Please sign in to comment.