Skip to content

Commit

Permalink
Merge pull request #25 from lbl-cbg/add-electrical-series
Browse files Browse the repository at this point in the history
Add electrical series and update recording process
  • Loading branch information
stephprince authored Jun 11, 2024
2 parents a2519a0 + 9ad263f commit 615f993
Show file tree
Hide file tree
Showing 27 changed files with 1,409 additions and 338 deletions.
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,20 @@ include(cmake/variables.cmake)
add_library(
aq-nwb_lib OBJECT
src/BaseIO.cpp
src/Channel.cpp
src/hdf5/HDF5IO.cpp
src/nwb/NWBFile.cpp
src/nwb/NWBRecording.cpp
src/nwb/base/TimeSeries.cpp
src/nwb/device/Device.cpp
src/nwb/ecephys/ElectricalSeries.cpp
src/nwb/file/ElectrodeGroup.cpp
src/nwb/file/ElectrodeTable.cpp
src/nwb/hdmf/base/Data.hpp
src/nwb/hdmf/base/Container.cpp
src/nwb/hdmf/table/DynamicTable.cpp
src/nwb/hdmf/table/ElementIdentifiers.hpp
src/nwb/hdmf/table/VectorData.hpp

)

target_include_directories(
Expand Down
30 changes: 27 additions & 3 deletions src/BaseIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ const BaseDataType BaseDataType::DSTR = BaseDataType(T_STR, DEFAULT_STR_SIZE);
// BaseIO

BaseIO::BaseIO()
: readyToOpen(
true) // TODO - move the readyToOpen flag to the NWBFile building part
: readyToOpen(true)
, opened(false)
{
}
Expand All @@ -56,13 +55,38 @@ Status BaseIO::createCommonNWBAttributes(const std::string& path,
const std::string& description)
{
createAttribute(objectNamespace, path, "namespace");
createAttribute(neurodataType, path, "neurodata_type");
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, path + "/data", "conversion");
createAttribute(BaseDataType::F32, &resolution, 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;
}

// BaseRecordingData

BaseRecordingData::BaseRecordingData() {}
Expand Down
39 changes: 37 additions & 2 deletions src/BaseIO.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,9 +268,30 @@ class BaseIO
*/
Status createCommonNWBAttributes(const std::string& path,
const std::string& objectNamespace,
const std::string& neurodataType,
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.
* @param interval Value is '1'
* @return The status of the operation.
*/
Status createTimestampsAttributes(const std::string& path);
/**
* @brief Returns true if the file is open.
* @return True if the file is open, false otherwise.
Expand Down Expand Up @@ -359,11 +380,25 @@ class BaseRecordingData
const BaseDataType& type,
const void* data) = 0;

/**
* @brief Writes a row of data in a 2D block.
* @param xDataSize The size of the data row in the x dimension (samples).
* @param yPosition The position of the data row in the y dimension
* (channels).
* @param type The data type of the elements in the data block.
* @param data A pointer to the data block.
* @return The status of the write operation.
*/
virtual Status writeDataRow(const SizeType& xDataSize,
const SizeType& yPos,
const BaseDataType& type,
const void* data) = 0;

protected:
/**
* @brief The current position in the x dimension.
*/
int xPos;
SizeType xPos;

/**
* @brief The size of the data block in each dimension.
Expand Down
41 changes: 41 additions & 0 deletions src/Channel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <string>

#include "Channel.hpp"

using namespace AQNWB;

Channel::Channel(const std::string name,
const std::string groupName,
const SizeType localIndex,
const SizeType globalIndex,
const float conversion,
const float samplingRate,
const float bitVolts,
const std::array<float, 3> position)
: name(name)
, groupName(groupName)
, localIndex(localIndex)
, globalIndex(globalIndex)
, position(position)
, conversion(conversion)
, samplingRate(samplingRate)
, bitVolts(bitVolts)
{
}

Channel::~Channel() {}

float Channel::getConversion() const
{
return bitVolts / conversion;
}

float Channel::getSamplingRate() const
{
return samplingRate;
}

float Channel::getBitVolts() const
{
return bitVolts;
}
95 changes: 95 additions & 0 deletions src/Channel.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#pragma once

#include <array>
#include <string>

#include "Types.hpp"

using SizeType = AQNWB::Types::SizeType;

namespace AQNWB
{
/**
* @brief Class for storing acquisition system channel information.
*/
class Channel
{
public:
/**
* @brief Constructor.
*/
Channel(const std::string name,
const std::string groupName,
const SizeType localIndex,
const SizeType globalIndex,
const float conversion = 1e6f, // uV to V
const float samplingRate = 30000.f, // placeholder
const float bitVolts = 0.000002f, // least significant bit needed to
// convert 16-bit int to volts
// currently a placeholder
const std::array<float, 3> position = {0.f, 0.f, 0.f});

/**
* @brief Destructor
*/
~Channel();

/**
* @brief Getter for conversion factor
* @return The conversion value.
*/
float getConversion() const;

/**
* @brief Getter for samplingRate
* @return The samplingRate value.
*/
float getSamplingRate() const;
/**
* @brief Getter for bitVolts
* @return The bitVolts value.
*/
float getBitVolts() const;

/**
* @brief Name of the channel.
*/
std::string name;

/**
* @brief Name of the array group the channel belongs to.
*/
std::string groupName;

/**
* @brief Index of channel within the recording array.
*/
SizeType localIndex;

/**
* @brief Index of channel across the recording system.
*/
SizeType globalIndex;

/**
* @brief Coordinates of channel (x, y, z) within the recording array.
*/
std::array<float, 3> position;

private:
/**
* @brief Conversion factor.
*/
float conversion;

/**
* @brief Sampling rate of the channel.
*/
float samplingRate;

/**
* @brief floating point value of microvolts per bit
*/
float bitVolts;
};
} // namespace AQNWB
10 changes: 10 additions & 0 deletions src/Types.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
#pragma once

#include <vector>
#include <cstddef>

namespace AQNWB
{

// Forward declaration of Channel
class Channel;

/**
* @brief Provides definitions for various types used in the project.
*/
Expand All @@ -28,5 +33,10 @@ class Types
* @brief Alias for an array of size types used in the project.
*/
using SizeArray = std::vector<size_t>;

/**
* @brief Alias for a group of channels.
*/
using ChannelGroup = std::vector<Channel>;
};
} // namespace AQNWB
16 changes: 16 additions & 0 deletions src/Utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

#include "BaseIO.hpp"
#include "boost/date_time/c_local_time_adjustor.hpp"
#include "hdf5/HDF5IO.hpp"

namespace AQNWB
{
Expand Down Expand Up @@ -51,4 +53,18 @@ inline std::string getCurrentTime()

return currentTime;
}

/**
* @brief Factory method to create an IO object.
* @return A pointer to a BaseIO object
*/
inline std::unique_ptr<BaseIO> createIO(const std::string& type,
const std::string& filename)
{
if (type == "HDF5") {
return std::make_unique<HDF5::HDF5IO>(filename);
} else {
throw std::invalid_argument("Invalid IO type");
}
}
} // namespace AQNWB
Loading

0 comments on commit 615f993

Please sign in to comment.