Skip to content

Commit 358d087

Browse files
committed
Implement the initDataSet, actually is 'saveSimData' for updated type: CONSTANT in Hdf5 Recorder
1 parent dec6c20 commit 358d087

File tree

5 files changed

+134
-53
lines changed

5 files changed

+134
-53
lines changed

Simulator/Layouts/Layout.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,12 @@ void Layout::setup()
117117
dist_ = sqrt(dist2_);
118118

119119
// Register variable: vertex locations if need
120-
// Recorder &recorder = Simulator::getInstance().getModel().getRecorder();
121-
// string baseName = "Location";
122-
// string xLocation = "x_" + baseName;
123-
// string yLocation = "y_" + baseName;
124-
// recorder.registerVariable(xLocation, xloc_, Recorder::UpdatedType::CONSTANT);
125-
// recorder.registerVariable(yLocation, yloc_, Recorder::UpdatedType::CONSTANT);
120+
Recorder &recorder = Simulator::getInstance().getModel().getRecorder();
121+
string baseName = "Location";
122+
string xLocation = "x_" + baseName;
123+
string yLocation = "y_" + baseName;
124+
recorder.registerVariable(xLocation, xloc_, Recorder::UpdatedType::CONSTANT);
125+
recorder.registerVariable(yLocation, yloc_, Recorder::UpdatedType::CONSTANT);
126126

127127
// test purpose
128128
// cout << "xloc_: " << &xloc_ << endl;

Simulator/Recorders/Hdf5Recorder.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ void Hdf5Recorder::init()
6666
try {
6767
// Create a new file using the default property lists
6868
resultOut_ = new H5File(resultFileName_, H5F_ACC_TRUNC);
69-
initDataSet();
69+
7070
} catch (FileIException &error) {
7171
cerr << "HDF5 File I/O Exception: " << endl;
7272
error.printErrorStack();
@@ -103,9 +103,23 @@ void Hdf5Recorder::term()
103103
}
104104
}
105105

106-
// Create data spaces and data sets of the hdf5 for recording histories.
107-
void Hdf5Recorder::initDataSet()
106+
// create the dataset for constant variable and store the data to dataset
107+
void Hdf5Recorder::saveSimData(const AllVertices &neurons)
108108
{
109+
// Initialize datasets for constant variables
110+
for (auto &variableInfo : variableTable_) {
111+
if (variableInfo.variableType_ == UpdatedType::CONSTANT) {
112+
// Define dimensions for the constant dataset
113+
hsize_t constantDims[1]
114+
= {static_cast<hsize_t>(variableInfo.variableLocation_.getNumElements())};
115+
DataSpace constantSpace(1, constantDims);
116+
117+
// Create dataset
118+
variableInfo.hdf5DataSet_ = resultOut_->createDataSet(
119+
variableInfo.variableName_, variableInfo.hdf5Datatype_, constantSpace);
120+
variableInfo.captureData();
121+
}
122+
}
109123
}
110124

111125
/// Receives a recorded variable entity from the variable owner class

Simulator/Recorders/Hdf5Recorder.h

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,7 @@ class Hdf5Recorder : public Recorder {
6666

6767
// TODO: No parameters needed (AllVertices &vertices)
6868
/// Writes simulation results to an output destination.
69-
virtual void saveSimData(const AllVertices &neurons) override
70-
{
71-
}
69+
virtual void saveSimData(const AllVertices &neurons) override;
7270

7371
/// Prints out all parameters to logging file.
7472
/// Registered to OperationManager as Operation::printParameters
@@ -93,6 +91,10 @@ class Hdf5Recorder : public Recorder {
9391
{
9492
}
9593

94+
virtual void initDataSet()
95+
{
96+
}
97+
9698
struct singleVariableInfo {
9799
/// the name of each variable
98100
string variableName_;
@@ -127,31 +129,49 @@ class Hdf5Recorder : public Recorder {
127129
if (dataType_ == typeid(uint64_t).name()) {
128130
hdf5Datatype_ = PredType::NATIVE_UINT64;
129131
} else if (dataType_ == typeid(bool).name()) {
130-
hdf5Datatype_ = PredType::NATIVE_UINT8;
132+
hdf5Datatype_ = PredType::NATIVE_INT;
131133
} else if (dataType_ == typeid(int).name()) {
132134
hdf5Datatype_ = PredType::NATIVE_INT;
133-
} else if (dataType_ == typeid(float).name()) {
135+
} else if (dataType_ == typeid(BGFLOAT).name()) {
134136
hdf5Datatype_ = PredType::NATIVE_FLOAT;
135-
} else if (dataType_ == typeid(double).name()) {
136-
hdf5Datatype_ = PredType::NATIVE_DOUBLE;
137137
} else {
138-
//string errorMsg = "Not supported type for type: " + dataType_;
139138
throw runtime_error("Unsupported data type");
140139
}
141140
}
142141

143-
// Creates a dynamic dataset in the HDF5 file
144-
void createDynamicDataset(H5File *resultOut_)
142+
// Method to capture and write data to the HDF5 dataset
143+
void captureData()
145144
{
146-
// Create dataspace with initial size and unlimited max size
147-
hsize_t dims[1] = {static_cast<hsize_t>(variableLocation_.getNumElements())};
148-
hsize_t maxDims[1] = {H5S_UNLIMITED};
149-
DataSpace dataspace(1, dims, maxDims);
150-
151-
// Create dataset
152-
hdf5DataSet_ = resultOut_->createDataSet(variableName_, hdf5Datatype_, dataspace);
153-
154-
std::cout << "Created dataset: " << variableName_ << std::endl;
145+
// Ensure the dataset exists and data can be written
146+
if (variableLocation_.getNumElements() > 0) {
147+
// Prepare the data buffer based on the HDF5 data type
148+
if (hdf5Datatype_ == PredType::NATIVE_FLOAT) {
149+
vector<BGFLOAT> dataBuffer(variableLocation_.getNumElements());
150+
for (int i = 0; i < variableLocation_.getNumElements(); ++i) {
151+
dataBuffer[i] = get<BGFLOAT>(variableLocation_.getElement(i));
152+
}
153+
// Write the data to the dataset
154+
hdf5DataSet_.write(dataBuffer.data(), hdf5Datatype_);
155+
156+
} else if (hdf5Datatype_ == PredType::NATIVE_INT) {
157+
vector<int> dataBuffer(variableLocation_.getNumElements());
158+
for (int i = 0; i < variableLocation_.getNumElements(); ++i) {
159+
dataBuffer[i] = get<int>(variableLocation_.getElement(i));
160+
}
161+
hdf5DataSet_.write(dataBuffer.data(), hdf5Datatype_);
162+
163+
} else if (hdf5Datatype_ == PredType::NATIVE_UINT64) {
164+
vector<uint64_t> dataBuffer(variableLocation_.getNumElements());
165+
for (int i = 0; i < variableLocation_.getNumElements(); ++i) {
166+
dataBuffer[i] = get<uint64_t>(variableLocation_.getElement(i));
167+
}
168+
hdf5DataSet_.write(dataBuffer.data(), hdf5Datatype_);
169+
170+
} else {
171+
// Throw an error if the data type is unsupported
172+
throw runtime_error("Unsupported data type");
173+
}
174+
}
155175
}
156176
};
157177

@@ -170,8 +190,6 @@ class Hdf5Recorder : public Recorder {
170190
}
171191

172192
private:
173-
virtual void initDataSet();
174-
175193
/// Populates Starter neuron matrix based with boolean values based on starterMap state
176194
///@param[in] matrix starter neuron matrix
177195
///@param starterMap Bool vector to reference neuron matrix location from.
@@ -182,7 +200,7 @@ class Hdf5Recorder : public Recorder {
182200

183201
// Member variables for HDF5 datasets
184202
H5File *resultOut_;
185-
DataSet dataSetXloc_;
203+
/*DataSet dataSetXloc_;
186204
DataSet dataSetYloc_;
187205
DataSet dataSetNeuronTypes_;
188206
DataSet dataSetNeuronThresh_;
@@ -204,7 +222,7 @@ class Hdf5Recorder : public Recorder {
204222
const H5std_string nameSimulationEndTime = "simulationEndTime";
205223
const H5std_string nameSpikesProbedNeurons = "spikesProbedNeurons";
206224
const H5std_string nameAttrPNUnit = "attrPNUint";
207-
const H5std_string nameProbedNeurons = "probedNeurons";
225+
const H5std_string nameProbedNeurons = "probedNeurons";*/
208226

209227
// Keep track of where we are in incrementally writing spikes
210228
vector<hsize_t> offsetSpikesProbedNeurons_;

Testing/UnitTesting/Hdf5RecorderTests.cpp

Lines changed: 70 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,42 @@
33
#include "RecordableBase.h"
44
#include "RecordableVector.h"
55
#include "Recorder.h"
6+
#include "VectorMatrix.h"
67
#include "gtest/gtest.h"
78

89
#if defined(HDF5)
910
#include "H5Cpp.h"
1011

12+
// Test case for initializing the Hdf5Recorder
13+
TEST(Hdf5RecorderTest, CreateInstanceSuccess)
14+
{
15+
Recorder *recorder = Hdf5Recorder::Create();
16+
ASSERT_TRUE(recorder != nullptr);
17+
}
18+
19+
// Test case for init() and term()
20+
TEST(Hdf5RecorderTest, Hdf5InitAndTermTest)
21+
{
22+
// Create an instance of Hdf5Recorder with a specific output file name
23+
std::string outputFile = "../Testing/UnitTesting/TestOutput/Hdf5test_output_term.h5";
24+
Hdf5Recorder recorder(outputFile);
25+
recorder.init();
26+
27+
// Ensure the file has been created successfully by the constructor
28+
FILE *f = fopen(outputFile.c_str(), "r");
29+
ASSERT_TRUE(f != NULL);
30+
fclose(f);
31+
32+
// Call the term() method to close the HDF5 file
33+
recorder.term();
34+
35+
// Check if the file can be reopened, indicating it was closed properly
36+
f = fopen(outputFile.c_str(), "r");
37+
bool fileExist = f != NULL;
38+
fclose(f);
39+
ASSERT_TRUE(fileExist);
40+
}
41+
1142
// Unit test for verifying the registerVariable method
1243
TEST(Hdf5RecorderTest, RegisterVariableTest)
1344
{
@@ -34,33 +65,51 @@ TEST(Hdf5RecorderTest, RegisterVariableTest)
3465
ASSERT_EQ(PredType::NATIVE_UINT64, varInfo.hdf5Datatype_);
3566
}
3667

37-
// Test case for initializing the Hdf5Recorder
38-
TEST(Hdf5RecorderTest, CreateInstanceSuccess)
68+
// Define the test case for saving simulation data
69+
TEST(Hdf5RecorderTest, SaveSimDataTest)
3970
{
40-
Recorder *recorder = Hdf5Recorder::Create();
41-
ASSERT_TRUE(recorder != nullptr);
42-
}
71+
// Define a temporary file path for testing
72+
std::string outputFile = "../Testing/UnitTesting/TestOutput/Hdf5test_output_save.h5";
4373

44-
// Test case for init() and term()
45-
TEST(Hdf5RecorderTest, Hdf5InitAndTermTest)
46-
{
47-
// Create an instance of Hdf5Recorder with a specific output file name
48-
std::string outputFile = "../Testing/UnitTesting/TestOutput/Hdf5test_output_term.h5";
74+
// Create an instance of Hdf5Recorder
4975
Hdf5Recorder recorder(outputFile);
5076
recorder.init();
5177

52-
// Ensure the file has been created successfully by the constructor
53-
FILE *f = fopen(outputFile.c_str(), "r");
54-
ASSERT_TRUE(f != NULL);
55-
fclose(f);
78+
// Create and configure EventBuffer for testing
79+
EventBuffer eventBuffer(5); // Initialize with a size that matches the mock data
80+
eventBuffer.insertEvent(1);
81+
eventBuffer.insertEvent(2);
82+
eventBuffer.insertEvent(3);
83+
eventBuffer.insertEvent(4);
84+
eventBuffer.insertEvent(5);
5685

57-
// Call the term() method to close the HDF5 file
58-
recorder.term();
86+
// Register the variable with Hdf5Recorder
87+
recorder.registerVariable("test_var1", eventBuffer, Recorder::UpdatedType::CONSTANT);
5988

60-
// Check if the file can be reopened, indicating it was closed properly
61-
f = fopen(outputFile.c_str(), "r");
62-
bool fileExist = f != NULL;
63-
fclose(f);
64-
ASSERT_TRUE(fileExist);
89+
// Create a unique_ptr to an empty AllVertices object
90+
unique_ptr<AllVertices> vertices = 0;
91+
92+
// Call saveSimData() to write the data to the file
93+
recorder.saveSimData(*vertices);
94+
95+
// Open the HDF5 file and read back the data
96+
H5File file(outputFile, H5F_ACC_RDONLY);
97+
DataSet dataset = file.openDataSet("test_var1");
98+
DataSpace dataspace = dataset.getSpace();
99+
100+
hsize_t num_elements;
101+
dataspace.getSimpleExtentDims(&num_elements, nullptr);
102+
103+
vector<uint64_t> dataBuffer(num_elements);
104+
// Read the data into the buffer
105+
dataset.read(dataBuffer.data(), PredType::NATIVE_UINT64);
106+
107+
// Verify the data matches the expected values
108+
vector<uint64_t> expectedData = {1, 2, 3, 4, 5};
109+
ASSERT_EQ(expectedData.size(), dataBuffer.size());
110+
for (size_t i = 0; i < expectedData.size(); ++i) {
111+
EXPECT_EQ(expectedData[i], dataBuffer[i]);
112+
}
65113
}
114+
66115
#endif // HDF5

build/temp_hdf5_test.h5

1.37 KB
Binary file not shown.

0 commit comments

Comments
 (0)