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

Handling unsampled states in offline/realtime analysis. #593

Merged
merged 2 commits into from
Jun 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/releasehistory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Bugfixes
--------
- Bug in statistical inefficiency computation -- where self.max_n_iterations wasn't being used -- was fixed (`#577 <https://github.com/choderalab/openmmtools/pull/577>`_).
- Bug in estimated performance in realtime yaml file -- fixed by iterating through all MCMC moves (`#578 <https://github.com/choderalab/openmmtools/pull/578>`_)
- Bug in handling unsampled states in realtime/offline analysis -- fixed by using ``MultiStateSampler._unsampled_states`` to build the mbar estimate array. Issue `#592 <https://github.com/choderalab/openmmtools/issues/592>`_ (`#593 <https://github.com/choderalab/openmmtools/pull/593>`_)


0.21.3 - Bugfix release
Expand Down
16 changes: 11 additions & 5 deletions openmmtools/multistate/multistatesampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -1514,9 +1514,14 @@ def _offline_analysis(self):
bump_error_counter = False
# Set up analyzer
# Unbias restraints is False because this will quickly accumulate large time to re-read the trajectories
# and unbias the restraints every online-analysis. Current model is to use the last_mbar_f_k as a
# hot-start to the analysis. Once we store unbias info as part of a CustomCVForce, we can revisit this choice.
analysis = MultiStateSamplerAnalyzer(self._reporter, analysis_kwargs={'initial_f_k': self._last_mbar_f_k},
# and unbias the restraints every online-analysis. Current model is to initialize the last_mbar_f_k_offline
# attribute to zeros the first time, and then using its last result to produce the subsequent ones.
# Once we store unbias info as part of a CustomCVForce, we can revisit this choice.
# Initialize with zeros on first run including unsampled states
if not hasattr(self, "_last_mbar_f_k_offline"):
self._last_mbar_f_k_offline = np.zeros(len(self._thermodynamic_states) + len(self._unsampled_states))
analysis = MultiStateSamplerAnalyzer(self._reporter,
analysis_kwargs={'initial_f_k': self._last_mbar_f_k_offline},
unbias_restraint=False)

# Indices for online analysis, "i'th index, j'th index"
Expand All @@ -1532,14 +1537,15 @@ def _offline_analysis(self):
except ParameterError as e:
# We don't update self._last_err_free_energy here since if it
# wasn't below the target threshold before, it won't stop MultiStateSampler now.
logger.debug(f"ParameterError computing MBAR. {e}.")
bump_error_counter = True
self._online_error_bank.append(e)
if len(self._online_error_bank) > 6:
# Cache only the last set
self._online_error_bank.pop(0)
free_energy = None
else:
self._last_mbar_f_k = mbar.f_k
self._last_mbar_f_k_offline = mbar.f_k
free_energy = free_energy[idx, jdx]
self._last_err_free_energy = err_free_energy[idx, jdx]
logger.debug("Current Free Energy Estimate is {} +- {} kT".format(free_energy,
Expand All @@ -1564,7 +1570,7 @@ def _offline_analysis(self):

# Write out the numbers
self._reporter.write_online_data_dynamic_and_static(self._iteration,
f_k=self._last_mbar_f_k,
f_k_offline=self._last_mbar_f_k_offline,
free_energy=(free_energy, self._last_err_free_energy))
# Write real time offline analysis YAML file
# TODO: Specify units
Expand Down