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::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()); }