Skip to content

Commit

Permalink
Added some new functions to simplify usage of array libraries as XTen…
Browse files Browse the repository at this point in the history
…sor and Eigen. #96
  • Loading branch information
ihedvall committed Aug 8, 2024
1 parent 4010e33 commit a417ae9
Show file tree
Hide file tree
Showing 12 changed files with 510 additions and 31 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ if(MDF_BUILD_TEST AND VCPKG)
list(APPEND VCPKG_MANIFEST_FEATURES "mdflibtest")
endif()



project(
mdflib
VERSION 2.2
Expand All @@ -47,7 +49,9 @@ if(MDF_BUILD_SHARED_LIB)
add_subdirectory(mdflibrary)
endif()


if(MDF_BUILD_TEST)
include("script/xtensor.cmake")
include("script/googletest.cmake")
enable_testing()
add_subdirectory(mdflib_test)
Expand Down
38 changes: 34 additions & 4 deletions include/mdf/ichannel.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,10 +350,13 @@ class IChannel : public IBlock {
bool GetChannelValue(const std::vector<uint8_t> &record_buffer,
T &dest, uint64_t array_index = 0) const;

/** \brief Fills a record buffer with a channel value.
/** \brief Sets a channel value.
*
* Internally used function that fills a sample record buffer with a channel
* value.
* The function is used when writing MDF files. The function
* take an unscaled channel value and insert it into the channel
* groups record buffer. This record buffer is later saved
* to the MDF file by calling the IChannelGroup::SaveSample()
* function.
* @tparam T Type of value.
* @param value The value to transfer.
* @param valid True if the value is valid.
Expand All @@ -362,6 +365,18 @@ class IChannel : public IBlock {
void SetChannelValue(const T &value, bool valid = true,
uint64_t array_index = 0);

/** \brief Sets channel array values.
*
* The function shall be used to simplify setting channel array
* values. The function assumes that all values are valid. If
* values may be invalid, the SetChannelValue() function should be used.
*
* @tparam T Type of values
* @param values 1-Dimensional list of array values.
*/
template<typename T>
void SetChannelValues(const std::vector<T>& value_array);

/** \brief Internally used function mainly for fetching VLSD index values.
*
* @param record_buffer The sample record buffer.
Expand Down Expand Up @@ -689,6 +704,21 @@ void IChannel::SetChannelValue(const std::string &value, bool valid,

/** \brief Support function that sets a string value to a record buffer. */
template <>
void IChannel::SetChannelValue(const std::vector<uint8_t> &value, bool valid,
void IChannel::SetChannelValue(const std::vector<uint8_t> &values, bool valid,
uint64_t array_index);

template <typename T>
void IChannel::SetChannelValues(const std::vector<T>& values) {
const auto* array = ChannelArray();
const auto array_size = array != nullptr ?
array->NofArrayValues() : 1;
uint64_t index = 0;
for (const T& value : values) {
if (index < array_size) {
SetChannelValue(value, true, index);
}
++index;
}
}

} // namespace mdf
4 changes: 2 additions & 2 deletions include/mdf/ichannelarray.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,13 @@ class IChannelArray : public IBlock {
* The function sets the number of dimensions and each dimension size.
* @param dim_sizes Array of dimension sizes.
*/
virtual void Shape(const std::vector<uint64_t>& dim_sizes) = 0;
virtual void Shape(const std::vector<size_t>& dim_sizes) = 0;

/** \brief Returns the dimension and each dimension size.
*
* @return Array of dimension sizes.
*/
[[nodiscard]] virtual const std::vector<uint64_t>& Shape() const = 0;
[[nodiscard]] virtual const std::vector<size_t>& Shape() const = 0;

/** \brief Returns a dimension size. */
[[nodiscard]] virtual uint64_t DimensionSize(size_t dimension) const = 0;
Expand Down
122 changes: 121 additions & 1 deletion include/mdf/ichannelobserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#include <vector>

#include "mdf/ichannel.h"

#include "mdf/isampleobserver.h"
#include "mdf/mdfhelper.h"

Expand Down Expand Up @@ -73,6 +72,15 @@ class IChannelObserver : public ISampleObserver {

[[nodiscard]] bool IsArray() const; ///< True if this channel is an array channel.

/** \brief Returns a shape vector that describes an array dimension.
*
* This function is used to size an array in an external library. The Eigen
* and XTensor C++ libraries are typical
*
* @return Shape vector that describes an array dimension.
*/
[[nodiscard]] std::vector<size_t> Shape() const;

/** \brief Property interface that defines if the VLSD raw data should be read
* or not.
*
Expand All @@ -96,6 +104,7 @@ class IChannelObserver : public ISampleObserver {
* @return
*/
[[nodiscard]] uint64_t ArraySize() const;

/** \brief Returns the channel value for a sample.
*
* Returns the (unscaled) so-called channel value for a specific sample.
Expand All @@ -108,6 +117,36 @@ class IChannelObserver : public ISampleObserver {
template <typename V>
bool GetChannelValue(uint64_t sample, V& value, uint64_t array_index = 0 ) const;

/** \brief Simple function that returns all non-scaled samples.
*
* Returns all non-scaled sample values. Do not use this function for array
* channels. Use the GetChannelValues() function for array values.
*
* @tparam V Type of values
* @param values The destination sample list.
* @return Returns a list of valid booleans.
*/
template<typename V>
std::vector<bool> GetChannelSamples(std::vector<V>& values) const;

/** \brief Returns a vector of array channel values for a specific sample.
*
* The function is intended to be used on channel arrays. It returns all
* scaled array values for a sample. Note that the valid flags are return
* by the GetValidList() function.
*
* The values vector doesn't need to be sized.
*
* If used on non-array channels, it returns a vector of one values.
* @tparam V Type of value
* @param sample Sample index.
* @param values The destination vector of values.
* @return Returns a vector of valid booleans.
*/
template<typename V>
std::vector<bool> GetChannelValues(uint64_t sample,
std::vector<V>& values) const;

/** \brief Returns the engineering value for a specific value.
*
* Returns the engineering (scaled) value for a specific value.
Expand All @@ -120,6 +159,32 @@ class IChannelObserver : public ISampleObserver {
template <typename V>
bool GetEngValue(uint64_t sample, V& value, uint64_t array_index = 0) const;

/** \brief Simple function that returns all scaled samples.
*
* Returns all scaled sample values. Do not use this function for array
* channels. Use the GetChannelValues() function for array values.
*
* @tparam V Type of values
* @param values The destination sample list.
* @return Returns a list of valid booleans.
*/
template<typename V>
std::vector<bool> GetEngSamples(std::vector<V>& values) const;

/** \brief Returns a vector of array values for a specific sample.
*
* The function is intended to be used on channel arrays. It returns all
* scaled array values for a sample. Note that the valid flags are return
* by the GetValidList
*
* If used on non-array channels, it returns a vector of one values.
* @tparam V Type of value
* @param sample Sample index.
* @return A vector of scaled values.
*/
template<typename V>
std::vector<bool> GetEngValues(uint64_t sample, std::vector<V>& values) const;

/** \brief Support function that convert a sample value to a user friendly string
*
* Function that convert a sample to a user friendly string. For non-array samples,
Expand Down Expand Up @@ -223,6 +288,33 @@ template <>
bool IChannelObserver::GetChannelValue(uint64_t sample,
std::vector<uint8_t>& value, uint64_t array_index) const;

template <typename V>
std::vector<bool> IChannelObserver::GetChannelSamples(
std::vector<V>& values) const {
const uint64_t nof_samples = NofSamples();
std::vector<bool> valid_array(nof_samples, false);
values.resize(nof_samples, {});
uint64_t sample = 0;
for (auto& value : values) {
valid_array[sample] = GetChannelValue(sample, value, 0);
++sample;
}
return valid_array;
}

template <typename V>
std::vector<bool> IChannelObserver::GetChannelValues(uint64_t sample,
std::vector<V>& values) const {
const auto array_size = ArraySize();
std::vector<bool> valid_array(array_size, false);
values.resize(array_size, {});
uint64_t index = 0;
for (auto& value : values) {
valid_array[index] = GetChannelValue(sample, value, index);
++index;
}
return valid_array;
}

template <typename V>
bool IChannelObserver::GetEngValue(uint64_t sample, V& value, uint64_t array_index) const {
Expand Down Expand Up @@ -283,4 +375,32 @@ template <>
bool IChannelObserver::GetEngValue(uint64_t sample,
std::vector<uint8_t>& value,
uint64_t array_index) const;
template <typename V>
std::vector<bool> IChannelObserver::GetEngSamples(
std::vector<V>& values) const {
const uint64_t nof_samples = NofSamples();
std::vector<bool> valid_array(nof_samples, false);
values.resize(nof_samples, {});
uint64_t sample = 0;
for (auto& value : values) {
valid_array[sample] = GetEngValue(sample, value, 0);
++sample;
}
return valid_array;
}

template <typename V>
std::vector<bool> IChannelObserver::GetEngValues(uint64_t sample,
std::vector<V>& values) const {
const auto array_size = ArraySize();
std::vector<bool> valid_array(array_size, false);
values.resize(array_size, {});
uint64_t index = 0;
for (auto& value : values) {
valid_array[index] = GetEngValue(sample, value, index);
++index;
}
return valid_array;
}

} // namespace mdf
3 changes: 3 additions & 0 deletions mdf2csv/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ add_executable(mdf2csv
src/logtoconsole.cpp
src/logtoconsole.h)

target_include_directories(mdf2csv PRIVATE ${XTENSOR_INCLUDE_DIRS})

if(MSVC)
target_compile_definitions(mdf2csv PRIVATE
_WIN32_WINNT=0x0A00
Expand All @@ -35,6 +37,7 @@ endif()

target_link_libraries(mdf2csv PRIVATE mdf)


if(VCPKG)
find_package(expat CONFIG REQUIRED)
target_link_libraries(mdf2csv PRIVATE expat::expat)
Expand Down
1 change: 1 addition & 0 deletions mdf2csv/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ add_executable(test_mdf2csv
../src/logtoconsole.h
testcreatefiles.cpp)


target_include_directories(test_mdf2csv PRIVATE ../src)
target_include_directories(test_mdf2csv PRIVATE ../../include)
target_link_libraries(test_mdf2csv PRIVATE mdf)
Expand Down
8 changes: 7 additions & 1 deletion mdflib/src/ichannelobserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,13 @@ void IChannelObserver::ReadVlsdData(bool read_vlsd_data) {
}
}


std::vector<size_t> IChannelObserver::Shape() const {
const IChannelArray* array = Channel().ChannelArray();
if (array != nullptr) {
return array->Shape();
}
return {1};
}

template <>
bool IChannelObserver::GetChannelValue(uint64_t sample, std::string& value, uint64_t array_index) const {
Expand Down
6 changes: 4 additions & 2 deletions mdflib_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ add_executable(test_mdf
src/testhelper.cpp
src/testchannel.cpp
src/testchannelarray.cpp
src/testchannelarray.h)
src/testchannelarray.h
src/testxtensor.cpp)

target_include_directories(test_mdf PRIVATE ../include ../mdflib/src)

target_include_directories(test_mdf PRIVATE ${XTENSOR_INCLUDE_DIRS})
target_link_libraries(test_mdf PRIVATE xtensor)
if(VCPKG)
find_package(Boost)
target_link_libraries(test_mdf PRIVATE Boost::boost)
Expand Down
Loading

0 comments on commit a417ae9

Please sign in to comment.