From 973343a01931575f39843dbd7aebfdc770370512 Mon Sep 17 00:00:00 2001 From: kyle-cochran Date: Mon, 9 Oct 2023 16:45:24 -0700 Subject: [PATCH] feat: add functions to extract multiple subsets at once. (#234) * feat: add functions to State and CoordinatesBroker to extract multiple subsets at once. * style: missed a couple of doc-string newlines * feat: add bindings (and fix typo bug * Apply suggestions from code review Co-authored-by: Vishwa Shah --------- Co-authored-by: Vishwa Shah --- .../Trajectory/State.cpp | 11 +- .../Trajectory/State/CoordinatesBroker.cpp | 8 ++ .../state/test_coordinates_broker.py | 21 ++- bindings/python/test/trajectory/test_state.py | 11 +- .../Astrodynamics/Trajectory/State.hpp | 124 ++++++++++++++++-- .../Trajectory/State/CoordinatesBroker.hpp | 79 ++++++----- .../Astrodynamics/Trajectory/State.cpp | 9 +- .../Trajectory/State/CoordinatesBroker.cpp | 25 ++++ .../Astrodynamics/Trajectory/State.test.cpp | 22 ++++ .../State/CoordinatesBroker.test.cpp | 52 ++++++++ 10 files changed, 307 insertions(+), 55 deletions(-) diff --git a/bindings/python/src/OpenSpaceToolkitAstrodynamicsPy/Trajectory/State.cpp b/bindings/python/src/OpenSpaceToolkitAstrodynamicsPy/Trajectory/State.cpp index ccbc54b33..4cb07dd22 100644 --- a/bindings/python/src/OpenSpaceToolkitAstrodynamicsPy/Trajectory/State.cpp +++ b/bindings/python/src/OpenSpaceToolkitAstrodynamicsPy/Trajectory/State.cpp @@ -49,7 +49,16 @@ inline void OpenSpaceToolkitAstrodynamicsPy_Trajectory_State(pybind11::module& a .def("get_coordinates_subsets", &State::getCoordinatesSubsets) .def("get_frame", &State::getFrame) - .def("extract_coordinates", &State::extractCoordinates, arg("coordinates_subset")) + .def( + "extract_coordinates", + overload_cast&>(&State::extractCoordinates, const_), + arg("coordinates_subset") + ) + .def( + "extract_coordinates", + overload_cast>&>(&State::extractCoordinates, const_), + arg("coordinates_subsets") + ) .def("in_frame", &State::inFrame, arg("frame")) diff --git a/bindings/python/src/OpenSpaceToolkitAstrodynamicsPy/Trajectory/State/CoordinatesBroker.cpp b/bindings/python/src/OpenSpaceToolkitAstrodynamicsPy/Trajectory/State/CoordinatesBroker.cpp index 96c57df09..8877f6257 100644 --- a/bindings/python/src/OpenSpaceToolkitAstrodynamicsPy/Trajectory/State/CoordinatesBroker.cpp +++ b/bindings/python/src/OpenSpaceToolkitAstrodynamicsPy/Trajectory/State/CoordinatesBroker.cpp @@ -45,6 +45,14 @@ inline void OpenSpaceToolkitAstrodynamicsPy_Trajectory_State_CoordinatesBroker(p arg("coordinates"), arg("coordinates_subset") ) + .def( + "extract_coordinates", + overload_cast>&>( + &CoordinatesBroker::extractCoordinates, const_ + ), + arg("coordinates"), + arg("coordinates_subsets") + ) ; } diff --git a/bindings/python/test/trajectory/state/test_coordinates_broker.py b/bindings/python/test/trajectory/state/test_coordinates_broker.py index 7383e4db7..c709d5203 100644 --- a/bindings/python/test/trajectory/state/test_coordinates_broker.py +++ b/bindings/python/test/trajectory/state/test_coordinates_broker.py @@ -57,15 +57,22 @@ def test_has_subset( ): assert coordinates_broker.has_subset(coordinates_subsets[0]) - def extract_coordinates( + def test_extract_coordinates( self, coordinates_broker: CoordinatesBroker, coordinates: list[float], coordinates_subsets: list[CoordinatesSubset], ): - assert coordinates_broker.extract_coordinates( - coordinates, coordinates_subsets[0] - ) == [1.0, 2.0] - assert coordinates_broker.extract_coordinates( - coordinates, coordinates_subsets[1] - ) == [3.0, 4.0, 5.0] + assert ( + coordinates_broker.extract_coordinates(coordinates, coordinates_subsets[0]) + == [1.0, 2.0] + ).all() + assert ( + coordinates_broker.extract_coordinates(coordinates, coordinates_subsets[1]) + == [3.0, 4.0, 5.0] + ).all() + + assert ( + coordinates_broker.extract_coordinates(coordinates, coordinates_subsets) + == [1.0, 2.0, 3.0, 4.0, 5.0] + ).all() diff --git a/bindings/python/test/trajectory/test_state.py b/bindings/python/test/trajectory/test_state.py index 81f2ed574..fef8a8160 100644 --- a/bindings/python/test/trajectory/test_state.py +++ b/bindings/python/test/trajectory/test_state.py @@ -128,7 +128,14 @@ def test_extract_coordinates( ): position_coordinates = state.extract_coordinates(CartesianPosition.default()) velocity_coordinates = state.extract_coordinates(CartesianVelocity.default()) - len(position_coordinates) == 3 - len(velocity_coordinates) == 3 + + assert len(position_coordinates) == 3 + assert len(velocity_coordinates) == 3 assert (position_coordinates == state.get_position().get_coordinates()).all() assert (velocity_coordinates == state.get_velocity().get_coordinates()).all() + + pv_coordinates = state.extract_coordinates( + [CartesianPosition.default(), CartesianVelocity.default()] + ) + assert len(pv_coordinates) == 6 + assert (pv_coordinates == state.get_coordinates()).all() diff --git a/include/OpenSpaceToolkit/Astrodynamics/Trajectory/State.hpp b/include/OpenSpaceToolkit/Astrodynamics/Trajectory/State.hpp index 559542ce9..df5f47686 100644 --- a/include/OpenSpaceToolkit/Astrodynamics/Trajectory/State.hpp +++ b/include/OpenSpaceToolkit/Astrodynamics/Trajectory/State.hpp @@ -38,19 +38,19 @@ using ostk::physics::time::Instant; using ostk::astro::trajectory::state::CoordinatesBroker; using ostk::astro::trajectory::state::CoordinatesSubset; -/// @brief Trajectory state +/// @brief Trajectory State class State { public: - /// @brief Constructor. + /// @brief Constructor. /// - /// @param [in] anInstant An instant - /// @param [in] aCoordinates The {cartesian-position, cartesian-velocity} coordinates at the instant - /// in International System of Units - /// @param [in] aFrameSPtr The reference frame in which the coordinates are referenced to and resolved - /// in - /// @param [in] aCoordinatesBrokerSPtr The coordinates broker associated to the coordinates + /// @param [in] anInstant An instant + /// @param [in] aCoordinates The {cartesian-position, cartesian-velocity} coordinates at the + /// instant in International System of Units + /// @param [in] aFrameSPtr The reference frame in which the coordinates are referenced to and + /// resolved in + /// @param [in] aCoordinatesBrokerSPtr The coordinates broker associated to the coordinates State( const Instant& anInstant, @@ -59,48 +59,154 @@ class State const Shared& aCoordinatesBrokerSPtr ); + /// @brief Constructor. + /// + /// @param [in] anInstant An instant + /// @param [in] aPosition The cartesian position at the instant in International System of Units + /// @param [in] aVelocity The cartesian velocity at the instant in International System of Units + State(const Instant& anInstant, const Position& aPosition, const Velocity& aVelocity); + /// @brief Equality operator. + /// + /// @param [in] aState The State to compare to + /// @return True if the States are equal, false otherwise + bool operator==(const State& aState) const; + /// @brief Inequality operator. + /// + /// @param [in] aState The State to compare to + /// @return True if the States are not equal, false otherwise + bool operator!=(const State& aState) const; + /// @brief Addition operator. + /// + /// @param [in] aState The State to add to this State + /// @return The sum of the two States + State operator+(const State& aState) const; + /// @brief Subtraction operator. + /// + /// @param [in] aState The State to subtract from this State + /// @return The difference between the two States + State operator-(const State& aState) const; + /// @brief Stream insertion operator. + /// + /// @param [in] anOutputStream The output stream to insert into + /// @param [in] aState The State to insert + /// @return The output stream with the State inserted + friend std::ostream& operator<<(std::ostream& anOutputStream, const State& aState); + /// @brief Check if the State is defined. + /// + /// @return True if the State is defined, false otherwise + bool isDefined() const; + /// @brief Accessor for the instant. + /// + /// @return The instant + const Instant& accessInstant() const; + /// @brief Accessor for the reference frame. + /// + /// @return The reference frame + const Shared accessFrame() const; + /// @brief Accessor for the coordinates. + /// + /// @return The coordinates + const VectorXd& accessCoordinates() const; + /// @brief Access the coordinates broker associated with the State. + /// + /// @return The coordinates broker associated to the State + const Shared& accessCoordinatesBroker() const; + /// @brief Get the size of the State. + /// + /// @return The size of the State + Size getSize() const; + /// @brief Get the instant associated with the State. + /// + /// @return The instant + Instant getInstant() const; + /// @brief Get the reference frame associated with the State. + /// + /// @return The reference frame + Shared getFrame() const; + /// @brief Get the cartesian position associated with the State (if present). + /// + /// @return The cartesian position + Position getPosition() const; + /// @brief Get the cartesian velocity associated with the State (if present). + /// + /// @return The cartesian velocity + Velocity getVelocity() const; + /// @brief Get the coordinates of the State. + /// + /// @return The coordinates + VectorXd getCoordinates() const; + /// @brief Get the coordinates subsets of the State. + /// + /// @return The coordinates subsets + const Array> getCoordinatesSubsets() const; - VectorXd extractCoordinates(const Shared& aSubetSPtr) const; + /// @brief Extract the coordinates for a single subset. + /// + /// @param [in] aSubsetSPtr The subset to extract the coordinates for + /// @return The coordinates for the subset + + VectorXd extractCoordinates(const Shared& aSubsetSPtr) const; + + /// @brief Extract the coordinates for multiple subsets. + /// + /// @param [in] aCoordinatesSubsetsArray The array of subsets to extract the coordinates for + /// @return The coordinates for the subsets + + VectorXd extractCoordinates(const Array>& aCoordinatesSubsetsArray) const; + + /// @brief Transform the State to a different reference frame. + /// + /// @param [in] aFrameSPtr The reference frame to transform to + /// @return The transformed State State inFrame(const Shared& aFrameSPtr) const; + /// @brief Print the State to an output stream. + /// + /// @param [in] anOutputStream The output stream to print to + /// @param [in] displayDecorator Whether or not to display the decorator + void print(std::ostream& anOutputStream, bool displayDecorator = true) const; + /// @brief Get an undefined State. + /// + /// @return An undefined State + static State Undefined(); private: diff --git a/include/OpenSpaceToolkit/Astrodynamics/Trajectory/State/CoordinatesBroker.hpp b/include/OpenSpaceToolkit/Astrodynamics/Trajectory/State/CoordinatesBroker.hpp index 646150155..b20b4b7e7 100644 --- a/include/OpenSpaceToolkit/Astrodynamics/Trajectory/State/CoordinatesBroker.hpp +++ b/include/OpenSpaceToolkit/Astrodynamics/Trajectory/State/CoordinatesBroker.hpp @@ -35,102 +35,113 @@ using ostk::astro::trajectory::state::CoordinatesSubset; class CoordinatesBroker { public: - /// @brief Constructor + /// @brief Constructor /// /// @code - /// CoordinatesBroker coordinatesBroker(); + /// CoordinatesBroker coordinatesBroker(); /// @endcode CoordinatesBroker(); - /// @brief Constructor + /// @brief Constructor /// /// @code - /// CoordinatesBroker coordinatesBroker({asubsetSPtr, anotherSubsetSPtr}); + /// CoordinatesBroker coordinatesBroker({asubsetSPtr, anotherSubsetSPtr}); /// @endcode /// - /// @param [in] aCoordinatesSubsetsArray the coordinates subsets to consider + /// @param [in] aCoordinatesSubsetsArray the coordinates subsets to consider CoordinatesBroker(const Array>& aCoordinatesSubsetsArray); - /// @brief Equal to operator + /// @brief Equal to operator /// - /// @param [in] aCoordinatesBroker A coordinates broker + /// @param [in] aCoordinatesBroker A coordinates broker /// - /// @return True if CoordinateBrokers equal + /// @return True if CoordinateBrokers equal bool operator==(const CoordinatesBroker& aCoordinatesBroker) const; - /// @brief Not equal to operator + /// @brief Not equal to operator /// - /// @param [in] aCoordinatesBroker A coordinates broker + /// @param [in] aCoordinatesBroker A coordinates broker /// - /// @return True if CoordinateBrokers are not equal + /// @return True if CoordinateBrokers are not equal bool operator!=(const CoordinatesBroker& aCoordinatesBroker) const; - /// @brief Return the considered coordinate subsets + /// @brief Return the considered coordinate subsets /// - /// @return The considered coordinate subsets + /// @return The considered coordinate subsets const Array>& accessSubsets() const; - /// @brief Return the total number of coordinates + /// @brief Return the total number of coordinates /// - /// @return The total number of coordinates + /// @return The total number of coordinates Size getNumberOfCoordinates() const; - /// @brief Return the total number of coordinate subsets + /// @brief Return the total number of coordinate subsets /// - /// @return The total number of coordinate subsets + /// @return The total number of coordinate subsets Size getNumberOfSubsets() const; - /// @brief Return the considered coordinate subsets + /// @brief Return the considered coordinate subsets /// - /// @return The considered coordinate subsets + /// @return The considered coordinate subsets Array> getSubsets() const; - /// @brief Add a coordinates subset to be considered, returning the starting index it will occupy (or - /// that it occupies if it was already added) in the state coordinates + /// @brief Add a coordinates subset to be considered, returning the starting index it will occupy + /// (or that it occupies if it was already added) in the state coordinates /// - /// @param [in] aCoordinatesSubsetSPtr a coordinates subset to be considered + /// @param [in] aCoordinatesSubsetSPtr a coordinates subset to be considered /// - /// @return The starting index of the subset in the state coordinates + /// @return The starting index of the subset in the state coordinates Index addSubset(const Shared& aCoordinatesSubsetSPtr); - /// @brief Check if a coordinates subset has already been considered + /// @brief Check if a coordinates subset has already been considered /// - /// @param [in] aCoordinatesSubsetSPtr the coordinates subset to be checked + /// @param [in] aCoordinatesSubsetSPtr the coordinates subset to be checked /// - /// @return True if the coordinates subset is already considered + /// @return True if the coordinates subset is already considered bool hasSubset(const Shared& aCoordinatesSubsetSPtr) const; - /// @brief Extract the coordinates of a given subset from the full coordinates vector + /// @brief Extract the coordinates of a given subset from the full coordinates vector /// - /// @param [in] aFullCoordinatesVector the full coordinates vecctor - /// @param [in] aCoordinatesSubset the coordinates subsets of interest + /// @param [in] aFullCoordinatesVector the full coordinates vecctor + /// @param [in] aCoordinatesSubset the coordinates subsets of interest /// - /// @return The coordinates of the subset + /// @return The coordinates of the subset VectorXd extractCoordinates(const VectorXd& aFullCoordinatesVector, const CoordinatesSubset& aCoordinatesSubset) const; - /// @brief Extract the coordinates of a given subset from the full coordinates vector + /// @brief Extract the coordinates of a given subset from the full coordinates vector /// - /// @param [in] aFullCoordinatesVector the full coordinates vecctor - /// @param [in] aCoordinatesSubsetSPtr the coordinates subsets of interest + /// @param [in] aFullCoordinatesVector the full coordinates vecctor + /// @param [in] aCoordinatesSubsetSPtr the coordinates subsets of interest /// - /// @return The coordinates of the subset + /// @return The coordinates of the subset VectorXd extractCoordinates( const VectorXd& aFullCoordinatesVector, const Shared& aCoordinatesSubsetSPtr ) const; + /// @brief Extract the coordinates of an array of subsets from the full coordinates vector + /// + /// @param [in] aFullCoordinatesVector the full coordinates vecctor + /// @param [in] aCoordinatesSubsetsArray the array of coordinates subsets of interest + /// + /// @return The coordinates of the array of subsets in the same order as the input subsets + + VectorXd extractCoordinates( + const VectorXd& aFullCoordinatesVector, const Array>& aCoordinatesSubsetsArray + ) const; + private: Index nextCoordinatesSubsetIndex_; Array> coordinatesSubsets_; diff --git a/src/OpenSpaceToolkit/Astrodynamics/Trajectory/State.cpp b/src/OpenSpaceToolkit/Astrodynamics/Trajectory/State.cpp index df469e9fb..effd586ea 100644 --- a/src/OpenSpaceToolkit/Astrodynamics/Trajectory/State.cpp +++ b/src/OpenSpaceToolkit/Astrodynamics/Trajectory/State.cpp @@ -305,9 +305,14 @@ const Array> State::getCoordinatesSubsets() cons return this->coordinatesBrokerSPtr_->getSubsets(); } -VectorXd State::extractCoordinates(const Shared& aSubetSPtr) const +VectorXd State::extractCoordinates(const Shared& aSubsetSPtr) const { - return this->coordinatesBrokerSPtr_->extractCoordinates(this->accessCoordinates(), aSubetSPtr); + return this->coordinatesBrokerSPtr_->extractCoordinates(this->accessCoordinates(), aSubsetSPtr); +} + +VectorXd State::extractCoordinates(const Array>& aCoordinatesSubsetsArray) const +{ + return this->coordinatesBrokerSPtr_->extractCoordinates(this->accessCoordinates(), aCoordinatesSubsetsArray); } State State::inFrame(const Shared& aFrameSPtr) const diff --git a/src/OpenSpaceToolkit/Astrodynamics/Trajectory/State/CoordinatesBroker.cpp b/src/OpenSpaceToolkit/Astrodynamics/Trajectory/State/CoordinatesBroker.cpp index 9d0d29151..3fc76bc15 100644 --- a/src/OpenSpaceToolkit/Astrodynamics/Trajectory/State/CoordinatesBroker.cpp +++ b/src/OpenSpaceToolkit/Astrodynamics/Trajectory/State/CoordinatesBroker.cpp @@ -1,6 +1,7 @@ /// Apache License 2.0 #include +#include #include @@ -115,6 +116,30 @@ VectorXd CoordinatesBroker::extractCoordinates( ); } +VectorXd CoordinatesBroker::extractCoordinates( + const VectorXd& aFullCoordinatesVector, const Array>& aCoordinatesSubsetsArray +) const +{ + Size coordinatesSubsetsSize = 0; + for (const auto& subset : aCoordinatesSubsetsArray) + { + coordinatesSubsetsSize += subset->getSize(); + } + + VectorXd coordinatesSubsetsVector(coordinatesSubsetsSize); + + int startIndex = 0; + for (const auto& subset : aCoordinatesSubsetsArray) + { + coordinatesSubsetsVector.segment(startIndex, subset->getSize()) = + aFullCoordinatesVector.segment(this->getSubsetIndex(subset->getId()), subset->getSize()); + + startIndex += subset->getSize(); + } + + return coordinatesSubsetsVector; +} + VectorXd CoordinatesBroker::extractCoordinates( const VectorXd& aFullCoordinatesVector, const Shared& aCoordinatesSubsetSPtr ) const diff --git a/test/OpenSpaceToolkit/Astrodynamics/Trajectory/State.test.cpp b/test/OpenSpaceToolkit/Astrodynamics/Trajectory/State.test.cpp index e6b0005e2..72818224e 100644 --- a/test/OpenSpaceToolkit/Astrodynamics/Trajectory/State.test.cpp +++ b/test/OpenSpaceToolkit/Astrodynamics/Trajectory/State.test.cpp @@ -957,6 +957,28 @@ TEST(OpenSpaceToolkit_Astrodynamics_Trajectory_State, ExtractCoordinates) EXPECT_EQ(coordinates.segment(0, 3), aState.extractCoordinates(CartesianPosition::Default())); EXPECT_EQ(coordinates.segment(3, 3), aState.extractCoordinates(CartesianVelocity::Default())); } + + { + const Instant instant = Instant::DateTime(DateTime(2018, 1, 1, 0, 0, 0), Scale::UTC); + VectorXd coordinates(6); + coordinates << 1.0, 2.0, 3.0, 4.0, 5.0, 6.0; + const Shared brokerSPtr = std::make_shared( + CoordinatesBroker({CartesianPosition::Default(), CartesianVelocity::Default()}) + ); + const State aState = {instant, coordinates, Frame::GCRF(), brokerSPtr}; + + const Array> positionSubset = {CartesianPosition::Default()}; + EXPECT_EQ(coordinates.segment(0, 3), aState.extractCoordinates(positionSubset)); + + const Array> velocitySubset = {CartesianVelocity::Default()}; + EXPECT_EQ(coordinates.segment(3, 3), aState.extractCoordinates(velocitySubset)); + + const Array> positionAndVelocitySubset = { + CartesianPosition::Default(), + CartesianVelocity::Default(), + }; + EXPECT_EQ(coordinates, aState.extractCoordinates(positionAndVelocitySubset)); + } } TEST(OpenSpaceToolkit_Astrodynamics_Trajectory_State, InFrame) diff --git a/test/OpenSpaceToolkit/Astrodynamics/Trajectory/State/CoordinatesBroker.test.cpp b/test/OpenSpaceToolkit/Astrodynamics/Trajectory/State/CoordinatesBroker.test.cpp index ddeb9d2f3..1fb5c1ea5 100644 --- a/test/OpenSpaceToolkit/Astrodynamics/Trajectory/State/CoordinatesBroker.test.cpp +++ b/test/OpenSpaceToolkit/Astrodynamics/Trajectory/State/CoordinatesBroker.test.cpp @@ -10,6 +10,7 @@ using ostk::core::types::Shared; using ostk::core::types::Size; using ostk::core::types::String; +using ostk::core::ctnr::Array; using ostk::math::obj::VectorXd; @@ -346,4 +347,55 @@ TEST_F(OpenSpaceToolkit_Astrodynamics_Trajectory_State_CoordinatesBroker, Extrac EXPECT_ANY_THROW(broker.extractCoordinates(fullCoordinatesVector, subset_4)); } + + { + CoordinatesBroker broker = CoordinatesBroker(); + broker.addSubset(subset_1); + broker.addSubset(subset_2); + broker.addSubset(subset_3); + + VectorXd fullCoordinatesVector(6); + fullCoordinatesVector << 0.0, 1.0, 2.0, 3.0, 4.0, 5.0; + + Array> subsets_1 = {subset_1}; + const VectorXd subset_1_coordinates = broker.extractCoordinates(fullCoordinatesVector, subsets_1); + EXPECT_EQ(1, subset_1_coordinates.size()); + EXPECT_EQ(0.0, subset_1_coordinates(0)); + + Array> subsets_12 = {subset_1, subset_2}; + const VectorXd subset_12_coordinates = broker.extractCoordinates(fullCoordinatesVector, subsets_12); + EXPECT_EQ(3, subset_12_coordinates.size()); + EXPECT_EQ(0.0, subset_12_coordinates(0)); + EXPECT_EQ(1.0, subset_12_coordinates(1)); + EXPECT_EQ(2.0, subset_12_coordinates(2)); + + Array> subsets_13 = {subset_1, subset_3}; + const VectorXd subset_13_coordinates = broker.extractCoordinates(fullCoordinatesVector, subsets_13); + EXPECT_EQ(4, subset_13_coordinates.size()); + EXPECT_EQ(0.0, subset_13_coordinates(0)); + EXPECT_EQ(3.0, subset_13_coordinates(1)); + EXPECT_EQ(4.0, subset_13_coordinates(2)); + EXPECT_EQ(5.0, subset_13_coordinates(3)); + + Array> subsets_31 = {subset_3, subset_1}; + const VectorXd subset_31_coordinates = broker.extractCoordinates(fullCoordinatesVector, subsets_31); + EXPECT_EQ(4, subset_31_coordinates.size()); + EXPECT_EQ(3.0, subset_31_coordinates(0)); + EXPECT_EQ(4.0, subset_31_coordinates(1)); + EXPECT_EQ(5.0, subset_31_coordinates(2)); + EXPECT_EQ(0.0, subset_31_coordinates(3)); + + Array> subsets_123 = {subset_1, subset_2, subset_3}; + const VectorXd subset_123_coordinates = broker.extractCoordinates(fullCoordinatesVector, subsets_123); + EXPECT_EQ(6, subset_123_coordinates.size()); + EXPECT_EQ(0.0, subset_123_coordinates(0)); + EXPECT_EQ(1.0, subset_123_coordinates(1)); + EXPECT_EQ(2.0, subset_123_coordinates(2)); + EXPECT_EQ(3.0, subset_123_coordinates(3)); + EXPECT_EQ(4.0, subset_123_coordinates(4)); + EXPECT_EQ(5.0, subset_123_coordinates(5)); + + Array> subsets_14 = {subset_1, subset_4}; + EXPECT_ANY_THROW(broker.extractCoordinates(fullCoordinatesVector, subsets_14)); + } }