Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TableUtilities and more CommonUtilities. #2808

Merged
merged 12 commits into from
Jun 29, 2020
Merged

Conversation

chrisdembia
Copy link
Member

@chrisdembia chrisdembia commented Jun 19, 2020

Part of #2559

Brief summary of changes

Some of these changes are required for #2793 (e.g., solveBisection()).

Testing I've completed

  • Ran ctests.

Looking for feedback on...

naming of new functions.

CHANGELOG.md (choose one)

  • updated.

@carmichaelong @aymanhab I don't think we need both of you to review, but either of you could review, so I've added both of you as reviewers.

@adamkewley , no pressure whatsoever, but feel free to pitch in on this review if you're interested. @aymanhab and @carmichaelong already have some context for this PR, so if you want more context, we can chat about it.


This change is Reviewable

Update VisualizerUtilities::showMotion() and StatesTrajectory to use a TimeSeriesTable.
@chrisdembia
Copy link
Member Author

Tests finally pass :)

@adamkewley
Copy link
Contributor

Nothing particularly unusual in there. Most of the stuff I spotted was more "things to think about", rather than game-changers, so I'd just take what I've written non-seriously if you need to ship this quickly.

Copy link
Member

@aymanhab aymanhab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 1 of 28 files at r1.
Reviewable status: 1 of 28 files reviewed, 1 unresolved discussion (waiting on @aymanhab, @carmichaelong, and @chrisdembia)


CHANGELOG.md, line 18 at r1 (raw file):

- Whitespace is trimmed when reading table metadata for STO, MOT, and CSV files.
- Introduce the following utility functions:
  - make_unique()

Where? Just reading this in release notes without context, users have no clue. Do we need this itemized list in CHANGLEOG or just a short summary, maybe an issue with details.

@aymanhab aymanhab self-requested a review June 22, 2020 15:22
Copy link
Member Author

@chrisdembia chrisdembia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 1 of 28 files reviewed, 1 unresolved discussion (waiting on @aymanhab and @carmichaelong)


CHANGELOG.md, line 18 at r1 (raw file):

Previously, aymanhab (Ayman Habib) wrote…

Where? Just reading this in release notes without context, users have no clue. Do we need this itemized list in CHANGLEOG or just a short summary, maybe an issue with details.

@aymanhab let me know which of the two approaches edits you prefer:

Introduce the following utility functions in OpenSim/Common/CommonUtilities.h:

versus

Introduce utilities for creating SimTK::Vectors, linear interpolation, updating table column labels from v3.3 to v4.0 syntax, and solving for a function's root using bisection (OpenSim/Common/CommonUtilities.h).

@aymanhab
Copy link
Member

Reviewable status: 1 of 28 files reviewed, 1 unresolved discussion (waiting on @aymanhab and @carmichaelong)

CHANGELOG.md, line 18 at r1 (raw file):

Previously, aymanhab (Ayman Habib) wrote…
@aymanhab let me know which of the two approaches edits you prefer:

Introduce the following utility functions in OpenSim/Common/CommonUtilities.h:

versus

Introduce utilities for creating SimTK::Vectors, linear interpolation, updating table column labels from v3.3 to v4.0 syntax, and solving for a function's root using bisection (OpenSim/Common/CommonUtilities.h).

I prefer the second which gives the high level functionality as seen by users. We can link to the PR or an issue summarizing the change if some user wants to go deeper. Thanks @chrisdembia

@chrisdembia
Copy link
Member Author

I prefer the second which gives the high level functionality as seen by users. We can link to the PR or an issue summarizing the change if some user wants to go deeper. Thanks @chrisdembia

Done.

@aymanhab aymanhab self-requested a review June 26, 2020 16:30
Copy link
Member

@aymanhab aymanhab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 7 of 28 files at r1, 1 of 1 files at r2.
Reviewable status: 6 of 27 files reviewed, 4 unresolved discussions (waiting on @aymanhab, @carmichaelong, and @chrisdembia)


OpenSim/Common/CommonUtilities.h, line 75 at r1 (raw file):

OSIMCOMMON_API
SimTK::Vector createVectorLinspace(int length, double start, double end);

Linspace is a bit unclear, uniformSpace? Are there similar matlab functions that users maybe familiar with?


OpenSim/Common/CommonUtilities.h, line 99 at r2 (raw file):

        const std::string& documentFileName,
        const std::string& pathnameRelativeToDocument);

The method name is a bit ambiguous because XML has a native PATH concept (sequence of nodes). The name could be something like convertDocumentRelativePathnameToAbsolute() or convertRelativeFilePathToAbsolute(). Thoughts?


OpenSim/Common/CommonUtilities.h, line 103 at r2 (raw file):

/// If the values of calcResidual(left) and calcResidual(right) have the same
/// sign and Logger::shouldLog(Logger::Level::Debug), then
/// this function writes a file `solveBisection_residual_<timestamp>.sto`

I'd use Logger level set to Debug, and not hardcode the actual signature of shouldLog since there are multiple ways to set it.

Copy link
Member

@aymanhab aymanhab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 4 of 28 files at r1, 1 of 4 files at r3.
Reviewable status: 11 of 27 files reviewed, 7 unresolved discussions (waiting on @aymanhab, @carmichaelong, and @chrisdembia)


OpenSim/Common/CommonUtilities.cpp, line 120 at r3 (raw file):

        const auto& newXi = newX[i];
        if (x_no_nans[0] <= newXi && newXi <= x_no_nans[x_no_nans.size() - 1])
            newY[i] = function.calcValue(SimTK::Vector(1, newXi));

Not sure what assumptions are made regarding x monotonically increasing (doesn't seem to be enforced) are newXi guaranteed by construction to fall between the x_no_nans bounds?


OpenSim/Common/CommonUtilities.cpp, line 145 at r3 (raw file):

    OPENSIM_THROW_IF(maxIterations < 0, Exception,
            "Expected maxIterations to be positive, but got {}.",

So 0 is allowed? Is this intentional?


OpenSim/Common/CommonUtilities.cpp, line 157 at r3 (raw file):

            row[0] = calcResidual(x[i]);
            table.appendRow(x[i], row);
        }

appendRow is known to be terrible time consuming call since it copies the table contents to add a new row, if time critical I'd avoid it


OpenSim/Common/IO.h, line 129 at r3 (raw file):

    /// https://stackoverflow.com/questions/874134/find-if-string-ends-with-another-string-in-c
    static bool EndsWith(const std::string& string, const std::string& ending);
    static void eraseEmptyElements(std::vector<std::string>& list);

Typically this methods have ignore case option or variant

@aymanhab aymanhab self-requested a review June 26, 2020 16:57
Copy link
Member

@aymanhab aymanhab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 4 of 28 files at r1, 1 of 4 files at r3.
Reviewable status: 16 of 27 files reviewed, 8 unresolved discussions (waiting on @aymanhab, @carmichaelong, and @chrisdembia)


OpenSim/Simulation/Test/testStatesTrajectory.cpp, line 512 at r3 (raw file):

        itime++;
    }
}

Is this tested somewhere else?

@aymanhab aymanhab self-requested a review June 26, 2020 17:31
Copy link
Member

@aymanhab aymanhab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 2 of 28 files at r1.
Reviewable status: 18 of 27 files reviewed, 10 unresolved discussions (waiting on @aymanhab, @carmichaelong, and @chrisdembia)


OpenSim/Common/Signal.h, line 90 at r3 (raw file):

    static std::vector<double> Pad(int aPad, int aN, const double aSignal[]);
    static void Pad(int aPad, OpenSim::Array<double>& aSignal);

Is there a reason to keep around 2 versions of Pad with 2 different interfaces and datatypes? Can these be unified?


OpenSim/Common/TimeSeriesTable.h, line 515 at r3 (raw file):

    friend class TableUtilities;

Why do we need this friendship, if TableUtilities is using the public interface of TimeSeriesTable

@aymanhab aymanhab self-requested a review June 26, 2020 17:50
Copy link
Member

@aymanhab aymanhab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 8 of 28 files at r1, 1 of 4 files at r3.
Reviewable status: all files reviewed, 13 unresolved discussions (waiting on @carmichaelong and @chrisdembia)


OpenSim/Common/Test/testDataTable.cpp, line 915 at r3 (raw file):

        CHECK(column[4] == Approx(0.2));
        CHECK(column[5] == Approx(0.0).margin(1e-10));
    }

What's the use of margin and why only in this case/column?


OpenSim/Simulation/SimulationUtilities.h, line 59 at r3 (raw file):

/// This can also be used to update the column labels of an Inverse
/// Kinematics Tool solution MOT file so that the data can be used as
/// states. If a label does not identify a state in the model, the column

MOT files are typically in degrees and don't contain muscle states, that's fine for a lower level utility but maybe some warning if states are missing would help


OpenSim/Simulation/StatesTrajectory.h, line 449 at r3 (raw file):

     * import opensim
     * model = opensim.Model("subject01.osim")
     * table = opensim.TimeSeriesTable("subject01_states.sto")

While useful to have the example here, this tends to be brittle since they need to be maintained, wondering if there's a better more sustainable solution. If we upgrade SWIG we may not need these altogether, I think

@aymanhab
Copy link
Member

Finished a pass of review, overall looks good, left a few questions/suggestions. Thanks @chrisdembia

Copy link
Member Author

@chrisdembia chrisdembia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ready for review.

Reviewable status: 22 of 28 files reviewed, 13 unresolved discussions (waiting on @aymanhab and @carmichaelong)


CHANGELOG.md, line 18 at r1 (raw file):

Previously, aymanhab (Ayman Habib) wrote…

I prefer the second which gives the high level functionality as seen by users. We can link to the PR or an issue summarizing the change if some user wants to go deeper. Thanks @chrisdembia

Done.


OpenSim/Common/CommonUtilities.h, line 75 at r1 (raw file):

Previously, aymanhab (Ayman Habib) wrote…

Linspace is a bit unclear, uniformSpace? Are there similar matlab functions that users maybe familiar with?

We chose this name because it's familiar to Matlab users: http://www.ece.northwestern.edu/local-apps/matlabhelp/techdoc/ref/linspace.html


OpenSim/Common/CommonUtilities.h, line 99 at r2 (raw file):

Previously, aymanhab (Ayman Habib) wrote…

The method name is a bit ambiguous because XML has a native PATH concept (sequence of nodes). The name could be something like convertDocumentRelativePathnameToAbsolute() or convertRelativeFilePathToAbsolute(). Thoughts?

Ah good point. I attempted a new name.


OpenSim/Common/CommonUtilities.h, line 103 at r2 (raw file):

Previously, aymanhab (Ayman Habib) wrote…

I'd use Logger level set to Debug, and not hardcode the actual signature of shouldLog since there are multiple ways to set it.

Done.


OpenSim/Common/CommonUtilities.cpp, line 120 at r3 (raw file):

Previously, aymanhab (Ayman Habib) wrote…

Not sure what assumptions are made regarding x monotonically increasing (doesn't seem to be enforced) are newXi guaranteed by construction to fall between the x_no_nans bounds?

I just added such a check to the constructor of PiecewiseLinearFunction.


OpenSim/Common/CommonUtilities.cpp, line 145 at r3 (raw file):

Previously, aymanhab (Ayman Habib) wrote…

So 0 is allowed? Is this intentional?

Yes, 0 is allowed.

In Moco, we use Ipopt and it permits 0 iterations.


OpenSim/Common/CommonUtilities.cpp, line 157 at r3 (raw file):

Previously, aymanhab (Ayman Habib) wrote…

appendRow is known to be terrible time consuming call since it copies the table contents to add a new row, if time critical I'd avoid it

Done.


OpenSim/Common/IO.h, line 129 at r3 (raw file):

Previously, aymanhab (Ayman Habib) wrote…

Typically this methods have ignore case option or variant

Done.


OpenSim/Common/Signal.h, line 90 at r3 (raw file):

Previously, aymanhab (Ayman Habib) wrote…

Is there a reason to keep around 2 versions of Pad with 2 different interfaces and datatypes? Can these be unified?

I've unified the implementations but left both interfaces.


OpenSim/Common/TimeSeriesTable.h, line 515 at r3 (raw file):

Previously, aymanhab (Ayman Habib) wrote…

Why do we need this friendship, if TableUtilities is using the public interface of TimeSeriesTable

The pad utility modifies the table's _indData, which is not public :(


OpenSim/Common/Test/testDataTable.cpp, line 915 at r3 (raw file):

Previously, aymanhab (Ayman Habib) wrote…

What's the use of margin and why only in this case/column?

Margin is a permitted absolute error; it's used here because Approx(0.0) is not sufficient on its own: catchorg/Catch2#1444


OpenSim/Simulation/SimulationUtilities.h, line 59 at r3 (raw file):

Previously, aymanhab (Ayman Habib) wrote…

MOT files are typically in degrees and don't contain muscle states, that's fine for a lower level utility but maybe some warning if states are missing would help

We use this in Moco when we track kinematics from an IK solution, in which case we need to update the column labels but it's fine that muscle states are missing.


OpenSim/Simulation/StatesTrajectory.h, line 449 at r3 (raw file):

Previously, aymanhab (Ayman Habib) wrote…

While useful to have the example here, this tends to be brittle since they need to be maintained, wondering if there's a better more sustainable solution. If we upgrade SWIG we may not need these altogether, I think

I think it's easiest to maintain documentation that resides in the repository (rather than separately editing Confluence).

I think these examples are still useful even if we move to SWIG 4, because then Python users can access this Python example within their Python interpreter.

The best documentation is example code; I've updated posthoc_StatesTrajectory_example.py in this PR.


OpenSim/Simulation/Test/testStatesTrajectory.cpp, line 512 at r3 (raw file):

Previously, aymanhab (Ayman Habib) wrote…

Is this tested somewhere else?

No, I've removed this check. For TimeSeriesTables, all rows have the same length. I think this check was largely unnecessary anyway.

@aymanhab aymanhab self-requested a review June 29, 2020 17:20
Copy link
Member

@aymanhab aymanhab left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 7 of 7 files at r4.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @aymanhab and @carmichaelong)

@chrisdembia chrisdembia merged commit 84954d5 into master Jun 29, 2020
@chrisdembia
Copy link
Member Author

Thanks @aymanhab

@chrisdembia chrisdembia deleted the TableUtilities branch June 29, 2020 22:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants