Skip to content

Sampler engine structure #280 - #287

Open
rozyczko wants to merge 15 commits into
developfrom
sampler-engine-structure-280
Open

rozyczko wants to merge 15 commits into
developfrom
sampler-engine-structure-280

Conversation

@rozyczko

@rozyczko rozyczko commented Aug 7, 2026

Copy link
Copy Markdown
Member

Core refactoring and shared logic:

  • Introduced EngineBase (engine_base.py) as a new base class for all evaluation engines (minimizers and samplers), with centralized parameter handling, fit function wrapping, and evaluation logic.
  • Refactored MinimizerBase so it inherits from EngineBase. Cleaned up the constructor and removed duplicated parameter caching logic.

Bumps integration and utilities:

  • Extracted BUMPS-specific problem construction and parameter conversion functions into a new module bumps_utils/problem.py, including build_curve_problem, to_bumps_parameter, parameter_names, and parameter_snapshot. These are now imported and exposed in bumps_utils/__init__.py.
  • Added a new validation module (bumps_utils/validation.py) with functions for validating run settings and input arrays

API changes and deprecations:

  • mcmc_sample() now lives on Sampler class directly. The method now routes calls to Sampler(...).sample(...)
  • Updated the progress_callback signature in MinimizerBase.fit to clarify that its return value is ignored and to align with the new shared engine base.

@rozyczko rozyczko added [area] fitting Umbrella for fitting related work [scope] maintenance Code/tooling cleanup, no feature or bugfix (major.minor.PATCH) [priority] high Should be prioritized soon labels Aug 7, 2026
@rozyczko
rozyczko requested a review from damskii9992 September 2, 2026 12:53

@damskii9992 damskii9992 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I am ALMOST done reviewing this behemoth of a PR. Still need to look at sampler_dream.py and the tests. but the day is almost over and I figured I should send off these comments now.

Comment thread src/easyscience/fitting/engine_base.py Outdated
Comment thread src/easyscience/fitting/minimizers/minimizer_base.py Outdated
Comment thread src/easyscience/fitting/sampler.py Outdated
Comment thread src/easyscience/fitting/sampler.py Outdated
Comment thread src/easyscience/fitting/sampler.py Outdated
Comment thread src/easyscience/fitting/minimizers/minimizer_bumps.py Outdated
Comment thread src/easyscience/fitting/minimizers/minimizer_bumps.py
Comment thread src/easyscience/fitting/minimizers/minimizer_bumps.py Outdated
Comment thread src/easyscience/fitting/minimizers/minimizer_bumps.py Outdated
Comment thread src/easyscience/fitting/minimizers/minimizer_bumps.py Outdated
@rozyczko
rozyczko requested a review from damskii9992 September 8, 2026 19:54
@damskii9992

Copy link
Copy Markdown
Contributor

You will need to change the tutorial in this PR too . . .

@damskii9992 damskii9992 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please also remove all the "Optional" typehints in the code and replace them with | None as is the new convention.

Comment thread src/easyscience/fitting/samplers/sampler_bumps.py Outdated
Comment thread src/easyscience/fitting/sampler.py Outdated

def __init__(
self,
fitter: 'Fitter',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Wasn't a big part of this re-factoring done to also ensure that you didn't need a Fitter to create a Sampler?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The refactor decoupled sampling from the minimizer, not from the Fitter. Fitter still has reshaping and fit-function wrapping.

One thing: __init__ requires hasattr(fitter, 'minimizer') but the minimizer is never used. I'll fix that.

Comment thread src/easyscience/fitting/engine_base.py Outdated
Comment on lines +8 to +33
def validate_run_settings(samples: int, burn: int, thin: int) -> None:
"""Validate the DREAM run settings.

Parameters
----------
samples : int
Number of raw samples to draw; must be a positive integer.
burn : int
Burn-in generations to discard; must be a non-negative integer.
thin : int
Thinning interval; must be a positive integer.

Raises
------
ValueError
If any value is out of range or not an integer.
"""
# bool is a subclass of int, so ``samples=True`` would otherwise pass as
# ``samples=1``; these checks are strict (``10.0`` is rejected), so
# booleans must be rejected too.
if not isinstance(samples, int) or isinstance(samples, bool) or samples <= 0:
raise ValueError('samples must be a positive integer.')
if not isinstance(burn, int) or isinstance(burn, bool) or burn < 0:
raise ValueError('burn must be a non-negative integer.')
if not isinstance(thin, int) or isinstance(thin, bool) or thin < 1:
raise ValueError('thin must be a positive integer.')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why factor this into a separate module? It's only used by the DreamSampler, so shouldn't it live there?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also, it is only used in 1 place, so why even factor it out at all? It's more readable to just have the code where it is used, if it is only used once . . .

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

moved to samples/validation.py, dropped from bumps_utils/init.py, exported from samplers/init.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

But why not move it into the DreamSampler class? It's only used in that class, right?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Potentially usable by other Samplers, barred the docstring change from DREAM run settings

Comment on lines +173 to +174
validate_run_settings(samples, burn, thin)
validate_arrays(x, y, weights)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should our validations belong in the Sampler class or here? Right now you validate in both places . . .
I think validations should belong in Sampler as long as they aren't engine-specific. Which means the engines can assume that whatever is passed to them is valid.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It is not actually duplicated. Sampler checks numeric/non-scalar/non-empty; validate_arrays checks shape match, finiteness, positive weights.
They are more complementary than dupes. And validate_arrays cannot move into Sampler regardless, since all three minimizers call it from Fitter.fit...

Comment thread src/easyscience/fitting/samplers/sampler_bumps.py
Comment thread src/easyscience/fitting/minimizers/minimizer_base.py Outdated
Comment thread src/easyscience/fitting/minimizers/minimizer_bumps.py Outdated
@rozyczko

rozyczko commented Sep 10, 2026

Copy link
Copy Markdown
Member Author

You will need to change the tutorial in this PR too . . .

No changes needed.
We removed Fitter.mcmc_sample, SamplingResults.to_legacy_dict, and the optional parameters and model list - things which are not used by any notebook.

I will need to change the tutorials for the ModelBase migration, true

@damskii9992

Copy link
Copy Markdown
Contributor

You will need to change the tutorial in this PR too . . .

No changes needed. We removed Fitter.mcmc_sample, SamplingResults.to_legacy_dict, and the optional parameters and model list - things which are not used by any notebook.

I will need to change the tutorials for the ModelBase migration, true

I think we have misaligned our idea for the public API a little bit.

I wanted Sampler to be a completely parallel option to the Fitter. I.e. the user never has to use or know about the Fitter if they only want to do sampling.

For convenience sake, I thought it'd be prudent to have a classmethod to construct a Sampler from a Fitter, and I guess in the reverse too, but I see them as fully independent and parallel objects/paths that a user can take to analyze their data.

@rozyczko

Copy link
Copy Markdown
Member Author

You will need to change the tutorial in this PR too . . .

No changes needed. We removed Fitter.mcmc_sample, SamplingResults.to_legacy_dict, and the optional parameters and model list - things which are not used by any notebook.
I will need to change the tutorials for the ModelBase migration, true

I think we have misaligned our idea for the public API a little bit.

I wanted Sampler to be a completely parallel option to the Fitter. I.e. the user never has to use or know about the Fitter if they only want to do sampling.

For convenience sake, I thought it'd be prudent to have a classmethod to construct a Sampler from a Fitter, and I guess in the reverse too, but I see them as fully independent and parallel objects/paths that a user can take to analyze their data.

Usually you want to do the fitting before running the sampling, so setting the fitter on the Sampler sort of makes sense.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[area] fitting Umbrella for fitting related work [priority] high Should be prioritized soon [scope] maintenance Code/tooling cleanup, no feature or bugfix (major.minor.PATCH)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants