void BaseTestReadOnly::testRead() { File file = File::open("test_read_only.h5", FileMode::ReadOnly); Section section = file.getSection(section_id); Block block = file.getBlock(block_id); DataArray data_array = block.getDataArray(data_array_id); Dimension dim = data_array.getDimension(dim_index); SampledDimension dim_sampled = data_array.getDimension(dim_sampled_index).asSampledDimension(); RangeDimension dim_range = data_array.getDimension(dim_range_index).asRangeDimension(); SetDimension dim_set = data_array.getDimension(dim_set_index).asSetDimension(); Tag tag = block.getTag(tag_id); MultiTag mtag = block.getMultiTag(mtag_id); Feature feature = tag.getFeature(feature_id); Property property = section.getProperty(property_id); // TODO use assertions here s << block.id() << block.name(); s << data_array.id() << data_array.name(); s << tag.id() << tag.name(); s << mtag.id() << mtag.name(); s << feature.id(); s << property.id() << property.name(); s << dim.index(); s << dim_sampled.index(); s << dim_range.index(); s << dim_set.index(); file.close(); }
void BaseTestReadOnly::init(nix::File &file) { startup_time = time(NULL); std::vector<nix::Value> values = { nix::Value(1.0), nix::Value(2.0), nix::Value(-99.99) }; std::vector<double> ticks = {1.0, 2.0, 3.4, 42.0}; Section section = file.createSection("foo_section", "metadata"); Block block = file.createBlock("block_one", "dataset"); DataArray positions = block.createDataArray("positions_DataArray", "dataArray", DataType::Double, NDSize({ 0, 0 })); DataArray data_array = block.createDataArray("array_one", "testdata", nix::DataType::Double, nix::NDSize({ 0, 0, 0 })); Dimension dim = data_array.appendSampledDimension(3.14); SampledDimension dim_sampled = data_array.appendSampledDimension(3.14); RangeDimension dim_range = data_array.appendRangeDimension(ticks); SetDimension dim_set = data_array.appendSetDimension(); Tag tag = block.createTag("featureTest", "Test", {0.0, 2.0, 3.4}); MultiTag mtag = block.createMultiTag("tag_one", "test_tag", positions); Feature feature = tag.createFeature(data_array, nix::LinkType::Tagged); Property property = section.createProperty("doubleProperty", values); section_id = section.id(); feature_id = feature.id(); tag_id = tag.id(); mtag_id = mtag.id(); property_id = property.id(); block_id = block.id(); data_array_id = data_array.id(); dim_index = dim.index(); dim_sampled_index = dim_sampled.index(); dim_range_index = dim_range.index(); dim_set_index = dim_set.index(); file.close(); }
void BaseTestDataAccess::testMultiTagUnitSupport() { std::vector<std::string> valid_units{"none","ms","s"}; std::vector<std::string> invalid_units{"mV", "Ohm", "muV"}; MultiTag testTag = block.createMultiTag("test", "testTag", multi_tag.positions()); testTag.units(valid_units); testTag.addReference(data_array); CPPUNIT_ASSERT_NO_THROW(util::retrieveData(testTag, 0, 0)); testTag.units(none); CPPUNIT_ASSERT_NO_THROW(util::retrieveData(testTag, 0, 0)); testTag.units(invalid_units); CPPUNIT_ASSERT_THROW(util::retrieveData(testTag, 0, 0), nix::IncompatibleDimensions); }
boost::optional<DataArray> getExtents(MultiTag& dt) { DataArray da = dt.extents(); if (da) return boost::optional<DataArray>(da); else return boost::none; }
void TestBlock::testMultiTagAccess() { vector<string> names = { "tag_a", "tag_b", "tag_c", "tag_d", "tag_e" }; // create a valid positions data array below typedef boost::multi_array<double, 3>::index index; DataArray positions = block.createDataArray("array_one", "testdata", DataType::Double, nix::NDSize({ 3, 4, 2 })); boost::multi_array<double, 3> A(boost::extents[3][4][2]); int values = 0; for(index i = 0; i != 3; ++i) for(index j = 0; j != 4; ++j) for(index k = 0; k != 2; ++k) A[i][j][k] = values++; positions.setData(A); CPPUNIT_ASSERT(block.multiTagCount() == 0); CPPUNIT_ASSERT(block.multiTags().size() == 0); CPPUNIT_ASSERT(block.getMultiTag("invalid_id") == false); vector<string> ids; for (auto it = names.begin(); it != names.end(); it++) { MultiTag tag = block.createMultiTag(*it, "segment", positions); CPPUNIT_ASSERT(tag.name() == *it); ids.push_back(tag.id()); } CPPUNIT_ASSERT_THROW(block.createMultiTag(names[0], "segment", positions), DuplicateName); CPPUNIT_ASSERT(block.multiTagCount() == names.size()); CPPUNIT_ASSERT(block.multiTags().size() == names.size()); for (auto it = ids.begin(); it != ids.end(); it++) { MultiTag tag = block.getMultiTag(*it); CPPUNIT_ASSERT(block.hasMultiTag(*it) == true); CPPUNIT_ASSERT(tag.id() == *it); block.deleteMultiTag(*it); } CPPUNIT_ASSERT(block.multiTagCount() == 0); CPPUNIT_ASSERT(block.multiTags().size() == 0); CPPUNIT_ASSERT(block.getMultiTag("invalid_id") == false); }
DataView retrieveFeatureData(const MultiTag &tag, size_t position_index, size_t feature_index) { if (tag.featureCount() == 0) { throw nix::OutOfBounds("There are no features associated with this tag!", 0); } if (feature_index >= tag.featureCount()) { throw nix::OutOfBounds("Feature index out of bounds.", 0); } Feature feat = tag.getFeature(feature_index); DataArray data = feat.data(); if (data == nix::none) { throw nix::UninitializedEntity(); //return NDArray(nix::DataType::Float,{0}); } if (feat.linkType() == nix::LinkType::Tagged) { NDSize offset, count; getOffsetAndCount(tag, data, position_index, offset, count); if (!positionAndExtentInData(data, offset, count)) { throw nix::OutOfBounds("Requested data slice out of the extent of the Feature!", 0); } DataView io = DataView(data, count, offset); return io; } else if (feat.linkType() == nix::LinkType::Indexed) { //FIXME does the feature data to have a setdimension in the first dimension for the indexed case? //For now it will just be a slice across the first dim. if (position_index > data.dataExtent()[0]){ throw nix::OutOfBounds("Position is larger than the data stored in the feature.", 0); } NDSize offset(data.dataExtent().size(), 0); offset[0] = position_index; NDSize count(data.dataExtent()); count[0] = 1; if (!positionAndExtentInData(data, offset, count)) { throw nix::OutOfBounds("Requested data slice out of the extent of the Feature!", 0); } DataView io = DataView(data, count, offset); return io; } // FIXME is this expected behavior? In the untagged case all data is returned NDSize offset(data.dataExtent().size(), 0); DataView io = DataView(data, data.dataExtent(), offset); return io; }
Result validate(const MultiTag &multi_tag) { Result result_base = validate_entity_with_sources(multi_tag); Result result = validator({ must(multi_tag, &MultiTag::positions, notFalse(), "positions are not set!"), // check units for validity could(multi_tag, &MultiTag::units, notEmpty(), { must(multi_tag, &MultiTag::units, isValidUnit(), "Some of the units in tag are invalid: not an atomic SI. Note: So far composite SI units are not supported!"), must(multi_tag, &MultiTag::references, tagUnitsMatchRefsUnits(multi_tag.units()), "Some of the referenced DataArrays' dimensions have units that are not convertible to the units set in tag. Note: So far composite SI units are not supported!")}), // check positions & extents could(multi_tag, &MultiTag::extents, notFalse(), { must(multi_tag, &MultiTag::positions, extentsMatchPositions(multi_tag.extents()), "Number of entries in positions and extents do not match!") }), could(multi_tag, &MultiTag::references, notEmpty(), { could(multi_tag, &MultiTag::extents, notFalse(), { must(multi_tag, &MultiTag::extents, extentsMatchRefs(multi_tag.references()), "number of entries (in 2nd dim) in extents does not match number of dimensions in all referenced DataArrays!") }), must(multi_tag, &MultiTag::positions, positionsMatchRefs(multi_tag.references()), "number of entries (in 2nd dim) in positions does not match number of dimensions in all referenced DataArrays!") }) }); return result.concat(result_base); }
DataView retrieveData(const MultiTag &tag, size_t position_index, size_t reference_index) { DataArray positions = tag.positions(); DataArray extents = tag.extents(); vector<DataArray> refs = tag.references(); if (refs.size() == 0) { // Do I need this? throw nix::OutOfBounds("There are no references in this tag!", 0); } if (position_index >= positions.dataExtent()[0] || (extents && position_index >= extents.dataExtent()[0])) { throw nix::OutOfBounds("Index out of bounds of positions or extents!", 0); } if (!(reference_index < tag.referenceCount())) { throw nix::OutOfBounds("Reference index out of bounds.", 0); } size_t dimension_count = refs[reference_index].dimensionCount(); if (positions.dataExtent().size() == 1 && dimension_count != 1) { throw nix::IncompatibleDimensions("Number of dimensions in position or extent do not match dimensionality of data", "util::retrieveData"); } else if (positions.dataExtent().size() > 1) { if (positions.dataExtent()[1] > dimension_count || (extents && extents.dataExtent()[1] > dimension_count)) { throw nix::IncompatibleDimensions("Number of dimensions in position or extent do not match dimensionality of data", "util::retrieveData"); } } NDSize offset, count; getOffsetAndCount(tag, refs[reference_index], position_index, offset, count); if (!positionAndExtentInData(refs[reference_index], offset, count)) { throw nix::OutOfBounds("References data slice out of the extent of the DataArray!", 0); } DataView io = DataView(refs[reference_index], count, offset); return io; }
void BaseTestMultiTag::testCreateRemove() { std::vector<std::string> ids; ndsize_t count = block.multiTagCount(); const char *names[5] = { "tag_a", "tag_b", "tag_c", "tag_d", "tag_e" }; for (int i = 0; i < 5; i++) { std::string type = "Event"; MultiTag dt1 = block.createMultiTag(names[i], type, positions); MultiTag dt2 = block.getMultiTag(dt1.id()); ids.push_back(dt1.id()); std::stringstream errmsg; errmsg << "Error while accessing multiTag: dt1.id() = " << dt1.id() << " / dt2.id() = " << dt2.id(); CPPUNIT_ASSERT_MESSAGE(errmsg.str(), dt1.id().compare(dt2.id()) == 0); } std::stringstream errmsg2; errmsg2 << "Error creating MultiTags. Counts do not match!"; CPPUNIT_ASSERT_MESSAGE(errmsg2.str(), block.multiTagCount() == (count+5)); CPPUNIT_ASSERT_THROW(block.createMultiTag(names[4], "test", positions), DuplicateName); for (size_t i = 0; i < ids.size(); i++) { block.deleteMultiTag(ids[i]); } std::stringstream errmsg1; errmsg1 << "Error while removing multiTags!"; CPPUNIT_ASSERT_MESSAGE(errmsg1.str(), block.multiTagCount() == count); DataArray a; MultiTag mtag; CPPUNIT_ASSERT_THROW(mtag = block.createMultiTag("test", "test", a), nix::UninitializedEntity); mtag = block.createMultiTag("test", "test", positions); mtag.extents(positions); CPPUNIT_ASSERT_THROW(mtag.positions(a), UninitializedEntity); CPPUNIT_ASSERT(mtag.extents().id() == positions.id()); CPPUNIT_ASSERT_NO_THROW(mtag.extents(a)); CPPUNIT_ASSERT(!mtag.extents()); }
void setUnits(MultiTag& dt, const std::vector<std::string>& units) { if (!units.empty()) dt.units(units); else dt.units(boost::none); }
bool Group::removeMultiTag(const MultiTag &multi_tag) { if (!util::checkEntityInput(multi_tag, false)) { return false; } return backend()->removeMultiTag(multi_tag.id()); }
boost::optional<Feature> getFeatureById(const MultiTag& st, const std::string& id) { Feature f = st.getFeature(id); return f ? boost::optional<Feature>(f) : boost::none; }
boost::optional<DataArray> getReferenceByPos(const MultiTag& st, size_t index) { DataArray da = st.getReference(index); return da ? boost::optional<DataArray>(da) : boost::none; }
void getOffsetAndCount(const MultiTag &tag, const DataArray &array, size_t index, NDSize &offsets, NDSize &counts) { DataArray positions = tag.positions(); DataArray extents = tag.extents(); NDSize position_size, extent_size; size_t dimension_count = array.dimensionCount(); if (positions) { position_size = positions.dataExtent(); } if (extents) { extent_size = extents.dataExtent(); } if (!positions || index >= position_size[0]) { throw nix::OutOfBounds("Index out of bounds of positions!", 0); } if (extents && index >= extent_size[0]) { throw nix::OutOfBounds("Index out of bounds of positions or extents!", 0); } if (position_size.size() == 1 && dimension_count != 1) { throw nix::IncompatibleDimensions("Number of dimensions in positions does not match dimensionality of data", "util::getOffsetAndCount"); } if (position_size.size() > 1 && position_size[1] > dimension_count) { throw nix::IncompatibleDimensions("Number of dimensions in positions does not match dimensionality of data", "util::getOffsetAndCount"); } if (extents && extent_size.size() > 1 && extent_size[1] > dimension_count) { throw nix::IncompatibleDimensions("Number of dimensions in extents does not match dimensionality of data", "util::getOffsetAndCount"); } NDSize temp_offset = NDSize{static_cast<NDSize::value_type>(index), static_cast<NDSize::value_type>(0)}; NDSize temp_count{static_cast<NDSize::value_type>(1), static_cast<NDSize::value_type>(dimension_count)}; vector<double> offset; positions.getData(offset, temp_count, temp_offset); NDSize data_offset(dimension_count, static_cast<size_t>(0)); NDSize data_count(dimension_count, static_cast<size_t>(1)); vector<string> units = tag.units(); for (size_t i = 0; i < offset.size(); ++i) { Dimension dimension = array.getDimension(i+1); string unit = "none"; if (i <= units.size() && units.size() > 0) { unit = units[i]; } data_offset[i] = positionToIndex(offset[i], unit, dimension); } if (extents) { vector<double> extent; extents.getData(extent, temp_count, temp_offset); for (size_t i = 0; i < extent.size(); ++i) { Dimension dimension = array.getDimension(i+1); string unit = "none"; if (i <= units.size() && units.size() > 0) { unit = units[i]; } ndsize_t c = positionToIndex(offset[i] + extent[i], unit, dimension) - data_offset[i]; data_count[i] = (c > 1) ? c : 1; } } offsets = data_offset; counts = data_count; }
void setExtents(MultiTag& dt, const boost::optional<DataArray>& data) { if (data) dt.extents(*data); else dt.extents(boost::none); }
boost::optional<DataArray> getReferenceById(const MultiTag& st, const std::string& id) { DataArray da = st.getReference(id); return da ? boost::optional<DataArray>(da) : boost::none; }
void BaseTestMultiTag::testUnits() { MultiTag dt = block.createMultiTag("TestMultiTag1", "Tag", positions); std::vector<std::string> valid_units = {"mV", "cm", "m^2"}; std::vector<std::string> invalid_units = {"mV", "haha", "qm^2"}; std::vector<std::string> insane_units = {"muV ", " muS"}; CPPUNIT_ASSERT_NO_THROW(dt.units(valid_units)); CPPUNIT_ASSERT(dt.units().size() == valid_units.size()); std::vector<std::string> retrieved_units = dt.units(); for (size_t i = 0; i < retrieved_units.size(); i++) { CPPUNIT_ASSERT(retrieved_units[i] == valid_units[i]); } dt.units(none); CPPUNIT_ASSERT(dt.units().size() == 0); CPPUNIT_ASSERT_THROW(dt.units(invalid_units), InvalidUnit); CPPUNIT_ASSERT(dt.units().size() == 0); dt.units(insane_units); retrieved_units = dt.units(); CPPUNIT_ASSERT(retrieved_units.size() == 2); CPPUNIT_ASSERT(retrieved_units[0] == "uV"); CPPUNIT_ASSERT(retrieved_units[1] == "uS"); block.deleteMultiTag(dt.id()); }
Feature createNewFeature(MultiTag& dt, const DataArray &data, LinkType link_type) { Feature f = dt.createFeature(data, link_type); return f; }
void BaseTestMultiTag::testReferences(){ DataArray da_1 = block.createDataArray("TestReference 1", "Reference", DataType::Double, NDSize({ 0 })); DataArray da_2 = block.createDataArray("TestReference 2", "Reference", DataType::Double, NDSize({ 0 })); DataArray a; MultiTag dt = block.createMultiTag("TestMultiTag1", "Tag", positions); CPPUNIT_ASSERT_THROW(dt.getReference(42), OutOfBounds); CPPUNIT_ASSERT(!dt.hasReference(a)); std::stringstream counterrmsg; counterrmsg << "BaseTestMultiTag::testReference: Counts do not match!"; CPPUNIT_ASSERT_MESSAGE(counterrmsg.str(), dt.referenceCount() == 0); dt.addReference(da_1); dt.addReference(da_2); CPPUNIT_ASSERT_THROW(dt.addReference(a), UninitializedEntity); CPPUNIT_ASSERT_THROW(dt.removeReference(a), UninitializedEntity); CPPUNIT_ASSERT_MESSAGE(counterrmsg.str(), dt.referenceCount() == 2); CPPUNIT_ASSERT(dt.hasReference(da_1)); CPPUNIT_ASSERT(dt.hasReference(da_2)); std::stringstream haserrmsg; haserrmsg << "BaseTestMultiTag::testReference: Has method did not work!"; CPPUNIT_ASSERT_MESSAGE(haserrmsg.str(), dt.hasReference(da_1.id())); CPPUNIT_ASSERT_MESSAGE(haserrmsg.str(), dt.hasReference(da_1.name())); DataArray ref1 = dt.getReference(da_1.id()); std::stringstream retrieveerrmsg; retrieveerrmsg << "BaseTestMultiTag::testReference: Retrieval did not work!"; CPPUNIT_ASSERT_MESSAGE(retrieveerrmsg.str(), ref1.id() == da_1.id()); DataArray ref2 = dt.getReference(da_1.name()); retrieveerrmsg << "BaseTestMultiTag::testReference: Retrieval by name did not work!"; CPPUNIT_ASSERT_MESSAGE(retrieveerrmsg.str(), ref2.id() == da_1.id()); std::vector<DataArray> arrays = dt.references(); CPPUNIT_ASSERT_MESSAGE(retrieveerrmsg.str(), arrays.size() == 2); std::stringstream hasReferrmsg; hasReferrmsg << "BaseTestMultiTag::testReference: hadReference did not work!"; CPPUNIT_ASSERT_MESSAGE(hasReferrmsg.str(), dt.hasReference(da_1.id())); CPPUNIT_ASSERT_MESSAGE(hasReferrmsg.str(), dt.hasReference(da_2.id())); std::stringstream delReferrmsg; delReferrmsg << "BaseTestMultiTag::testReference: removeReference did not work!"; dt.removeReference(da_1.id()); CPPUNIT_ASSERT_MESSAGE(delReferrmsg.str(), dt.referenceCount() == 1); dt.removeReference("NONEXISTENT"); CPPUNIT_ASSERT_MESSAGE(delReferrmsg.str(), dt.referenceCount() == 1); dt.removeReference(da_2.name()); CPPUNIT_ASSERT_MESSAGE(delReferrmsg.str(), dt.referenceCount() == 0); dt.addReference(da_1); CPPUNIT_ASSERT(dt.referenceCount() == 1); CPPUNIT_ASSERT_NO_THROW(dt.removeReference(da_1)); CPPUNIT_ASSERT(dt.referenceCount() == 0); // delete data arrays std::vector<std::string> ids = {da_1.id(), da_2.id()}; block.deleteDataArray(da_1.id()); block.deleteDataArray(da_2.id()); // check if references are gone too! CPPUNIT_ASSERT(dt.referenceCount() == 0); CPPUNIT_ASSERT(!dt.hasReference(ids[0])); CPPUNIT_ASSERT(!dt.hasReference(ids[1])); block.deleteMultiTag(dt.id()); }
boost::optional<Feature> getFeatureByPos(const MultiTag& st, size_t index) { Feature f = st.getFeature(index); return f ? boost::optional<Feature>(f) : boost::none; }
void Group::addMultiTag(const MultiTag &multi_tag) { if (!util::checkEntityInput(multi_tag)) { throw UninitializedEntity(); } backend()->addMultiTag(multi_tag.id()); }