return partial convergence analysis if mbar fails for individual fraction#1984
return partial convergence analysis if mbar fails for individual fraction#1984aqemia-benedict-tan wants to merge 14 commits into
Conversation
IAlibay
left a comment
There was a problem hiding this comment.
Thanks @aqemia-benedict-tan, this looks great - just the one comment on the code as-is.
The main thing we would need (and why I have to request changes) is that we need to add tests to cover the new behaviour
Ideally we would want to:
- Test that the check the array of forward and backwards energies returned make sense (similar to )
- Something in
tests/analysis/test_plotting.pythat checks that passing in an array with NaN's works fine and probably a manual check that the plot looks ok.
| # MBAR can fail to converge at low fractions of uncorrelated | ||
| # samples. If this happens, append NaN and carry on so that | ||
| # estimates at higher fractions are still reported. | ||
| try: |
There was a problem hiding this comment.
[nit] Given the similar-ish duplicated code, it might be good to just move this to a helper method that takes in the sub-sampled u_ln, fraction, and either "reverse" or "forward" for the warning string.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1984 +/- ##
==========================================
- Coverage 94.95% 90.16% -4.79%
==========================================
Files 216 216
Lines 20517 20578 +61
==========================================
- Hits 19481 18554 -927
- Misses 1036 2024 +988
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Thanks for the feedback @IAlibay, I have refactored to include the helper function
|
|
Thanks @aqemia-benedict-tan ! I'lll have another look at this early next week. |
IAlibay
left a comment
There was a problem hiding this comment.
Sorry - I somewhat changed my mind on what the behaviour should look like on failure, that will require some code changes.
Could you also:
- Add a news entry under
openfe/news. - Add yourself to the CITATION.cff author list?
Thanks!
| fraction = chunk / N_l[0] | ||
|
|
||
| # Forward | ||
| DG, dDG = self._get_free_energy( |
There was a problem hiding this comment.
I've been thinking about this a little bit more and I've come to the realization that we probably should NaN both the forward and the reverse chunk if either fails.
My reasoning is that whilst a failure is directly caused by a lack of convergence in the estimator, it's more broadly caused by too few data points (generally too high a decorrelation time). So whilst one direction could pass (e.g. the reduced potentials happen to be easier to deal with), it's probably not reasonable to include either.
There was a problem hiding this comment.
Yes this makes sense - commits 7b7dba3 and dbf9b71 refactor the _get_fraction_free_energy helper to return NaN for both directions, if either the forwards or reverse estimate fails.
Commit 42ee838 updates the tests, the test at src/openfe/tests/protocols/test_openmmutils.py is adapted to ensure NaN is returned for both directions in the case that the lowest fraction of samples failes in either the forwards or reverse direction.
The new graph from the plotting test looks like this:
| uncorrelated samples) should be rendered as gaps without raising. | ||
| """ | ||
| forward_reverse = _make_forward_reverse( | ||
| forward=[np.nan, np.nan, -9.2, -9.4, -9.5, -9.6, -9.65, -9.7, -9.72, -9.75], |
There was a problem hiding this comment.
What if the nan happens towards the end? It's unlikely but could happen.
My understanding is that the fill_between call would just do nothing. In that case - it might be better to just return None for the whole thing.
There was a problem hiding this comment.
Good point! Commit ce66327 fixes this by returningNone if the final element of the reverse and forwards estimate (i.e. fraction 1.0) isNaN. A unit test is also added for this scenario.
| rtol=5e-01, | ||
| ) # fmt: skip | ||
|
|
||
| def test_forward_and_reverse_nan_on_mbar_failure(self, analyzer): |
There was a problem hiding this comment.
Thanks for doing this - this test looks great!
…n where MBAR fails
IAlibay
left a comment
There was a problem hiding this comment.
A few more things and then I think we're there!
|
|
||
| fractions.append(chunk / N_l[0]) | ||
| fractions.append(fraction) | ||
| except ParameterError: |
There was a problem hiding this comment.
I think this outer try/except is now dead. Can you remove it (alongisde the associated ParameterError import)?
| "of uncorrelated samples (fraction 1.0); discarding the forward " | ||
| "and reverse convergence analysis." | ||
| ) | ||
| warnings.warn(wmsg) |
There was a problem hiding this comment.
Can you set the stacklevel parameter to 2 here? We're not great at being consistent about it elsewhere, but it's a small QoL thing that will be useful for users.
|
No API break detected ✅ |

When running ABFE calculations in OpenFE, MBAR sometimes fails to produce an estimate at low fractions of uncorrelated samples (~0.1-0.4). It would be helpful to still return the convergence trace where MBAR can generate a meaningful result (e.g. >0.7) This PR modifies
get_forward_and_reverse_analysisunderopenmm_utilsso thatNaNvalues are appended to the forwards/reverse estimate lists where MBAR fails and the successful estimates are still returned.Checklist
pre-commit.ci autofix.Developers certificate of origin