Release Notes

v0.7.6

This is a patch release from v0.7.5v0.7.6.

Fixes

Contributors

v0.7.6 benefited from contributions from:

  • Lorenz Gaertner

v0.7.5

This is a patch release from v0.7.4v0.7.5.

Fixes

  • Remove operating system dependent components of schema validation to allow for validation on Windows. (PR #2357)

v0.7.4

This is a patch release from v0.7.3v0.7.4.

Fixes

  • Skip callbacks with dead weakrefs while iterating over callbacks in pyhf events, like pyhf.set_backend(), to avoid the possibility of accessing dead weakrefs before they could be garbage collected. (PR #2310)

    The fixed bug was subtle and occurred nondeterministically when the pyhf.tensorlib was changed repeatedly causing dead weakrefs to be accessed before Python’s garbage collection could remove them. Most users should be unaffected.

Contributors

v0.7.4 benefited from contributions from:

  • Daniel Werner

  • Jonas Rembser

v0.7.3

This is a patch release from v0.7.2v0.7.3.

Fixes

  • Use numpy.prod() API over numpy.product as numpy.product is deprecated as of NumPy v1.25.0. (PR #2242)

  • Guard pyhf.optimize.opt_minuit.minuit_optimizer optimizer strategy from None to ensure iminuit.Minuit.strategy strategies are correctly handled. (PRs #2277, #2278)

    The fixed bug was subtle and only occurred for specific configurations of settings and arguments where do_grad=False was used (either explicitly by provided kwarg or implicitly through defaults). To determine if you might have been affected by it, check your code for setups like the following.

    # Bug is backend independent. JAX is selected as an example where
    # do_grad=False might be selected in response to the backend's value of
    # pyhf.tensorlib.default_do_grad being True.
    pyhf.set_backend("jax", pyhf.optimize.minuit_optimizer(strategy=0))
    
    ...
    
    fit_result, opt_result = pyhf.infer.mle.fit(
        data, model, return_result_obj=True, do_grad=False
    )
    assert opt_result.minuit.strategy.strategy == 0  # fails for pyhf v0.7.2
    

    Full example that fails in pyhf v0.7.2:

    import pyhf
    
    pyhf.set_backend("jax", pyhf.optimize.minuit_optimizer(strategy=0))
    
    model = pyhf.simplemodels.uncorrelated_background(
        signal=[12.0, 11.0], bkg=[50.0, 52.0], bkg_uncertainty=[3.0, 7.0]
    )
    data = [51, 48] + model.config.auxdata
    
    # passing with strategy kwarg explicitly given
    fit_result, opt_result = pyhf.infer.mle.fit(
        data, model, return_result_obj=True, do_grad=False, strategy=0
    )
    minuit_strategy = opt_result.minuit.strategy.strategy
    print(f"# Minuit minimization strategy: {minuit_strategy}")
    assert minuit_strategy == 0
    
    # strategy kwarg not given
    fit_result, opt_result = pyhf.infer.mle.fit(
        data, model, return_result_obj=True, do_grad=False
    )
    minuit_strategy = opt_result.minuit.strategy.strategy
    print(f"# Minuit minimization strategy: {minuit_strategy}")
    assert minuit_strategy == 0  # fails for pyhf v0.7.2
    

Contributors

v0.7.3 benefited from contributions from:

  • Alexander Held

  • Daniel Werner

v0.7.2

This is a patch release from v0.7.1v0.7.2.

Important Notes

  • pyhf became a NumFOCUS Affiliated Project on 2022-12-19. NumFOCUS Affiliated Project v0.7.1 is the first release to appear in a NumFOCUS Newsletter and v0.7.2 is the first release to appear as part of the Affiliated Projects page. (PR #2179)

Fixes

Contributors

v0.7.2 benefited from contributions from:

  • Alexander Held

v0.7.1

This is a patch release from v0.7.0v0.7.1.

Important Notes

  • All backends are now fully compatible and tested with Python 3.11. (PR #2145)

  • The tensorflow extra ('pyhf[tensorflow]') now automatically installs tensorflow-macos for Apple silicon machines. (PR #2119)

Fixes

Contributors

v0.7.1 benefited from contributions from:

  • Alexander Held

v0.7.0

This is a minor release from v0.6.3v0.7.0.

Important Notes

  • Please note this release has API breaking changes and carefully read these notes while updating your code to the v0.7.0 API.

  • All backends are now fully compatible and tested with Python 3.10. (PR #1809)

  • The pyhf.tensorlib.poisson API now allows for the expected rate parameter lam to be 0 in the case that the observed events n is 0 given that the limit \(\lim_{\lambda \to 0} \,\mathrm{Pois}(n | \lambda)\) is well defined. (PR #1657)

  • pyhf.readxml.parse() now supports reading of XML configurations with absolute paths. To support this, pyhf xlm2json now has a -v/--mount option. (PR #1909)

  • Support for model specifications without a parameter of interest defined is added. (PRs #1638, #1636)

  • The pyhf.parameters.paramsets classes suggested_fixed attribute behavior has been updated. To access the behavior used in pyhf v0.6.x use the suggested_fixed_as_bool attribute. (PR #1639)

  • pyhf.pdf._ModelConfig.par_names is changed to be a property attribute. (PR #2027)

  • The order of model parameters is now sorted by model parameter name. (PR #1625)

  • Support for writing user custom modifiers is added. (PRs #1625, #1644)

  • Performance in pyhf.readxml is increased by improvements to pyhf.readxml.import_root_histogram(). (PR #1691)

  • pyhf.contrib.utils.download() is now more robust to different target file types. (PRs #1697, #1704)

  • A pyhf.default_backend has been added that is configurable through a default kwarg in pyhf.set_backend(). (PR #1646) This is part of work to make pyhf fully automatic differentiable. (Issue #882)

  • Schema validation now allows for both list and pyhf.tensorlib objects to exist in the model specification. (PR #1647)

  • The minimum required dependencies have been updated to support added features:

    • scipy>=1.2.0 (PR #1274)

    • click>=8.0.0 (PRs #1909, #1958)

    • jsonschema>=4.15.0 (PRs #1976, #1979)

    • importlib_resources>=1.4.0 (for Python 3.7, 3.8) (PR #1979)

    • typing_extensions>=3.7.4.3 (for Python 3.7 only) (PRs #1940, #1961)

  • The minimum required backend versions have been updated to support added features:

    • JAX backend requires jax>=0.2.10, jaxlib>=0.1.61 (PR #1962)

    • PyTorch backend requires torch>=1.10.0 (PR #1657)

    • TensorFlow backend requires tensorflow>=2.7.0, tensorflow-probability>=0.11.0 (PRs #1962, #1657)

    • iminuit optimizer requires iminuit>=2.7.0 (PR #1895)

    • 'xmlio' extra requires uproot>=4.1.1 (PR #1567)

Fixes

Features

Python API

  • The following functions have been added to the pyhf.tensorlib API:

    • pyhf.tensorlib.transpose (PR #1696)

    • pyhf.tensorlib.percentile (PR #817)

  • pyhf.readxml.parse() now supports reading of XML configurations with absolute paths with the addition of the mounts optional argument. (PR #1909)

  • Support for overriding the paths for finding schemas is added, using the pyhf installed location as a base via pyhf.utils.schemas. (PRs #1753, #1818)

    >>> from pathlib import Path
    >>> import pyhf.schema
    >>> current_schema_path = pyhf.schema.path
    >>> current_schema_path
    PosixPath('/path/to/your/venv/lib/python3.X/site-packages/pyhf/schemas')
    >>> custom_schema_path = Path("/path/to/custom/pyhf/schema")
    >>> with pyhf.schema(custom_schema_path):
    ...     print(repr(pyhf.schema.path))
    ...
    PosixPath('/path/to/custom/pyhf/schema')
    >>> pyhf.schema.path
    PosixPath('/path/to/your/venv/lib/python3.X/site-packages/pyhf/schemas')
    
  • In pyhf.workspace.Workspace.model() the parameter of interest specified in the measurement may now be overridden using the added poi_name kwarg. (PR #1636)

  • The pyhf.parameters.paramsets classes suggested_fixed attribute behavior has been updated to return a list of bool of length n_parameters. To access the behavior used in pyhf v0.6.x use the suggested_fixed_as_bool attribute. (PR #1639)

  • pyhf.pdf._ModelConfig.par_names is changed to be a property attribute. (PR #2027)

  • The order of model parameters is now sorted by model parameter name. (PR #1625)

    >>> import pyhf
    >>> model = pyhf.simplemodels.correlated_background(
    ...     signal=[12.0, 11.0],
    ...     bkg=[50.0, 52.0],
    ...     bkg_up=[45.0, 57.0],
    ...     bkg_down=[55.0, 47.0],
    ... )
    >>> model.config.par_order
    ['correlated_bkg_uncertainty', 'mu']
    >>> model.config.par_names
    ['correlated_bkg_uncertainty', 'mu']
    
  • Support for writing user custom modifiers is added. (PRs #1625, #1644) This is still in the stage where it is targeted at expert users.

  • {modifier}_builder classes are added for all modifiers. (PRs #1625) For example, pyhf.modifiers.histosys.histosys_builder.

  • When using pyhf.writexml and the normfactor parameter config is missing inits or bounds, fall back to using default values. (PRs #1819)

  • Supported options for pyhf.infer.hypotest() can now be passed as kwargs through the pyhf.infer.intervals.upper_limits.upper_limit() API. (PR #1613) This now enables things like using pyhf.infer.calculators.ToyCalculator as the calculator used for the hypothesis test scan:

    >>> import numpy as np
    >>> import pyhf
    >>> pyhf.set_backend("jax")
    >>> model = pyhf.simplemodels.uncorrelated_background(
    ...     signal=[12.0, 11.0], bkg=[50.0, 52.0], bkg_uncertainty=[3.0, 7.0]
    ... )
    >>> observations = [51, 48]
    >>> data = pyhf.tensorlib.astensor(observations + model.config.auxdata)
    >>> scan = np.linspace(0, 5, 21)
    >>> obs_limit, exp_limits, (scan, results) = pyhf.infer.intervals.upper_limits.upper_limit(
    ...     data, model, scan, return_results=True, calctype="toybased", ntoys=3000
    ... )
    
  • Allow for fit parameter values from required fits in pyhf.infer.test_statistics functions to be returned by use of return_fitted_pars kwarg with the pyhf.infer.test_statistics functions and return_calculator kwarg with pyhf.infer.hypotest(). (PR #1554)

  • A validate kwarg has been added to pyhf.workspace.Workspace() and pyhf.pdf.Model() to allow skipping validation. (PR #1646) This should only be used by expert users who understand the risks.

  • A pyhf.default_backend has been added that is configurable through a default kwarg in pyhf.set_backend(). (PR #1646) This allows setting the pyhf.default_backend to be different from the value of pyhf.tensorlib returned by pyhf.get_backend(), which can be useful in situations where differentiable model construction is needed.

    >>> import jax
    >>> import pyhf
    >>> pyhf.set_backend("jax", default=True)
    >>> pyhf.set_backend("numpy")
    >>> pyhf.get_backend()
    (<pyhf.tensor.numpy_backend.numpy_backend object at 0x...>, <pyhf.optimize.scipy_optimizer object at 0x...>)
    >>> pyhf.default_backend
    <pyhf.tensor.jax_backend.jax_backend object at 0x...>
    >>> def example_op(x):
    ...     return 2 * pyhf.default_backend.power(pyhf.default_backend.astensor(x), 3)
    ...
    >>> example_op([2.0])
    DeviceArray([16.], dtype=float64)
    >>> jax.jacrev(jax.jit(example_op))([2.0])
    [DeviceArray([24.], dtype=float64, weak_type=True)]
    
  • Schema validation now allows for both list and pyhf.tensorlib objects to exist in the model specification. (PR #1647)

    >>> import pyhf
    >>> signal = pyhf.tensorlib.astensor([12.0, 11.0])
    >>> background = pyhf.tensorlib.astensor([50.0, 52.0])
    >>> background_uncertainty = pyhf.tensorlib.astensor([3.0, 7.0])
    >>> model = pyhf.simplemodels.uncorrelated_background(
    ...     signal=signal, bkg=background, bkg_uncertainty=background_uncertainty
    ... )
    

CLI API

  • The pyhf xlm2json CLI API now has a -v/--mount option to support reading XML configurations with absolute paths. (PR #1909) Similar to Docker volume mounts, the options allows a user to pass two fields separated by a colon (:). The first field is a local path and the second field is the absolute path specified in the XML configuration to be substituted. Without the -v/--mount option a user would have to manually edit the absolute path in each XML file it appeared in!

    pyhf xml2json \
        --mount /local/path/to/workspace:/absolute/path/to/replace/inside/xml \
        --output-file workspace.json \
        workspace/analysis_config.xml
    

Deprecations

Python API

Removals

Python API

Contributors

v0.7.0 benefited from contributions from:

  • Alexander Held

  • Mason Proffitt

  • Lars Henkelmann

  • Aryan Roy

  • Graeme Watt

  • Jerry Ling

  • Nathan Simpson

  • Beojan Stanislaus

v0.6.3

This is a patch release from v0.6.2v0.6.3.

Important Notes

  • With the addition of writing ROOT files in uproot v4.1.0 the xmlio extra no longer requires uproot3 and all dependencies on uproot3 and uproot3-methods have been dropped. (PR #1567) uproot4 additionally brings large speedups to writing, which results in an order of magnitude faster conversion time for most workspace conversions from JSON back to XML + ROOT with pyhf json2xml.

  • All backends are now fully compatible and tested with Python 3.9. (PR #1574)

  • The TensorFlow backend now supports compatibility with TensorFlow v2.2.1 and later and TensorFlow Probability v0.10.1 and later. (PR #1001)

  • The pyhf.workspace.Workspace.data() with_aux keyword arg has been renamed to include_auxdata to improve API consistency. (PR #1562)

Fixes

  • The weakref bug with Click v8.0+ was resolved. pyhf is now fully compatible with Click v7 and v8 releases. (PR #1530)

Features

Python API

  • Model parameter names are now propagated to optimizers through addition of the pyhf.pdf._ModelConfig.par_names() API. pyhf.pdf._ModelConfig.par_names() also handles non-scalar modifiers with 1 parameter. (PRs #1536, #1560)

    >>> import pyhf
    >>> model = pyhf.simplemodels.uncorrelated_background(
    ...     signal=[12.0, 11.0], bkg=[50.0, 52.0], bkg_uncertainty=[3.0, 7.0]
    ... )
    >>> model.config.parameters
    ['mu', 'uncorr_bkguncrt']
    >>> model.config.npars
    3
    >>> model.config.par_names()
    ['mu', 'uncorr_bkguncrt[0]', 'uncorr_bkguncrt[1]']
    
  • The pyhf.pdf._ModelConfig channel_nbins dict is now sorted by keys to match the order of the channels list. (PR #1546)

  • The pyhf.workspace.Workspace.data() with_aux keyword arg has been renamed to include_auxdata to improve API consistency. (PR #1562)

v0.6.2

This is a patch release from v0.6.1v0.6.2.

Important Notes

  • The pyhf.simplemodels.hepdata_like() API has been deprecated in favor of pyhf.simplemodels.uncorrelated_background(). The pyhf.simplemodels.hepdata_like() API will be removed in pyhf v0.7.0. (PR #1438)

  • There is a small breaking API change for pyhf.contrib.viz.brazil.plot_results(). See the Python API changes section for more information.

  • The pyhf.patchset.PatchSet schema now allows string types for patch values in patchsets. (PR #1488)

  • Only lower bounds on core dependencies are now set. This allows for greater developer freedom and reduces the risk of breaking user’s applications by unnecessarily constraining libraries. This also means that users will be responsible for ensuring that their installed dependencies do not conflict with or break pyhf. c.f. Hynek Schlawack’s blog post Semantic Versioning Will Not Save You for more in-depth coverage on this topic. For most users nothing should change. This mainly affects developers of other libraries in which pyhf is a dependency. (PR #1382)

  • Calling dir() on any pyhf module or trying to tab complete an API will now provide a more helpfully restricted view of the available APIs. This should help provide better exploration of the pyhf API. (PR #1403)

  • Docker images of releases are now published to both Docker Hub and to the GitHub Container Registry. (PR #1444)

  • CUDA enabled Docker images are now available for release v0.6.1 and later on Docker Hub and the GitHub Container Registry. Visit github.com/pyhf/cuda-images for more information.

Fixes

  • Allow for precision to be properly set for the tensorlib ones and zeros methods through a dtype argument. This allows for precision to be properly set through the pyhf.set_backend() precision argument. (PR #1369)

  • The default precision for all backends is now 64b. (PR #1400)

  • Add check to ensure that POIs are not fixed during a fit. (PR #1409)

  • Parameter name strings are now normalized to remove trailing spaces. (PR #1436)

  • The logging level is now not automatically set in pyhf.contrib.utils. (PR #1460)

Features

Python API

CLI API

  • The CLI API now supports a patchset inspect API to list the individual patches in a PatchSet. (PR #1412)

pyhf patchset inspect [OPTIONS] [PATCHSET]

Contributors

v0.6.2 benefited from contributions from:

  • Alexander Held

v0.6.1

This is a patch release from v0.6.0v0.6.1.

Important Notes

  • As a result of changes to the default behavior of torch.distributions in PyTorch v1.8.0, accommodating changes have been made in the underlying implementations for pyhf.tensor.pytorch_backend.pytorch_backend(). These changes require a new lower bound of torch v1.8.0 for use of the PyTorch backend.

Fixes

  • In the PyTorch backend the validate_args kwarg is used with torch.distributions to ensure a continuous approximation of the Poisson distribution in torch v1.8.0+.

Features

Python API

  • The solver_options kwarg can be passed to the pyhf.optimize.opt_scipy.scipy_optimizer() optimizer for additional configuration of the minimization. See scipy.optimize.show_options() for additional options of optimization solvers.

  • The torch API is now used to provide the implementations of the ravel, tile, and outer tensorlib methods for the PyTorch backend.

v0.6.0

This is a minor release from v0.5.4v0.6.0.

Important Notes

  • Please note this release has API breaking changes and carefully read these notes while updating your code to the v0.6.0 API. Perhaps most relevant is the changes to the pyhf.infer.hypotest() API, which now uses a calctype argument to differentiate between using an asymptotic calculator or a toy calculator, and a test_stat kwarg to specify which test statistic the calculator should use, with 'qtilde', corresponding to pyhf.infer.test_statistics.qmu_tilde(), now the default option. It also relies more heavily on using kwargs to pass options through to the optimizer.

  • Following the recommendations of NEP 29 — Recommend Python and NumPy version support as a community policy standard pyhf v0.6.0 drops support for Python 3.6. PEP 494 – Python 3.6 Release Schedule also notes that Python 3.6 will be end of life in December 2021, so pyhf is moving forward with a minimum required runtime of Python 3.7.

  • Support for the discovery test statistic, \(q_{0}\), has now been added through the pyhf.infer.test_statistics.q0() API.

  • Support for pseudoexperiments (toys) has been added through the pyhf.infer.calculators.ToyCalculator() API. Please see the corresponding example notebook for more detailed exploration of the API.

  • The minuit extra, python -m pip install pyhf[minuit], now uses and requires the iminuit v2.X release series and API. Note that iminuit v2.X can result in slight differences in minimization results from iminuit v1.X.

  • The documentation will now be versioned with releases on ReadTheDocs. Please use pyhf.readthedocs.io to access the documentation for the latest stable release of pyhf.

  • pyhf is transitioning away from Stack Overflow to GitHub Discussions for resolving user questions not covered in the documentation. Please check the GitHub Discussions page to search for discussions addressing your questions and to open up a new discussion if your question is not covered.

  • pyhf has published a paper in the Journal of Open Source Software. JOSS DOI Please make sure to include the paper reference in all citations of pyhf, as documented in the Use and Citations section of the documentation.

Fixes

  • Fix bug where all extras triggered warning for installation of the contrib extra.

  • float-like values are used in division for pyhf.writexml().

  • Model.spec now supports building new models from existing models.

  • \(p\)-values are now reported based on their quantiles, instead of interpolating test statistics and converting to \(p\)-values.

  • Namespace collisions between uproot3 and uproot/uproot4 have been fixed for the xmlio extra.

  • The normsys modifier now uses the pyhf.interpolators.code4 interpolation method by default.

  • The histosys modifier now uses the pyhf.interpolators.code4p interpolation method by default.

Features

Python API

  • The tensorlib API now supports a tensorlib.to_numpy and tensorlib.ravel API.

  • The pyhf.infer.calculators.ToyCalculator() API has been added to support pseudoexperiments (toys).

  • The empirical test statistic distribution API has been added to help support the ToyCalculator API.

  • Add a tolerance kwarg to the optimizer API to set a float value as a tolerance for termination of the fit.

  • The pyhf.optimize.opt_minuit.minuit_optimizer() optimizer now can return correlations of the fitted parameters through use of the return_correlation Boolean kwarg.

  • Add the pyhf.utils.citation API to get a str of the preferred BibTeX entry for citation of the version of pyhf installed. See the example for the CLI API for more information.

  • The pyhf.infer.hypotest() API now uses a calctype argument to differentiate between using an asymptotic calculator or a toy calculator, and a test_stat kwarg to specify which test statistic to use. It also relies more heavily on using kwargs to pass options through to the optimizer.

  • The default test_stat kwarg for pyhf.infer.hypotest() and the calculator APIs is 'qtilde', which corresponds to the alternative test statistic pyhf.infer.test_statistics.qmu_tilde().

  • The return type of \(p\)-value like functions is now a 0-dimensional tensor (with shape ()) instead of a float. This is required to support end-to-end automatic differentiation in future releases.

CLI API

  • The CLI API now supports a --citation or --cite option to print the preferred BibTeX entry for citation of the version of pyhf installed.

$ pyhf --citation
@software{pyhf,
  author = {Lukas Heinrich and Matthew Feickert and Giordon Stark},
  title = "{pyhf: v0.6.0}",
  version = {0.6.0},
  doi = {10.5281/zenodo.1169739},
  url = {https://doi.org/10.5281/zenodo.1169739},
  note = {https://github.com/scikit-hep/pyhf/releases/tag/v0.6.0}
}

@article{pyhf_joss,
  doi = {10.21105/joss.02823},
  url = {https://doi.org/10.21105/joss.02823},
  year = {2021},
  publisher = {The Open Journal},
  volume = {6},
  number = {58},
  pages = {2823},
  author = {Lukas Heinrich and Matthew Feickert and Giordon Stark and Kyle Cranmer},
  title = {pyhf: pure-Python implementation of HistFactory statistical models},
  journal = {Journal of Open Source Software}
}

Contributors

v0.6.0 benefited from contributions from:

  • Alexander Held

  • Marco Gorelli

  • Pradyumna Rahul K

  • Eric Schanet

  • Henry Schreiner

v0.5.4

This is a patch release from v0.5.3v0.5.4.

Fixes

  • Require uproot3 instead of uproot v3.X releases to avoid conflicts when uproot4 is installed in an environment with uproot v3.X installed and namespace conflicts with uproot-methods. Adoption of uproot3 in v0.5.4 will ensure v0.5.4 works far into the future if XML and ROOT I/O through uproot is required.

Example:

Without the v0.5.4 patch release there is a regression in using uproot v3.X and uproot4 in the same environment (which was swiftly identified and patched by the fantastic uproot team)

$ python -m pip install "pyhf[xmlio]<0.5.4"
$ python -m pip list | grep "pyhf\|uproot"
pyhf           0.5.3
uproot         3.13.1
uproot-methods 0.8.0
$ python -m pip install uproot4
$ python -m pip list | grep "pyhf\|uproot"
pyhf           0.5.3
uproot         4.0.0
uproot-methods 0.8.0
uproot4        4.0.0

this is resolved in v0.5.4 with the requirement of uproot3

$ python -m pip install "pyhf[xmlio]>=0.5.4"
$ python -m pip list | grep "pyhf\|uproot"
pyhf            0.5.4
uproot3         3.14.1
uproot3-methods 0.10.0
$ python -m pip install uproot4 # or uproot
$ python -m pip list | grep "pyhf\|uproot"
pyhf            0.5.4
uproot          4.0.0
uproot3         3.14.1
uproot3-methods 0.10.0
uproot4         4.0.0

v0.5.3

This is a patch release from v0.5.2v0.5.3.

Fixes

  • Workspaces are now immutable

  • ShapeFactor support added to XML reading and writing

  • An error is raised if a fit initialization parameter is outside of its bounds (preventing hypotest with POI outside of bounds)

Features

Python API

  • Inverting hypothesis tests to get upper limits now has an API with pyhf.infer.intervals.upperlimit

  • Building workspaces from a model and data added with pyhf.workspace.build

CLI API

  • Added CLI API for pyhf.infer.fit: pyhf fit

  • pyhf combine now allows for merging channels: pyhf combine --merge-channels --join <join option>

  • Added utility to download archived pyhf pallets (workspaces + patchsets) to contrib module: pyhf contrib download

Contributors

v0.5.3 benefited from contributions from:

  • Karthikeyan Singaravelan