Skip to content
This repository was archived by the owner on Feb 26, 2025. It is now read-only.

Retrieve spike time units in SpikePopulation #363

Merged
merged 1 commit into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions include/bbp/sonata/report_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,19 @@ class SONATA_API SpikeReader
*/
Sorting getSorting() const;

/**
* Return the unit of time
*/
std::string getTimeUnits() const;

private:
Population(const std::string& filename, const std::string& populationName);

SpikeTimes spike_times_;
Sorting sorting_ = Sorting::none;
// Use for clamping of user values
double tstart_, tstop_;
std::string time_units_;

void filterNode(Spikes& spikes, const Selection& node_ids) const;
void filterTimestamp(Spikes& spikes, double tstart, double tstop) const;
Expand Down
5 changes: 4 additions & 1 deletion python/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1283,7 +1283,10 @@ PYBIND11_MODULE(_libsonata, m) {
DOC_SPIKEREADER_POP(getSorting))
.def_property_readonly("times",
&SpikeReader::Population::getTimes,
DOC_SPIKEREADER_POP(getTimes));
DOC_SPIKEREADER_POP(getTimes))
.def_property_readonly("time_units",
&SpikeReader::Population::getTimeUnits,
DOC_REPORTREADER_POP(getTimeUnits));
py::class_<SpikeReader>(m, "SpikeReader", DOC(bbp, sonata, SpikeReader))
.def(py::init([](py::object h5_filepath) { return SpikeReader(py::str(h5_filepath)); }),
"h5_filepath"_a)
Expand Down
2 changes: 2 additions & 0 deletions python/generated/docstrings.h
Original file line number Diff line number Diff line change
Expand Up @@ -1324,6 +1324,8 @@ static const char *__doc_bbp_sonata_SpikeReader_Population_getSorting = R"doc(Re

static const char *__doc_bbp_sonata_SpikeReader_Population_getTimes = R"doc(Return (tstart, tstop) of the population)doc";

static const char *__doc_bbp_sonata_SpikeReader_Population_getTimeUnits = R"doc(Return the unit of time)doc";

static const char *__doc_bbp_sonata_SpikeReader_Population_sorting = R"doc()doc";

static const char *__doc_bbp_sonata_SpikeReader_Population_spike_times = R"doc()doc";
Expand Down
1 change: 1 addition & 0 deletions python/tests/test_reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def test_get_spikes_from_population(self):
self.assertEqual(self.test_obj['All'].sorting, "by_time")
self.assertEqual(self.test_obj['spikes1'].sorting, "by_id")
self.assertEqual(self.test_obj['spikes2'].sorting, "none")
self.assertEqual(self.test_obj['spikes2'].time_units, 'ms')
self.assertEqual(self.test_obj['empty'].get(), [])

self.assertEqual(len(self.test_obj['All'].get(node_ids=[])), 0)
Expand Down
5 changes: 5 additions & 0 deletions src/report_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ SpikeReader::Population::Sorting SpikeReader::Population::getSorting() const {
return sorting_;
}

std::string SpikeReader::Population::getTimeUnits() const {
return time_units_;
}

SpikeReader::Population::Population(const std::string& filename,
const std::string& populationName) {
HighFive::File file(filename, HighFive::File::ReadOnly);
Expand All @@ -206,6 +210,7 @@ SpikeReader::Population::Population(const std::string& filename,

pop.getDataSet("node_ids").read(node_ids);
pop.getDataSet("timestamps").read(timestamps);
pop.getDataSet("timestamps").getAttribute("units").read(time_units_);

if (node_ids.size() != timestamps.size()) {
throw SonataError(
Expand Down
7 changes: 5 additions & 2 deletions tests/data/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,13 +204,15 @@ def write_spikes(filepath):
gpop_all = h5f.create_group('/spikes/' + population_names[0])
gpop_all.attrs.create('sorting', data=2, dtype=sorting_type)
timestamps, node_ids = zip(*sorted(zip(timestamps_base, node_ids_base)))
set = gpop_all.create_dataset('timestamps', data=timestamps, dtype=np.double)
dtimestamps = gpop_all.create_dataset('timestamps', data=timestamps, dtype=np.double)
dtimestamps.attrs.create('units', data="ms", dtype=string_dtype)
gpop_all.create_dataset('node_ids', data=node_ids, dtype=np.uint64)

gpop_spikes1 = h5f.create_group('/spikes/' + population_names[1])
gpop_spikes1.attrs.create('sorting', data=1, dtype=sorting_type)
node_ids, timestamps = zip(*sorted(zip(node_ids_base, timestamps_base)))
gpop_spikes1.create_dataset('timestamps', data=timestamps, dtype=np.double)
dtimestamps = gpop_spikes1.create_dataset('timestamps', data=timestamps, dtype=np.double)
dtimestamps.attrs.create('units', data="ms", dtype=string_dtype)
gpop_spikes1.create_dataset('node_ids', data=node_ids, dtype=np.uint64)

gpop_spikes2 = h5f.create_group('/spikes/' + population_names[2])
Expand All @@ -222,6 +224,7 @@ def write_spikes(filepath):
gpop_empty = h5f.create_group('/spikes/' + population_names[3])
gpop_empty.attrs.create('sorting', data=1, dtype=sorting_type)
dtimestamps = gpop_empty.create_dataset('timestamps', data=[], dtype=np.double)
dtimestamps.attrs.create('units', data="ms", dtype=string_dtype)
gpop_empty.create_dataset('node_ids', data=[], dtype=np.uint64)

if __name__ == '__main__':
Expand Down
Binary file modified tests/data/spikes.h5
Binary file not shown.
1 change: 1 addition & 0 deletions tests/test_report_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ TEST_CASE("SpikeReader", "[base]") {
REQUIRE(reader.openPopulation("empty").get() == std::vector<std::pair<uint64_t, double>>{});

REQUIRE(reader.openPopulation("All").getTimes() == std::make_tuple(0.1, 1.3));
REQUIRE(reader.openPopulation("All").getTimeUnits() == "ms");
}

TEST_CASE("SomaReportReader limits", "[base]") {
Expand Down
Loading