Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add read tests for TimeSeries , VectorData, Data, ElementIdentifers, Device` #124

Merged
merged 25 commits into from
Jan 11, 2025
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
134fb4b
Add missing offset attriubte for TimeSeries.data
oruebel Jan 9, 2025
d07e053
Add basic unit test for TimeSeries read
oruebel Jan 9, 2025
b91dd24
Add more REQUIRE checks
oruebel Jan 9, 2025
03577da
Add missing TimeSerires.conitnuity field for write. Move timeseries-s…
oruebel Jan 9, 2025
675a8db
Fix spellcheck errors
oruebel Jan 9, 2025
2408a08
Add read test for timestamps.unit and timestamps.interval
oruebel Jan 9, 2025
f88a83d
Support using starting_time and rate with TimeSeries
oruebel Jan 9, 2025
de1f220
Add missing timeseries control and control description. Fix chunking …
oruebel Jan 9, 2025
66e85fd
Move neurodata_type and namespace attributes to Container
oruebel Jan 9, 2025
b3039b3
Merge branch 'add_read' into add_read_field_read_tests
oruebel Jan 10, 2025
f320535
Fix #126 Initiallization of VectorData
oruebel Jan 10, 2025
af9a420
Renamed testBase to testTimeSeries
oruebel Jan 10, 2025
eee8df1
Add initial unit tests for VectorData
oruebel Jan 10, 2025
e6807e2
Add additional unit tests for VectorData
oruebel Jan 10, 2025
aa30d36
Add write/read test for Data
oruebel Jan 10, 2025
e65b6c5
Add write/read test for ElementIdentifiers
oruebel Jan 10, 2025
220bcfa
Add unit test for Device
oruebel Jan 10, 2025
9e5562d
Remove extra comment
oruebel Jan 10, 2025
ec93a96
Remove extra comments
oruebel Jan 10, 2025
324ca6f
Update src/io/hdf5/HDF5IO.cpp
oruebel Jan 10, 2025
cb94d61
Update tests/testTimeSeries.cpp
oruebel Jan 10, 2025
a5b6909
Move test to RegisteredType
oruebel Jan 10, 2025
7c484be
Update writing of control_description
oruebel Jan 10, 2025
f72ca7c
Fix code linting
oruebel Jan 10, 2025
231af52
Add pass-through for control to RecordingContainers::write.. methods
oruebel Jan 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 1 addition & 34 deletions src/io/BaseIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,45 +43,12 @@ BaseIO::~BaseIO() {}

Status BaseIO::createCommonNWBAttributes(const std::string& path,
const std::string& objectNamespace,
const std::string& neurodataType,
const std::string& description)
const std::string& neurodataType)
{
createAttribute(objectNamespace, path, "namespace");
createAttribute(generateUuid(), path, "object_id");
if (neurodataType != "")
createAttribute(neurodataType, path, "neurodata_type");
if (description != "")
createAttribute(description, path, "description");
return Status::Success;
}

Status BaseIO::createDataAttributes(const std::string& path,
const float& conversion,
const float& resolution,
const std::string& unit)
{
createAttribute(BaseDataType::F32,
&conversion,
AQNWB::mergePaths(path, "data"),
"conversion");
createAttribute(BaseDataType::F32,
&resolution,
AQNWB::mergePaths(path, "data"),
"resolution");
createAttribute(unit, path + "/data", "unit");

return Status::Success;
}

Status BaseIO::createTimestampsAttributes(const std::string& path)
{
int interval = 1;
createAttribute(BaseDataType::I32,
static_cast<const void*>(&interval),
path + "/timestamps",
"interval");
createAttribute("seconds", path + "/timestamps", "unit");

return Status::Success;
}

Expand Down
25 changes: 1 addition & 24 deletions src/io/BaseIO.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,34 +446,11 @@ class BaseIO
* @param path The location of the object in the file.
* @param objectNamespace The namespace of the object.
* @param neurodataType The neurodata type of the object.
* @param description The description of the object (default is empty).
* @return The status of the operation.
*/
Status createCommonNWBAttributes(const std::string& path,
const std::string& objectNamespace,
const std::string& neurodataType = "",
const std::string& description = "");

/**
* @brief Convenience function for creating data related attributes.
* @param path The location of the object in the file.
* @param conversion Scalar to multiply each element in data to convert it to
* the specified ‘unit’.
* @param resolution Smallest meaningful difference between values in data.
* @param unit Base unit of measurement for working with the data.
* @return The status of the operation.
*/
Status createDataAttributes(const std::string& path,
const float& conversion,
const float& resolution,
const std::string& unit);

/**
* @brief Convenience function for creating timestamp related attributes.
* @param path The location of the object in the file.
* @return The status of the operation.
*/
Status createTimestampsAttributes(const std::string& path);
const std::string& neurodataType = "");

/**
* @brief Returns true if the file is open.
Expand Down
3 changes: 3 additions & 0 deletions src/io/ReadIO.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ class DataBlockGeneric
*/
std::type_index typeIndex = typeid(void);

/** \brief The base data type for the data block */
IO::BaseDataType baseDataType;

/**
* \brief Default constructor
*/
Expand Down
90 changes: 90 additions & 0 deletions src/io/hdf5/HDF5IO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,9 @@ AQNWB::IO::DataBlockGeneric HDF5IO::readAttribute(
numElements *= v;
}

// Set the base data type for the attribute
result.baseDataType = getBaseDataType(dataType);

// Read the attribute into a vector of the appropriate type
if (dataType.getClass() == H5T_STRING) {
if (dataType.isVariableStr()) {
Expand Down Expand Up @@ -517,6 +520,7 @@ AQNWB::IO::DataBlockGeneric HDF5IO::readDataset(

// Read the dataset into a vector of the appropriate type
H5::DataType dataType = dataset.getDataType();
result.baseDataType = getBaseDataType(dataType);
if (dataType.getClass() == H5T_STRING) {
// Use readStringDataHelper to read string data
result.data =
Expand Down Expand Up @@ -1127,6 +1131,49 @@ H5::DataType HDF5IO::getNativeType(IO::BaseDataType type)
}
}

AQNWB::IO::BaseDataType HDF5IO::getBaseDataType(const H5::DataType& nativeType)
{
if (nativeType == H5::PredType::NATIVE_INT8) {
return IO::BaseDataType(IO::BaseDataType::Type::T_I8);
} else if (nativeType == H5::PredType::NATIVE_INT16) {
return IO::BaseDataType(IO::BaseDataType::Type::T_I16);
} else if (nativeType == H5::PredType::NATIVE_INT32) {
return IO::BaseDataType(IO::BaseDataType::Type::T_I32);
} else if (nativeType == H5::PredType::NATIVE_INT64) {
return IO::BaseDataType(IO::BaseDataType::Type::T_I64);
} else if (nativeType == H5::PredType::NATIVE_UINT8) {
return IO::BaseDataType(IO::BaseDataType::Type::T_U8);
} else if (nativeType == H5::PredType::NATIVE_UINT16) {
return IO::BaseDataType(IO::BaseDataType::Type::T_U16);
} else if (nativeType == H5::PredType::NATIVE_UINT32) {
return IO::BaseDataType(IO::BaseDataType::Type::T_U32);
} else if (nativeType == H5::PredType::NATIVE_UINT64) {
return IO::BaseDataType(IO::BaseDataType::Type::T_U64);
} else if (nativeType == H5::PredType::NATIVE_FLOAT) {
return IO::BaseDataType(IO::BaseDataType::Type::T_F32);
} else if (nativeType == H5::PredType::NATIVE_DOUBLE) {
return IO::BaseDataType(IO::BaseDataType::Type::T_F64);
} else if (nativeType.getClass() == H5T_STRING) {
if (nativeType.isVariableStr()) {
return IO::BaseDataType(IO::BaseDataType::Type::V_STR);
} else {
// Fixed length string: get the size
size_t size = nativeType.getSize();
return IO::BaseDataType(IO::BaseDataType::Type::T_STR, size);
}
} else if (nativeType.getClass() == H5T_ARRAY) {
// Array type: get the base type and size
hid_t nativeTypeId = nativeType.getId();
H5::ArrayType arrayType(nativeTypeId);
H5::DataType baseType = arrayType.getSuper();
hsize_t size = arrayType.getArrayNDims();
return IO::BaseDataType(getBaseDataType(baseType).type, size);
} else {
// Default case: return a 32-bit integer type
return IO::BaseDataType(IO::BaseDataType::Type::T_I32);
}
}

H5::DataType HDF5IO::getH5Type(IO::BaseDataType type)
{
H5::DataType baseType;
Expand Down Expand Up @@ -1177,3 +1224,46 @@ H5::DataType HDF5IO::getH5Type(IO::BaseDataType type)
} else
return baseType;
}

/*
IO::BaseDataType HDF5IO::getBaseType(const H5::DataType &nativeType)
{
if (nativeType == H5::PredType::NATIVE_INT8) {
return IO::BaseDataType(IO::BaseDataType::Type::T_I8);
} else if (nativeType == H5::PredType::NATIVE_INT16) {
return IO::BaseDataType(IO::BaseDataType::Type::T_I16);
} else if (nativeType == H5::PredType::NATIVE_INT32) {
return IO::BaseDataType(IO::BaseDataType::Type::T_I32);
} else if (nativeType == H5::PredType::NATIVE_INT64) {
return IO::BaseDataType(IO::BaseDataType::Type::T_I64);
} else if (nativeType == H5::PredType::NATIVE_UINT8) {
return IO::BaseDataType(IO::BaseDataType::Type::T_U8);
} else if (nativeType == H5::PredType::NATIVE_UINT16) {
return IO::BaseDataType(IO::BaseDataType::Type::T_U16);
} else if (nativeType == H5::PredType::NATIVE_UINT32) {
return IO::BaseDataType(IO::BaseDataType::Type::T_U32);
} else if (nativeType == H5::PredType::NATIVE_UINT64) {
return IO::BaseDataType(IO::BaseDataType::Type::T_U64);
} else if (nativeType == H5::PredType::NATIVE_FLOAT) {
return IO::BaseDataType(IO::BaseDataType::Type::T_F32);
} else if (nativeType == H5::PredType::NATIVE_DOUBLE) {
return IO::BaseDataType(IO::BaseDataType::Type::T_F64);
} else if (nativeType.getClass() == H5T_STRING) {
if (nativeType.isVariableStr()) {
return IO::BaseDataType(IO::BaseDataType::Type::V_STR);
} else {
// Fixed length string: get the size
size_t size = nativeType.getSize();
return IO::BaseDataType(IO::BaseDataType::Type::T_STR, size);
}
} else if (nativeType.getClass() == H5T_ARRAY) {
// Array type: get the base type and size
H5::ArrayType arrayType(nativeType);
H5::DataType baseType = arrayType.getSuper();
hsize_t size = arrayType.getArrayNDims();
return IO::BaseDataType(getBaseType(baseType).type, size);
} else {
// Default case: return a 32-bit integer type
return IO::BaseDataType(IO::BaseDataType::Type::T_I32);
}
}*/
oruebel marked this conversation as resolved.
Show resolved Hide resolved
10 changes: 10 additions & 0 deletions src/io/hdf5/HDF5IO.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,16 @@ class HDF5IO : public BaseIO
*/
static H5::DataType getNativeType(IO::BaseDataType type);

/**
* @brief Returns the BaseDataType for a given HDF5 native data type
*
* This function implements the opposite mapping of getNativeType.
*
* @param nativeType The native data type.
* @return The corresponding BaseDataType
*/
static IO::BaseDataType getBaseDataType(const H5::DataType& nativeType);

/**
* @brief Returns the HDF5 data type for a given base data type.
*
Expand Down
2 changes: 1 addition & 1 deletion src/nwb/NWBFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ Status NWBFile::createFileStructure(const std::string& identifierText,
return Status::Failure;
}
m_io->createCommonNWBAttributes(
m_path, this->getNamespace(), this->getTypeName(), "");
m_path, this->getNamespace(), this->getTypeName());
m_io->createAttribute(AQNWB::SPEC::CORE::version, "/", "nwb_version");
m_io->createGroup("/acquisition");
m_io->createGroup("/analysis");
Expand Down
2 changes: 2 additions & 0 deletions src/nwb/RegisteredType.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
#include <unordered_set>

#include "Types.hpp"
#include "Utils.hpp"
#include "io/BaseIO.hpp"
#include "io/ReadIO.hpp"

namespace AQNWB
{
Expand Down
Loading
Loading