Skip to content

Commit

Permalink
Retrieve spike time units in SpikePopulation (#363)
Browse files Browse the repository at this point in the history
  • Loading branch information
jorblancoa authored Jul 24, 2024
1 parent 919be1f commit 5c5e582
Show file tree
Hide file tree
Showing 8 changed files with 24 additions and 3 deletions.
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

0 comments on commit 5c5e582

Please sign in to comment.