aqnwb 0.1.0
Loading...
Searching...
No Matches
Utils.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <chrono>
5#include <cmath>
6#include <cstdint>
7#include <ctime>
8#include <iomanip>
9#include <regex>
10#include <sstream>
11#include <string>
12
13#include <boost/date_time.hpp>
14#include <boost/endian/conversion.hpp>
15#include <boost/uuid/uuid.hpp>
16#include <boost/uuid/uuid_generators.hpp>
17#include <boost/uuid/uuid_io.hpp>
18
19#include "boost/date_time/c_local_time_adjustor.hpp"
20#include "io/BaseIO.hpp"
21#include "io/hdf5/HDF5IO.hpp"
22
23namespace AQNWB
24{
29static inline std::string generateUuid()
30{
31 boost::uuids::uuid uuid = boost::uuids::random_generator()();
32 std::string uuidStr = boost::uuids::to_string(uuid);
33
34 return uuidStr;
35}
36
41static inline std::string getCurrentTime()
42{
43 // Set up boost time zone adjustment and time facet
44 using local_adj =
45 boost::date_time::c_local_adjustor<boost::posix_time::ptime>;
46 boost::posix_time::time_facet* f = new boost::posix_time::time_facet();
47 f->time_duration_format("%+%H:%M");
48
49 // get local time, utc time, and offset
50 auto now = boost::posix_time::microsec_clock::universal_time();
51 auto utc_now = local_adj::utc_to_local(now);
52 boost::posix_time::time_duration td = utc_now - now;
53
54 // Format the date and time in ISO 8601 format with the UTC offset
55 std::ostringstream oss_offset;
56 oss_offset.imbue(std::locale(oss_offset.getloc(), f));
57 oss_offset << td;
58
59 std::string currentTime = to_iso_extended_string(utc_now);
60 currentTime += oss_offset.str();
61
62 return currentTime;
63}
64
73static inline bool isISO8601Date(const std::string& dateStr)
74{
75 // Define the regex pattern for ISO 8601 extended format with timezone offset
76 // Allow one or more fractional seconds digits
77 const std::string iso8601Pattern =
78 R"(^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+[+-]\d{2}:\d{2}$)";
79 std::regex pattern(iso8601Pattern);
80
81 // Check if the date string matches the regex pattern
82 return std::regex_match(dateStr, pattern);
83}
84
89static inline std::shared_ptr<IO::BaseIO> createIO(const std::string& type,
90 const std::string& filename)
91{
92 if (type == "HDF5") {
93 return std::make_shared<AQNWB::IO::HDF5::HDF5IO>(filename);
94 } else {
95 throw std::invalid_argument("Invalid IO type");
96 }
97}
98
112static inline std::string mergePaths(const std::string& path1,
113 const std::string& path2)
114{
115 std::string result = path1;
116 // Remove trailing "/" from path1
117 while (!result.empty() && result.back() == '/' && result != "/") {
118 result.pop_back();
119 }
120 // Remove leading "/" from path2
121 size_t start = 0;
122 while (start < path2.size() && path2[start] == '/') {
123 start++;
124 }
125 // Get path2 without trailing slashes
126 std::string path2Clean = path2.substr(start);
127 while (!path2Clean.empty() && path2Clean.back() == '/' && path2Clean != "/") {
128 path2Clean.pop_back();
129 }
130 // Append path2 to path1 with a "/" in between
131 if (!result.empty() && !path2Clean.empty()) {
132 result += '/';
133 }
134 result += path2Clean;
135
136 // Remove any potential occurrences of "//" and replace with "/"
137 size_t pos = result.find("//");
138 while (pos != std::string::npos) {
139 result.replace(pos, 2, "/");
140 pos = result.find("//", pos);
141 }
142
143 // Remove trailing "/" from final result if not root path
144 while (!result.empty() && result.back() == '/' && result != "/") {
145 result.pop_back();
146 }
147
148 return result;
149}
150
159static inline void convertFloatToInt16LE(const float* source,
160 void* dest,
161 SizeType numSamples)
162{
163 // TODO - several steps in this function may be unnecessary for our use
164 // case. Consider simplifying the intermediate cast to char and the
165 // final cast to uint16_t.
166 auto maxVal = static_cast<double>(0x7fff);
167 auto intData = static_cast<char*>(dest);
168
169 for (SizeType i = 0; i < numSamples; ++i) {
170 auto clampedValue =
171 std::clamp(maxVal * static_cast<double>(source[i]), -maxVal, maxVal);
172 auto intValue =
173 static_cast<uint16_t>(static_cast<int16_t>(std::round(clampedValue)));
174 intValue = boost::endian::native_to_little(intValue);
175 *reinterpret_cast<uint16_t*>(intData) = intValue;
176 intData += 2; // destBytesPerSample is always 2
177 }
178}
179
186static inline std::unique_ptr<int16_t[]> transformToInt16(
187 SizeType numSamples, float conversion_factor, const float* data)
188{
189 std::unique_ptr<float[]> scaledData = std::make_unique<float[]>(numSamples);
190 std::unique_ptr<int16_t[]> intData = std::make_unique<int16_t[]>(numSamples);
191
192 // copy data and multiply by scaling factor
193 float multFactor = 1.0f / (32767.0f * conversion_factor);
194 std::transform(data,
195 data + numSamples,
196 scaledData.get(),
197 [multFactor](float value) { return value * multFactor; });
198
199 // convert float to int16
200 convertFloatToInt16LE(scaledData.get(), intData.get(), numSamples);
201
202 return intData;
203}
204
205} // namespace AQNWB
AQNWB::Types::SizeType SizeType
Definition Channel.hpp:8
The main namespace for AqNWB.
Definition Channel.hpp:11
static std::unique_ptr< int16_t[]> transformToInt16(SizeType numSamples, float conversion_factor, const float *data)
Method to scale float values and convert to int16 values.
Definition Utils.hpp:186
static void convertFloatToInt16LE(const float *source, void *dest, SizeType numSamples)
Method to convert float values to uint16 values. This method was adapted from JUCE AudioDataConverter...
Definition Utils.hpp:159
static std::string mergePaths(const std::string &path1, const std::string &path2)
Merge two paths into a single path, handling extra trailing and starting "/".
Definition Utils.hpp:112
static bool isISO8601Date(const std::string &dateStr)
Check that a string is formatted in ISO8601 format.
Definition Utils.hpp:73
static std::string generateUuid()
Generates a UUID (Universally Unique Identifier) as a string.
Definition Utils.hpp:29
static std::shared_ptr< IO::BaseIO > createIO(const std::string &type, const std::string &filename)
Factory method to create an IO object.
Definition Utils.hpp:89
static std::string getCurrentTime()
Get the current time in ISO 8601 format with the UTC offset.
Definition Utils.hpp:41