Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-emcee for openSUSE:Factory checked in at 2024-04-21 20:27:20 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-emcee (Old) and /work/SRC/openSUSE:Factory/.python-emcee.new.26366 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-emcee" Sun Apr 21 20:27:20 2024 rev:8 rq:1169367 version:3.1.6 Changes: -------- --- /work/SRC/openSUSE:Factory/python-emcee/python-emcee.changes 2023-01-28 19:01:15.896034985 +0100 +++ /work/SRC/openSUSE:Factory/.python-emcee.new.26366/python-emcee.changes 2024-04-21 20:28:49.081305303 +0200 @@ -1,0 +2,16 @@ +Sat Apr 20 13:53:33 UTC 2024 - Dirk Müller <[email protected]> + +- update to 3.1.6: + * Compat fix for older numpy versions +- update to 3.1.5: + * Update blobs docs + * Fix integrated_time docstring + * Fixed DEMove Implementation + * Move proposals should match the dtype of original input + * Update the Read the Docs configuration + * Fix moves documentation typos + * Update EnsembleSampler docstring in ensemble.py + * Fix typo in assertion message + * MAINT: updates for numpy2 closes #509 + +------------------------------------------------------------------- Old: ---- emcee-3.1.4.tar.gz New: ---- emcee-3.1.6.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-emcee.spec ++++++ --- /var/tmp/diff_new_pack.10FJDF/_old 2024-04-21 20:28:51.389390028 +0200 +++ /var/tmp/diff_new_pack.10FJDF/_new 2024-04-21 20:28:51.389390028 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-emcee # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -20,7 +20,7 @@ # NEP 29: python36-numpy and -scipy are no longer available in TW %define skip_python36 1 Name: python-emcee -Version: 3.1.4 +Version: 3.1.6 Release: 0 Summary: Python affine-invariant ensemble MCMC sampling License: MIT ++++++ emcee-3.1.4.tar.gz -> emcee-3.1.6.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/.github/workflows/tests.yml new/emcee-3.1.6/.github/workflows/tests.yml --- old/emcee-3.1.4/.github/workflows/tests.yml 2023-01-27 13:19:09.000000000 +0100 +++ new/emcee-3.1.6/.github/workflows/tests.yml 2024-04-19 11:49:57.000000000 +0200 @@ -16,7 +16,7 @@ runs-on: ${{ matrix.os }} strategy: matrix: - python-version: ["3.7", "3.8", "3.9", "3.10"] + python-version: ["3.9", "3.10", "3.11", "3.12"] os: ["ubuntu-latest"] include: - python-version: "3.9" @@ -26,11 +26,11 @@ steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies @@ -49,12 +49,41 @@ COVERALLS_PARALLEL: true COVERALLS_FLAG_NAME: ${{ matrix.python-version }}-${{ matrix.os }} + numpy_edge: + runs-on: ${{ matrix.os }} + strategy: + matrix: + python-version: ["3.12"] + numpy-version: ["numpy>=2.0.0rc1"] + os: ["ubuntu-latest"] + include: + - python-version: "3.9" + numpy-version: "numpy<1.25" + os: "ubuntu-latest" + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install -U pip + python -m pip install pip install pytest "${{ matrix.numpy-version }}" + python -m pip install -e. + - name: Run tests + run: pytest + coverage: needs: tests runs-on: ubuntu-latest steps: - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.9" - name: Finish coverage collection @@ -68,11 +97,11 @@ lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup Python - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: "3.9" - name: Install dependencies @@ -85,10 +114,10 @@ build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 name: Install Python with: python-version: "3.9" @@ -97,7 +126,7 @@ python -m pip install -U pip python -m pip install -U build python -m build . - - uses: actions/upload-artifact@v3 + - uses: actions/upload-artifact@v4 with: path: dist/* @@ -106,12 +135,12 @@ runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/') steps: - - uses: actions/download-artifact@v3 + - uses: actions/download-artifact@v4 with: name: artifact path: dist - - uses: pypa/[email protected] + - uses: pypa/[email protected] with: user: __token__ password: ${{ secrets.pypi_password }} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/.pre-commit-config.yaml new/emcee-3.1.6/.pre-commit-config.yaml --- old/emcee-3.1.4/.pre-commit-config.yaml 2023-01-27 13:19:09.000000000 +0100 +++ new/emcee-3.1.6/.pre-commit-config.yaml 2024-04-19 11:49:57.000000000 +0200 @@ -1,13 +1,13 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.6.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: debug-statements - repo: https://github.com/PyCQA/isort - rev: "5.11.4" + rev: "5.13.2" hooks: - id: isort args: [] @@ -15,6 +15,6 @@ exclude: docs/tutorials - repo: https://github.com/psf/black - rev: "22.12.0" + rev: "24.4.0" hooks: - id: black-jupyter diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/.readthedocs.yaml new/emcee-3.1.6/.readthedocs.yaml --- old/emcee-3.1.4/.readthedocs.yaml 1970-01-01 01:00:00.000000000 +0100 +++ new/emcee-3.1.6/.readthedocs.yaml 2024-04-19 11:49:57.000000000 +0200 @@ -0,0 +1,19 @@ +version: 2 + +build: + os: ubuntu-20.04 + apt_packages: + - fonts-liberation + tools: + python: "3.10" + +python: + install: + - requirements: docs/requirements.txt + - method: pip + path: . + +sphinx: + configuration: docs/conf.py + fail_on_warning: true + builder: dirhtml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/PKG-INFO new/emcee-3.1.6/PKG-INFO --- old/emcee-3.1.4/PKG-INFO 2023-01-27 13:19:19.915073600 +0100 +++ new/emcee-3.1.6/PKG-INFO 2024-04-19 11:50:06.431932700 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: emcee -Version: 3.1.4 +Version: 3.1.6 Summary: The Python ensemble sampling toolkit for MCMC Home-page: https://emcee.readthedocs.io Author: Daniel Foreman-Mackey @@ -16,10 +16,16 @@ Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Description-Content-Type: text/x-rst -Provides-Extra: extras -Provides-Extra: tests License-File: LICENSE License-File: AUTHORS.rst +Requires-Dist: numpy +Provides-Extra: extras +Requires-Dist: h5py; extra == "extras" +Requires-Dist: scipy; extra == "extras" +Provides-Extra: tests +Requires-Dist: pytest; extra == "tests" +Requires-Dist: pytest-cov; extra == "tests" +Requires-Dist: coverage[toml]; extra == "tests" emcee ===== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/docs/tutorials/monitor.ipynb new/emcee-3.1.6/docs/tutorials/monitor.ipynb --- old/emcee-3.1.4/docs/tutorials/monitor.ipynb 2023-01-27 13:19:09.000000000 +0100 +++ new/emcee-3.1.6/docs/tutorials/monitor.ipynb 2024-04-19 11:49:57.000000000 +0200 @@ -54,6 +54,7 @@ "\n", "np.random.seed(42)\n", "\n", + "\n", "# The definition of the log probability function\n", "# We'll also use the \"blobs\" feature to track the \"log prior\" for each step\n", "def log_prob(theta):\n", @@ -338,6 +339,7 @@ "source": [ "run2_backend = emcee.backends.HDFBackend(filename, name=\"mcmc_second_prior\")\n", "\n", + "\n", "# this time, with a subtly different prior\n", "def log_prob2(theta):\n", " log_prior = -0.5 * np.sum((theta - 2.0) ** 2 / 100.0)\n", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/docs/tutorials/moves.ipynb new/emcee-3.1.6/docs/tutorials/moves.ipynb --- old/emcee-3.1.4/docs/tutorials/moves.ipynb 2023-01-27 13:19:09.000000000 +0100 +++ new/emcee-3.1.6/docs/tutorials/moves.ipynb 2024-04-19 11:49:57.000000000 +0200 @@ -160,7 +160,7 @@ "source": [ "For \"lightly\" multimodal problems like these, some combination of the {class}`moves.DEMove` and {class}`moves.DESnookerMove` can often perform better than the default.\n", "In this case, let's use a weighted mixture of the two moves.\n", - "In deatil, this means that, at each step, we'll randomly select either a :class:`moves.DEMove` (with 80% probability) or a {class}`moves.DESnookerMove` (with 20% probability)." + "In detail, this means that, at each step, we'll randomly select either a {class}`moves.DEMove` (with 80% probability) or a {class}`moves.DESnookerMove` (with 20% probability)." ] }, { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/docs/user/blobs.rst new/emcee-3.1.6/docs/user/blobs.rst --- old/emcee-3.1.4/docs/user/blobs.rst 2023-01-27 13:19:09.000000000 +0100 +++ new/emcee-3.1.6/docs/user/blobs.rst 2024-04-19 11:49:57.000000000 +0200 @@ -12,12 +12,22 @@ the sampler will do type inference to save the simplest possible representation of the blobs. +Anything that your ``log_prob`` function returns in addition to the log +probability is assumed to be a blob and is tracked as part of blobs. +Put another way, if ``log_prob`` returns more than one thing, all the things +after the first (which is assumed to be the log probability) are assumed to be +blobs. +If ``log_prob`` returns ``-np.inf`` for the log probability, the blobs are not +inspected or tracked so can be anything (but the correct number of arguments +must still be returned). + Using blobs to track the value of the prior ------------------------------------------- A common pattern is to save the value of the log prior at every step in the chain. -To do this, you could do something like: +To do this, your ``log_prob`` function should return your blobs (in this case log prior) as well as the log probability when called. +This can be implemented something like: .. code-block:: python @@ -33,10 +43,19 @@ def log_prob(params): lp = log_prior(params) if not np.isfinite(lp): - return -np.inf, -np.inf + # log prior is not finite, return -np.inf for log probability + # and None for log prior as it won't be used anyway (but we + # must use the correct number of return values) + return -np.inf, None ll = log_like(params) if not np.isfinite(ll): - return lp, -np.inf + # log likelihood is not finite, return -np.inf for log + # probability and None for log prior (again, this value isn't + # used but we have to have the correct number of return values) + return -np.inf, None + + # return log probability (sum of log prior and log likelihood) + # and log prior. Log prior will be saved as part of the blobs. return lp + ll, lp coords = np.random.randn(32, 3) @@ -50,8 +69,9 @@ print(log_prior_samps.shape) # (100, 32) print(flat_log_prior_samps.shape) # (3200,) -After running this, the "blobs" stored by the sampler will be a ``(nsteps, -nwalkers)`` NumPy array with the value of the log prior at every sample. +As shown above, after running this, the "blobs" stored by the sampler will be +a ``(nsteps, nwalkers)`` NumPy array with the value of the log prior at every +sample. Named blobs & custom dtypes --------------------------- @@ -60,6 +80,9 @@ them. To implement this, we use the ``blobs_dtype`` argument in :class:`EnsembleSampler`. +Using this is also helpful to specify types. +If you don't provide ``blobs_dtype``, the dtype of the extra args is automatically guessed the first time ``log_prob`` is called. + For example, let's say that, for some reason, we wanted to save the mean of the parameters as well as the log prior. To do this, we would update the above example as follows: @@ -69,16 +92,25 @@ def log_prob(params): lp = log_prior(params) if not np.isfinite(lp): - return -np.inf, -np.inf, -np.inf + # As above, log prior is not finite, so return -np.inf for log + # probability and None for everything else (these values aren't + # used, but the number of return values must be correct) + return -np.inf, None, None ll = log_like(params) if not np.isfinite(ll): - return lp, -np.inf, -np.inf + # Log likelihood is not finite so return -np.inf for log + # probabilitiy and None for everything else (maintaining the + # correct number of return values) + return -np.inf, None, None + + # All values are finite, so return desired blobs (in this case: log + # probability, log prior and mean of parameters) return lp + ll, lp, np.mean(params) coords = np.random.randn(32, 3) nwalkers, ndim = coords.shape - # Here are the important lines + # Here are the important lines for defining the blobs_dtype dtype = [("log_prior", float), ("mean", float)] sampler = emcee.EnsembleSampler(nwalkers, ndim, log_prob, blobs_dtype=dtype) @@ -88,14 +120,14 @@ blobs = sampler.get_blobs() log_prior_samps = blobs["log_prior"] mean_samps = blobs["mean"] - print(log_prior_samps.shape) - print(mean_samps.shape) + print(log_prior_samps.shape) # (100, 32) + print(mean_samps.shape) # (100, 32) flat_blobs = sampler.get_blobs(flat=True) flat_log_prior_samps = flat_blobs["log_prior"] flat_mean_samps = flat_blobs["mean"] - print(flat_log_prior_samps.shape) - print(flat_mean_samps.shape) + print(flat_log_prior_samps.shape) # (3200,) + print(flat_mean_samps.shape) # (3200,) This will print diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/readthedocs.yml new/emcee-3.1.6/readthedocs.yml --- old/emcee-3.1.4/readthedocs.yml 2023-01-27 13:19:09.000000000 +0100 +++ new/emcee-3.1.6/readthedocs.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,13 +0,0 @@ -version: 2 - -python: - version: 3.8 - install: - - requirements: docs/requirements.txt - - method: pip - path: . - -sphinx: - configuration: docs/conf.py - fail_on_warning: true - builder: dirhtml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/src/emcee/autocorr.py new/emcee-3.1.6/src/emcee/autocorr.py --- old/emcee-3.1.4/src/emcee/autocorr.py 2023-01-27 13:19:09.000000000 +0100 +++ new/emcee-3.1.6/src/emcee/autocorr.py 2024-04-19 11:49:57.000000000 +0200 @@ -46,7 +46,7 @@ return len(taus) - 1 -def integrated_time(x, c=5, tol=50, quiet=False): +def integrated_time(x, c=5, tol=50, quiet=False, has_walkers=True): """Estimate the integrated autocorrelation time of a time series. This estimate uses the iterative procedure described on page 16 of @@ -54,9 +54,11 @@ determine a reasonable window size. Args: - x: The time series. If multidimensional, set the time axis using the - ``axis`` keyword argument and the function will be computed for - every other axis. + x (numpy.ndarray): The time series. If 2-dimensional, the array + dimesions are interpreted as ``(n_step, n_walker)`` unless + ``has_walkers==False``, in which case they are interpreted as + ``(n_step, n_param)``. If 3-dimensional, the dimensions are + interperted as ``(n_step, n_walker, n_param)``. c (Optional[float]): The step size for the window search. (default: ``5``) tol (Optional[float]): The minimum number of autocorrelation times @@ -64,10 +66,13 @@ quiet (Optional[bool]): This argument controls the behavior when the chain is too short. If ``True``, give a warning instead of raising an :class:`AutocorrError`. (default: ``False``) + has_walkers (Optional[bool]): Whether the last axis should be + interpreted as walkers or parameters if ``x`` has 2 dimensions. + (default: ``True``) Returns: float or array: An estimate of the integrated autocorrelation time of - the time series ``x`` computed along the axis ``axis``. + the time series ``x``. Raises AutocorrError: If the autocorrelation time can't be reliably estimated @@ -79,7 +84,10 @@ if len(x.shape) == 1: x = x[:, np.newaxis, np.newaxis] if len(x.shape) == 2: - x = x[:, :, np.newaxis] + if not has_walkers: + x = x[:, np.newaxis, :] + else: + x = x[:, :, np.newaxis] if len(x.shape) != 3: raise ValueError("invalid dimensions") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/src/emcee/emcee_version.py new/emcee-3.1.6/src/emcee/emcee_version.py --- old/emcee-3.1.4/src/emcee/emcee_version.py 2023-01-27 13:19:19.000000000 +0100 +++ new/emcee-3.1.6/src/emcee/emcee_version.py 2024-04-19 11:50:06.000000000 +0200 @@ -1 +1 @@ -__version__ = "3.1.4" +__version__ = "3.1.6" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/src/emcee/ensemble.py new/emcee-3.1.6/src/emcee/ensemble.py --- old/emcee-3.1.4/src/emcee/ensemble.py 2023-01-27 13:19:09.000000000 +0100 +++ new/emcee-3.1.6/src/emcee/ensemble.py 2024-04-19 11:49:57.000000000 +0200 @@ -21,6 +21,13 @@ # for py2.7, will be an Exception in 3.8 from collections import Iterable +try: + # Try to import from numpy.exceptions (available in NumPy 1.25 and later) + from numpy.exceptions import VisibleDeprecationWarning +except ImportError: + # Fallback to the top-level numpy import (for older versions) + from numpy import VisibleDeprecationWarning + class EnsembleSampler(object): """An ensemble MCMC sampler @@ -45,10 +52,10 @@ (default: :class:`StretchMove`) args (Optional): A list of extra positional arguments for ``log_prob_fn``. ``log_prob_fn`` will be called with the sequence - ``log_pprob_fn(p, *args, **kwargs)``. + ``log_prob_fn(p, *args, **kwargs)``. kwargs (Optional): A dict of extra keyword arguments for ``log_prob_fn``. ``log_prob_fn`` will be called with the sequence - ``log_pprob_fn(p, *args, **kwargs)``. + ``log_prob_fn(p, *args, **kwargs)``. pool (Optional): An object with a ``map`` method that follows the same calling sequence as the built-in ``map`` function. This is generally used to compute the log-probabilities for the ensemble @@ -179,7 +186,7 @@ if name not in dupes: uniq.append(name) dupes.add(name) - msg = f"duplicate paramters: {dupes}" + msg = f"duplicate parameters: {dupes}" assert len(uniq) == len(parameter_names), msg if isinstance(parameter_names, list): @@ -489,10 +496,19 @@ results = list(map_func(self.log_prob_fn, p)) try: - log_prob = np.array([float(l[0]) for l in results]) - blob = [l[1:] for l in results] + # perhaps log_prob_fn returns blobs? + + # deal with the blobs first + # if l does not have a len attribute (i.e. not a sequence, no blob) + # then a TypeError is raised. However, no error will be raised if + # l is a length-1 array, np.array([1.234]). In that case blob + # will become an empty list. + blob = [l[1:] for l in results if len(l) > 1] + if not len(blob): + raise IndexError + log_prob = np.array([_scalar(l[0]) for l in results]) except (IndexError, TypeError): - log_prob = np.array([float(l) for l in results]) + log_prob = np.array([_scalar(l) for l in results]) blob = None else: # Get the blobs dtype @@ -502,7 +518,7 @@ try: with warnings.catch_warnings(record=True): warnings.simplefilter( - "error", np.VisibleDeprecationWarning + "error", VisibleDeprecationWarning ) try: dt = np.atleast_1d(blob[0]).dtype @@ -682,3 +698,16 @@ list of dictionaries of parameters """ return [{key: xi[val] for key, val in key_map.items()} for xi in x] + + +def _scalar(fx): + # Make sure a value is a true scalar + # 1.0, np.float64(1.0), np.array([1.0]), np.array(1.0) + if not np.isscalar(fx): + try: + fx = np.asarray(fx).item() + except (TypeError, ValueError) as e: + raise ValueError("log_prob_fn should return scalar") from e + return float(fx) + else: + return float(fx) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/src/emcee/moves/de.py new/emcee-3.1.6/src/emcee/moves/de.py --- old/emcee-3.1.4/src/emcee/moves/de.py 2023-01-27 13:19:09.000000000 +0100 +++ new/emcee-3.1.6/src/emcee/moves/de.py 2024-04-19 11:49:57.000000000 +0200 @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +from functools import lru_cache import numpy as np @@ -13,7 +14,7 @@ This `Differential evolution proposal <http://www.stat.columbia.edu/~gelman/stuff_for_blog/cajo.pdf>`_ is implemented following `Nelson et al. (2013) - <https://arxiv.org/abs/1311.5229>`_. + <https://doi.org/10.1088/0067-0049/210/1/11>`_. Args: sigma (float): The standard deviation of the Gaussian used to stretch @@ -27,8 +28,7 @@ def __init__(self, sigma=1.0e-5, gamma0=None, **kwargs): self.sigma = sigma self.gamma0 = gamma0 - kwargs["nsplits"] = 3 - super(DEMove, self).__init__(**kwargs) + super().__init__(**kwargs) def setup(self, coords): self.g0 = self.gamma0 @@ -38,14 +38,40 @@ self.g0 = 2.38 / np.sqrt(2 * ndim) def get_proposal(self, s, c, random): - Ns = len(s) - Nc = list(map(len, c)) - ndim = s.shape[1] - q = np.empty((Ns, ndim), dtype=np.float64) - f = self.sigma * random.randn(Ns) - for i in range(Ns): - w = np.array([c[j][random.randint(Nc[j])] for j in range(2)]) - random.shuffle(w) - g = np.diff(w, axis=0) * self.g0 + f[i] - q[i] = s[i] + g - return q, np.zeros(Ns, dtype=np.float64) + c = np.concatenate(c, axis=0) + ns, ndim = s.shape + nc = c.shape[0] + + # Get the pair indices + pairs = _get_nondiagonal_pairs(nc) + + # Sample from the pairs + indices = random.choice(pairs.shape[0], size=ns, replace=True) + pairs = pairs[indices] + + # Compute diff vectors + diffs = np.diff(c[pairs], axis=1).squeeze(axis=1) # (ns, ndim) + + # Sample a gamma value for each walker following Nelson et al. (2013) + gamma = self.g0 * (1 + self.sigma * random.randn(ns, 1)) # (ns, 1) + + # In this way, sigma is the standard deviation of the distribution of gamma, + # instead of the standard deviation of the distribution of the proposal as proposed by Ter Braak (2006). + # Otherwise, sigma should be tuned for each dimension, which confronts the idea of affine-invariance. + + q = s + gamma * diffs + + return q, np.zeros(ns, dtype=np.float64) + + +@lru_cache(maxsize=1) +def _get_nondiagonal_pairs(n: int) -> np.ndarray: + """Get the indices of a square matrix with size n, excluding the diagonal.""" + rows, cols = np.tril_indices(n, -1) # -1 to exclude diagonal + + # Combine rows-cols and cols-rows pairs + pairs = np.column_stack( + [np.concatenate([rows, cols]), np.concatenate([cols, rows])] + ) + + return pairs diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/src/emcee/moves/de_snooker.py new/emcee-3.1.6/src/emcee/moves/de_snooker.py --- old/emcee-3.1.4/src/emcee/moves/de_snooker.py 2023-01-27 13:19:09.000000000 +0100 +++ new/emcee-3.1.6/src/emcee/moves/de_snooker.py 2024-04-19 11:49:57.000000000 +0200 @@ -32,7 +32,7 @@ Ns = len(s) Nc = list(map(len, c)) ndim = s.shape[1] - q = np.empty((Ns, ndim), dtype=np.float64) + q = np.empty_like(s) metropolis = np.empty(Ns, dtype=np.float64) for i in range(Ns): w = np.array([c[j][random.randint(Nc[j])] for j in range(3)]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/src/emcee/moves/gaussian.py new/emcee-3.1.6/src/emcee/moves/gaussian.py --- old/emcee-3.1.4/src/emcee/moves/gaussian.py 2023-01-27 13:19:09.000000000 +0100 +++ new/emcee-3.1.6/src/emcee/moves/gaussian.py 2024-04-19 11:49:57.000000000 +0200 @@ -60,7 +60,6 @@ class _isotropic_proposal(object): - allowed_modes = ["vector", "random", "sequential"] def __init__(self, scale, factor, mode): @@ -111,7 +110,6 @@ class _proposal(_isotropic_proposal): - allowed_modes = ["vector"] def get_updated_vector(self, rng, x0): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/src/emcee/moves/walk.py new/emcee-3.1.6/src/emcee/moves/walk.py --- old/emcee-3.1.4/src/emcee/moves/walk.py 2023-01-27 13:19:09.000000000 +0100 +++ new/emcee-3.1.6/src/emcee/moves/walk.py 2024-04-19 11:49:57.000000000 +0200 @@ -28,7 +28,7 @@ c = np.concatenate(c, axis=0) Ns, Nc = len(s), len(c) ndim = s.shape[1] - q = np.empty((Ns, ndim), dtype=np.float64) + q = np.empty_like(s) s0 = Nc if self.s is None else self.s for i in range(Ns): inds = random.choice(Nc, s0, replace=False) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/src/emcee/tests/unit/test_autocorr.py new/emcee-3.1.6/src/emcee/tests/unit/test_autocorr.py --- old/emcee-3.1.4/src/emcee/tests/unit/test_autocorr.py 2023-01-27 13:19:09.000000000 +0100 +++ new/emcee-3.1.6/src/emcee/tests/unit/test_autocorr.py 2024-04-19 11:49:57.000000000 +0200 @@ -28,6 +28,13 @@ assert np.all(np.abs(tau - 19.0) / 19.0 < 0.2) +def test_nd_without_walkers(seed=1234, ndim=3, N=10000): + x = get_chain(seed=seed, ndim=ndim, N=N) + tau1 = integrated_time(x[:, np.newaxis]) + tau2 = integrated_time(x, has_walkers=False) + assert np.allclose(tau1, tau2) + + def test_too_short(seed=1234, ndim=3, N=100): x = get_chain(seed=seed, ndim=ndim, N=N) with pytest.raises(AutocorrError): @@ -39,10 +46,9 @@ np.random.seed(42) xs = np.random.randn(16384, 2) - # This throws exception unconditionally in buggy impl's - acls_multi = integrated_time(xs) + acls_multi = integrated_time(xs[:, np.newaxis]) acls_single = np.array( [integrated_time(xs[:, i]) for i in range(xs.shape[1])] - ) + ).squeeze() - assert np.all(np.abs(acls_multi - acls_single) < 2) + assert np.allclose(acls_multi, acls_single) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/src/emcee/tests/unit/test_ensemble.py new/emcee-3.1.6/src/emcee/tests/unit/test_ensemble.py --- old/emcee-3.1.4/src/emcee/tests/unit/test_ensemble.py 2023-01-27 13:19:09.000000000 +0100 +++ new/emcee-3.1.6/src/emcee/tests/unit/test_ensemble.py 2024-04-19 11:49:57.000000000 +0200 @@ -1,6 +1,7 @@ """ Unit tests of some functionality in ensemble.py when the parameters are named """ + import string from unittest import TestCase @@ -182,3 +183,37 @@ assert results.coords.shape == (n_walkers, len(self.names)) chain = sampler.chain assert chain.shape == (n_walkers, n_steps, len(self.names)) + + +class TestLnProbFn(TestCase): + # checks that the log_prob_fn can deal with a variety of 'scalar-likes' + def lnpdf(self, x): + v = np.log(np.sqrt(np.pi) * np.exp(-((x / 2.0) ** 2))) + v = float(v[0]) + assert np.isscalar(v) + return v + + def lnpdf_arr1(self, x): + v = self.lnpdf(x) + return np.array([v]) + + def lnpdf_float64(self, x): + v = self.lnpdf(x) + return np.float64(v) + + def lnpdf_arr0D(self, x): + v = self.lnpdf(x) + return np.array(v) + + def test_deal_with_scalar_likes(self): + rng = np.random.default_rng() + fns = [ + self.lnpdf, + self.lnpdf_arr1, + self.lnpdf_float64, + self.lnpdf_arr0D, + ] + for fn in fns: + init = rng.random((50, 1)) + sampler = EnsembleSampler(50, 1, fn) + _ = sampler.run_mcmc(initial_state=init, nsteps=20) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/src/emcee.egg-info/PKG-INFO new/emcee-3.1.6/src/emcee.egg-info/PKG-INFO --- old/emcee-3.1.4/src/emcee.egg-info/PKG-INFO 2023-01-27 13:19:19.000000000 +0100 +++ new/emcee-3.1.6/src/emcee.egg-info/PKG-INFO 2024-04-19 11:50:06.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: emcee -Version: 3.1.4 +Version: 3.1.6 Summary: The Python ensemble sampling toolkit for MCMC Home-page: https://emcee.readthedocs.io Author: Daniel Foreman-Mackey @@ -16,10 +16,16 @@ Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Description-Content-Type: text/x-rst -Provides-Extra: extras -Provides-Extra: tests License-File: LICENSE License-File: AUTHORS.rst +Requires-Dist: numpy +Provides-Extra: extras +Requires-Dist: h5py; extra == "extras" +Requires-Dist: scipy; extra == "extras" +Provides-Extra: tests +Requires-Dist: pytest; extra == "tests" +Requires-Dist: pytest-cov; extra == "tests" +Requires-Dist: coverage[toml]; extra == "tests" emcee ===== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/src/emcee.egg-info/SOURCES.txt new/emcee-3.1.6/src/emcee.egg-info/SOURCES.txt --- old/emcee-3.1.4/src/emcee.egg-info/SOURCES.txt 2023-01-27 13:19:19.000000000 +0100 +++ new/emcee-3.1.6/src/emcee.egg-info/SOURCES.txt 2024-04-19 11:50:06.000000000 +0200 @@ -1,6 +1,7 @@ .gitattributes .gitignore .pre-commit-config.yaml +.readthedocs.yaml AUTHORS.rst CODE_OF_CONDUCT.md CONTRIBUTING.md @@ -10,7 +11,6 @@ README.rst VISION.md pyproject.toml -readthedocs.yml setup.py tox.ini .github/ISSUE_TEMPLATE.md diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/emcee-3.1.4/tox.ini new/emcee-3.1.6/tox.ini --- old/emcee-3.1.4/tox.ini 2023-01-27 13:19:09.000000000 +0100 +++ new/emcee-3.1.6/tox.ini 2024-04-19 11:49:57.000000000 +0200 @@ -1,12 +1,12 @@ [tox] -envlist = py{37,38,39,310}{,-extras},lint +envlist = py{39,310,311,312}{,-extras},lint [gh-actions] python = - 3.7: py37 - 3.8: py38 - 3.9: py39-extras + 3.9: py39 3.10: py310 + 3.11: py311-extras + 3.12: py312 [testenv] deps = coverage[toml]
