diff --git a/.codeclimate.yml b/.codeclimate.yml
deleted file mode 100644
index ca3a1e0..0000000
--- a/.codeclimate.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-engines:
- duplication:
- enabled: true
- config:
- languages:
- - python
- fixme:
- enabled: true
- radon:
- enabled: true
- config:
- python_version: 3
-ratings:
- paths:
- - "**.py"
-exclude_paths:
- - tests/
- - docs/
- - build/
- - dist/
- - legacy/
-checks:
- argument-count:
- enabled: false
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 3928304..8f72038 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -74,7 +74,17 @@ repos:
- id: upgrade-type-hints
args: [ '--futures=true' ]
- - repo: https://github.com/psf/black
- rev: 24.3.0
+ - repo: https://github.com/MarcoGorelli/auto-walrus
+ rev: v0.2.2
hooks:
- - id: black
+ - id: auto-walrus
+
+ - repo: https://github.com/astral-sh/ruff-pre-commit
+ rev: "v0.3.5"
+ hooks:
+ - id: ruff
+ types_or: [ python, pyi, jupyter ]
+ args: [ --fix, --unsafe-fixes, --show-fixes , --line-length=120]
+ # Run the formatter.
+ - id: ruff-format
+ types_or: [ python, pyi, jupyter ]
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 0000000..82e2b5a
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,23 @@
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+build:
+ os: ubuntu-22.04
+ tools:
+ python: "3.12"
+
+# Build documentation in the docs/ directory with Sphinx
+sphinx:
+ configuration: docs/conf.py
+
+formats: [ ]
+
+python:
+ install:
+ - requirements: requirements_dev.txt
+ - requirements: requirements.txt
+ - method: pip
+ path: .
diff --git a/.scrutinizer.yml b/.scrutinizer.yml
deleted file mode 100644
index e7a075c..0000000
--- a/.scrutinizer.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-checks:
- python:
- code_rating: true
- duplicate_code: true
-build:
- environment:
- python: '3.7.1'
- dependencies:
- # Runs before inferred commands
- before:
- - pip install -r requirements_dev.txt
- nodes:
- analysis:
- project_setup:
- override:
- - 'true'
- tests:
- override:
- - py-scrutinizer-run
- - command: pylint-run
- use_website_config: true
- environment:
- node:
- version: 6.0.0
- tests: true
-filter:
- excluded_paths:
- - '/tests/*'
- dependency_paths:
- - 'lib/*'
diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css
new file mode 100644
index 0000000..f1729be
--- /dev/null
+++ b/docs/_static/css/custom.css
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2022 zfit
+ */
+
+/*pydata-sphinx-theme provides some css variables for customizing the look of the theme.*/
+/*See a list of supported css variables at*/
+/*https://github.com/pydata/pydata-sphinx-theme/blob/master/pydata_sphinx_theme/static/css/theme.css*/
+html[data-theme="light"] {
+ /*--pst-color-primary: #080c80 !important;*/
+ --pst-color-primary: #D35827;
+ --pst-color-secondary: #27bcd3;
+ --pst-color-inline-code: #1d54e2;
+ /*--pst-color-target: yellow;*/
+
+
+ /*Here we use css directly because for these attributes there exist no css variables defined by pydata-sphinx-theme.*/
+ /*See https://github.com/pydata/pydata-sphinx-theme/issues/353 for possible changes in the future.*/
+
+ --pst-color-navbar-link: 255, 255, 255;
+ --pst-color-navbar-link-hover: 203, 86, 40;
+ --pst-color-navbar-link-active: 203, 86, 40;
+}
+
+html[data-theme="dark"] {
+ /*--pst-color-primary: #080c80 !important;*/
+ --pst-color-primary: #D35827;
+ --pst-color-secondary: #27bcd3;
+ --pst-color-inline-code: #1d54e2;
+ /*--pst-color-target: yellow;*/
+
+ --pst-color-navbar-link: 255, 255, 255;
+ --pst-color-navbar-link-hover: 203, 86, 40;
+ --pst-color-navbar-link-active: 203, 86, 40;
+}
+
+i.fa-github-square:before {
+ color: #ffffffff !important;
+}
diff --git a/docs/api/static/zfit_physics.pdf.rst b/docs/api/static/zfit_physics.pdf.rst
new file mode 100644
index 0000000..8c4d3c1
--- /dev/null
+++ b/docs/api/static/zfit_physics.pdf.rst
@@ -0,0 +1,7 @@
+pdf
+===
+
+.. automodule:: zfit_physics.pdf
+ :members:
+ :undoc-members:
+ :show-inheritance:
diff --git a/docs/api/tools/change_headline.py b/docs/api/tools/change_headline.py
index 272dd4e..f62f101 100644
--- a/docs/api/tools/change_headline.py
+++ b/docs/api/tools/change_headline.py
@@ -1,4 +1,7 @@
+from __future__ import annotations
+
import argparse
+from pathlib import Path
parser = argparse.ArgumentParser(description="replace first two line")
@@ -7,15 +10,13 @@
n_files = 0
for rest_file in parsed_args.files:
- with open(rest_file) as f:
+ with Path(rest_file).open() as f:
first_word = f.readline().strip().split()[0]
if "." not in first_word:
continue
replacement = first_word.split(".")[-1]
underline = f.readline()[0] * len(replacement)
lower_file = f.read()
- with open(rest_file, "w") as f:
+ with Path(rest_file).open("w") as f:
f.write("\n".join((replacement, underline, lower_file)))
n_files += 1
-
-print(f"finished successfully parsing {n_files} files")
diff --git a/docs/conf.py b/docs/conf.py
index 8bc6913..94f2f3c 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -17,12 +17,12 @@
# -- Project information -----------------------------------------------------
-import os
-import sys
+from __future__ import annotations
-import sphinx_bootstrap_theme
+import sys
+from pathlib import Path
-sys.path.insert(0, os.path.abspath(".."))
+sys.path.insert(0, str(Path("..").resolve()))
import zfit_physics
@@ -32,7 +32,7 @@
author = zfit_physics.__author__
# The short X.Y version
-version = zfit_physics.__version__
+version = zfit_physics.__version__.split("+")[0]
# The full version, including alpha/beta/rc tags
release = zfit_physics.__version__
@@ -45,19 +45,36 @@
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
+#
+needs_sphinx = "3.0.0"
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
"sphinx.ext.autodoc",
- "sphinx.ext.doctest",
+ "sphinx.ext.napoleon",
+ "sphinx_autodoc_typehints",
+ # sphinx_autodoc_typehints must be imported after napoleon to properly work.
+ # See https://github.com/agronholm/sphinx-autodoc-typehints/issues/15
+ "jupyter_sphinx",
+ "sphinx.ext.autosummary",
+ "sphinx.ext.viewcode",
"sphinx.ext.intersphinx",
- "sphinx.ext.todo",
+ "sphinxcontrib.images",
"sphinx.ext.coverage",
"sphinx.ext.mathjax",
- "sphinx.ext.ifconfig",
- "sphinx.ext.viewcode",
"sphinx.ext.githubpages",
- "sphinx.ext.napoleon",
+ "sphinx.ext.todo",
+ "sphinx_copybutton",
+ "sphinxcontrib.youtube",
+ "sphinx_panels",
+ "seed_intersphinx_mapping",
+ "myst_nb",
+ "sphinx_togglebutton",
]
+panels_add_bootstrap_css = False # for sphinx_panel, use custom css from theme, not bootstrap
+
using_numpy_style = False # False -> google style
# Napoleon settings (convert numpy/google docstrings to proper ReST
@@ -73,6 +90,36 @@
napoleon_use_param = True
napoleon_use_rtype = True
+# -- sphinx_autodoc_typehints settings ---------------------------------------------
+
+# if True, set typing.TYPE_CHECKING to True to enable “expensive” typing imports
+set_type_checking_flag = True
+# if True, class names are always fully qualified (e.g. module.for.Class). If False, just the class
+# name displays (e.g. Class)
+typehints_fully_qualified = False
+# (default: False): If False, do not add ktype info for undocumented parameters. If True, add stub documentation for
+# undocumented parameters to be able to add type info.
+always_document_param_types = False
+# (default: True): If False, never add an :rtype: directive. If True, add the :rtype: directive if no existing :rtype:
+# is found.
+typehints_document_rtype = True
+
+# -- autodoc settings ---------------------------------------------
+
+# also doc __init__ docstrings
+autoclass_content = "both"
+autodoc_member_order = "bysource"
+autodoc_default_options = {
+ "show-inheritance": True,
+ "inherited-members": True,
+}
+autodoc_inherit_docstrings = False
+
+# -- autosummary settings ---------------------------------------------
+
+autosummary_generate = True
+autosummary_generate_overwrite = True
+
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
@@ -84,6 +131,7 @@
# source_suffix = ['.rst', '.md']
source_suffix = ".rst"
+
# The master toctree document.
master_doc = "index"
@@ -108,80 +156,47 @@
# a list of builtin themes.
#
-html_theme = "bootstrap"
-html_theme_path = sphinx_bootstrap_theme.get_html_theme_path()
+# -- Options for HTML output -------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+#
+
+html_theme = "pydata_sphinx_theme"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
+html_css_files = [
+ "css/custom.css",
+]
+
+# Theme options are theme-specific and customize the look and feel of a
+# theme further.
+
html_theme_options = {
- # Navigation bar title. (Default: ``project`` value)
- "navbar_title": "zfit",
- # Tab name for entire site. (Default: "Site")
- # 'navbar_site_name': "Docs",
- # 'navbar_site_name': "Overview",
- # A list of tuples containing pages or urls to link to.
- # Valid tuples should be in the following forms:
- # (name, page) # a link to a page
- # (name, "/aa/bb", 1) # a link to an arbitrary relative url
- # (name, "http://example.com", True) # arbitrary absolute url
- # Note the "1" or "True" value above as the third argument to indicate
- # an arbitrary url.
- "navbar_links": [
- ("Getting started", "getting_started"),
- ("Amplitude", "amplitude"),
- # ("Parameter", "parameter"),
- # ("Model", "model"),
- # ("Data", "data"),
- # ("Loss", "loss"),
- # ("Minimize", "minimize"),
- ("API", "API"),
- # ("Link", "http://example.com", True),
- ],
- # Render the next and previous page links in navbar. (Default: true)
- "navbar_sidebarrel": False,
- # Render the current pages TOC in the navbar. (Default: true)
- "navbar_pagenav": False,
- # Tab name for the current pages TOC. (Default: "Page")
- # 'navbar_pagenav_name': "Page",
- # Global TOC depth for "site" navbar tab. (Default: 1)
- # Switching to -1 shows all levels.
- "globaltoc_depth": 1,
- # Include hidden TOCs in Site navbar?
- #
- # Note: If this is "false", you cannot have mixed ``:hidden:`` and
- # non-hidden ``toctree`` directives in the same page, or else the build
- # will break.
- #
- # Values: "true" (default) or "false"
- "globaltoc_includehidden": "true",
- # HTML navbar class (Default: "navbar") to attach to
element.
- # For black navbar, do "navbar navbar-inverse"
- # 'navbar_class': "navbar navbar-inverse",
- "navbar_class": "navbar",
- # Fix navigation bar to top of page?
- # Values: "true" (default) or "false"
- "navbar_fixed_top": "true",
- # Location of link to source.
- # Options are "nav" (default), "footer" or anything else to exclude.
- # 'source_link_position': "nav",
- "source_link_position": False,
- # Bootswatch (http://bootswatch.com/) theme.
- #
- # Options are nothing (default) or the name of a valid theme
- # such as "cosmo" or "sandstone".
- #
- # The set of valid themes depend on the version of Bootstrap
- # that's used (the next config option).
- #
- # Currently, the supported themes are:
- # - Bootstrap 2: https://bootswatch.com/2
- # - Bootstrap 3: https://bootswatch.com/3
- "bootswatch_theme": "flatly",
- # Choose Bootstrap version.
- # Values: "3" (default) or "2" (in quotes)
- "bootstrap_version": "4",
+ "logo": {
+ "image_light": "images/zfit-logo_400x168.png",
+ "image_dark": "images/zfit-logo-light_400x168.png",
+ },
+ "github_url": "https://github.com/zfit/zfit",
+ "use_edit_page_button": True,
+ "navigation_depth": 3,
+ "search_bar_text": "Search zfit...",
+ "navigation_with_keys": True,
+ "search_bar_position": "sidebar",
+ "icon_links": [{}], # temporary fix for https://github.com/pydata/pydata-sphinx-theme/issues/1220
+ # "repository_url": "https://github.com/zfit/zfit", # adding jupyter book somehow?
+ # "repository_branch": "develop",
+ # "path_to_docs": "docs",
+}
+
+html_context = {
+ "github_user": "zfit",
+ "github_repo": "zfit",
+ "github_version": "develop",
+ "doc_path": "docs",
}
# Add any paths that contain custom static files (such as style sheets) here,
@@ -274,7 +289,30 @@
# -- Options for intersphinx extension ---------------------------------------
# Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {"https://docs.python.org/": None}
+# cross reference
+default_role = "py:obj"
+primary_domain = "py"
+# nitpicky = True # warn if cross-references are missing
+# nitpick_ignore = [
+# ("py:class", "tensorflow.keras.losses.Loss"),
+# ]
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {
+ # 'numdifftools': ('https://numdifftools.readthedocs.io/en/latest/index.html', None),
+ "tensorflow": (
+ "https://www.tensorflow.org/api_docs/python",
+ "https://raw.githubusercontent.com/GPflow/tensorflow-intersphinx/master/tf2_py_objects.inv",
+ ),
+ "tensorflow_probability": (
+ "https://www.tensorflow.org/probability/api_docs/python",
+ " https://raw.githubusercontent.com/GPflow/tensorflow-intersphinx/master/tfp_py_objects.inv",
+ ),
+ "uproot": ("https://uproot.readthedocs.io/en/latest/", None),
+ "python": ("https://docs.python.org/3", None),
+ "matplotlib": ("https://matplotlib.org/stable/", None),
+ "pandas": ("https://pandas.pydata.org/docs/", None),
+ "numpy": ("https://numpy.org/doc/stable/", None),
+}
# -- Options for todo extension ----------------------------------------------
diff --git a/docs/images/scikit-hep-logo_168x168.png b/docs/images/scikit-hep-logo_168x168.png
index 2921a3b..1e30811 100644
Binary files a/docs/images/scikit-hep-logo_168x168.png and b/docs/images/scikit-hep-logo_168x168.png differ
diff --git a/docs/images/zfit-favicon.png b/docs/images/zfit-favicon.png
new file mode 100644
index 0000000..37fa196
Binary files /dev/null and b/docs/images/zfit-favicon.png differ
diff --git a/docs/images/zfit-logo-light_400x168.png b/docs/images/zfit-logo-light_400x168.png
new file mode 100644
index 0000000..c8a41a4
Binary files /dev/null and b/docs/images/zfit-logo-light_400x168.png differ
diff --git a/docs/images/zfit-logo_400x168.png b/docs/images/zfit-logo_400x168.png
new file mode 100644
index 0000000..8d54e39
Binary files /dev/null and b/docs/images/zfit-logo_400x168.png differ
diff --git a/docs/images/zfit-logo_57x24.png b/docs/images/zfit-logo_57x24.png
new file mode 100644
index 0000000..88b2f39
Binary files /dev/null and b/docs/images/zfit-logo_57x24.png differ
diff --git a/docs/images/zfit-logo_hires.png b/docs/images/zfit-logo_hires.png
new file mode 100644
index 0000000..a2d0e0c
Binary files /dev/null and b/docs/images/zfit-logo_hires.png differ
diff --git a/docs/images/zfit-logo_veryhires.png b/docs/images/zfit-logo_veryhires.png
new file mode 100644
index 0000000..5465d34
Binary files /dev/null and b/docs/images/zfit-logo_veryhires.png differ
diff --git a/docs/images/zfit-vector.svg b/docs/images/zfit-vector.svg
new file mode 100644
index 0000000..0517765
--- /dev/null
+++ b/docs/images/zfit-vector.svg
@@ -0,0 +1 @@
+
diff --git a/docs/images/zfit_workflow_v1.png b/docs/images/zfit_workflow_v1.png
index d2ef943..42ebaae 100644
Binary files a/docs/images/zfit_workflow_v1.png and b/docs/images/zfit_workflow_v1.png differ
diff --git a/docs/images/zfit_workflow_v2.png b/docs/images/zfit_workflow_v2.png
new file mode 100644
index 0000000..2048c8d
Binary files /dev/null and b/docs/images/zfit_workflow_v2.png differ
diff --git a/docs/index.rst b/docs/index.rst
index 3cdbb62..7dd522f 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,20 +1,25 @@
-.. zfit-physics documentation master file, created by
- sphinx-quickstart on Sat Mar 30 23:00:08 2019.
- You can adapt this file completely to your liking, but it should at least
- contain the root `toctree` directive.
-Welcome to zfit-physics's documentation!
-========================================
+Welcome to zfit-physics
+=======================
-.. toctree::
- :maxdepth: 2
- :caption: Contents:
+zfit-physics is a package that provides physics-related functionality to zfit. It is not a standalone package but requires `zfit
`_ to be installed.
+
+It can be installed via pip:
+
+.. code-block:: bash
+
+ pip install zfit-physics
+or via conda:
+.. code-block:: bash
-Indices and tables
-==================
+ conda install -c conda-forge zfit-physics
+
+PDF documentation
+-----------------
+
+.. toctree::
+ :maxdepth: 2
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
+ api/static/zfit_physics.pdf
diff --git a/pyproject.toml b/pyproject.toml
index 3c8fe9e..c89b8a8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -8,19 +8,56 @@ requires = [
build-backend = "setuptools.build_meta"
-[tool.black]
+[tool.ruff]
+#src = ["src"]
line-length = 120
-include = '\.pyi?$'
-exclude = '''
-/(
- \.git
- | \.hg
- | \.mypy_cache
- | \.tox
- | \.venv
- | _build
- | buck-out
- | build
- | dist
-)/
-'''
+exclude = [
+ ".tox/*",
+ "*/test*",
+ "*/__init__.py",
+ "*/_version.py",
+]
+[tool.ruff.lint]
+extend-select = [
+ "B", # flake8-bugbear
+ "I", # isort
+ "ARG", # flake8-unused-arguments
+ "C4", # flake8-comprehensions
+ "EM", # flake8-errmsg
+ "ICN", # flake8-import-conventions
+ "G", # flake8-logging-format
+ "PGH", # pygrep-hooks
+ "PIE", # flake8-pie
+ "PL", # pylint
+ "PT", # flake8-pytest-style
+ "PTH", # flake8-use-pathlib
+ "RET", # flake8-return
+ "RUF", # Ruff-specific
+ "SIM", # flake8-simplify
+ "T20", # flake8-print
+ "UP", # pyupgrade
+ "YTT", # flake8-2020
+ "EXE", # flake8-executable
+ "NPY", # NumPy specific rules
+ "PD", # pandas-vet
+]
+ignore = [
+ "UP007", # type annotation upgrade, breaks pydantic for Python 3.9 (remove once above)
+ "PLR09", # Too many <...>
+ "PLR2004", # Magic value used in comparison
+ "ISC001", # Conflicts with formatter
+ "RET505", # This is sometimes wanted, protets against accidental intendation
+ "PD901", # "avoid using `df[...].values`" -> no, this is a very good name if there is only one df
+ "PD011", # "replace `df[...].values` with `df[...].to_numpy()`" -> not yet, it's not deprecated.
+ # Prefer to have a single way to access the data if we don't care about whether it's a numpy array or not.
+ "PLW0603", # updating global variables with a function is bad, but we use it for
+ "PLW2901", # "for loop overwritten by assignment" -> we use this to update the loop variable
+ "PD013", # "melt over stack": df function, but triggers on tensors
+ "NPY002", # "Use rnd generator in numpy" -> we use np.random for some legacy stuff but do use the new one where we can
+
+]
+isort.required-imports = ["from __future__ import annotations"]
+
+[tool.ruff.lint.per-file-ignores]
+"tests/**" = ["T20"]
+"noxfile.py" = ["T20"]
diff --git a/requirements.txt b/requirements.txt
index 93185ed..0fde880 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1 +1 @@
-zfit>=0.12
+zfit>=0.20
diff --git a/requirements_dev.txt b/requirements_dev.txt
index 03c364d..89542ff 100644
--- a/requirements_dev.txt
+++ b/requirements_dev.txt
@@ -2,15 +2,26 @@ bumpversion>=0.5.3
coverage>=4.5.1
coverage>=4.5.1
flake8>=3.5.0
+jupyter-sphinx
+myst-nb
numba-stats @ git+https://github.com/HDembinski/numba-stats.git # CMSShape not yet released (expected 1.8.0)
pip>=9.0.1
pre-commit
+pydata-sphinx-theme>=0.9 # new dark theme configuration
pytest>=3.4.2
pytest-cov
pytest-rerunfailures>=6
pytest-runner>=2.11.1
-Sphinx>=1.7.1
-sphinx_bootstrap_theme
+seed_intersphinx_mapping
+setupext-janitor
+Sphinx>=3.5.4
+sphinx-autodoc-typehints
+sphinx-copybutton
+sphinx-panels
+sphinx_togglebutton
+sphinxcontrib-applehelp<1.0.8 # needs sphinx>=0.5, why are we still stuck at <0.5?
+sphinxcontrib-images
+sphinxcontrib-youtube>=1.0.0,<1.2.0
tox>=2.9.1
twine>=1.10.0
twine
diff --git a/setup.py b/setup.py
index cfc6287..25d9a02 100644
--- a/setup.py
+++ b/setup.py
@@ -1,19 +1,19 @@
-#!/usr/bin/env python
-
"""The setup script."""
-import os
-from setuptools import find_packages, setup
+from __future__ import annotations
-here = os.path.abspath(os.path.dirname(__file__))
+from pathlib import Path
+
+from setuptools import find_packages, setup
-with open(os.path.join(here, "requirements.txt"), encoding="utf-8") as requirements_file:
+here = Path(__file__).parent.resolve()
+with Path(here / "requirements.txt").open(encoding="utf-8") as requirements_file:
requirements = requirements_file.read().splitlines()
-with open(os.path.join(here, "requirements_dev.txt"), encoding="utf-8") as requirements_dev_file:
+with Path(here / "requirements_dev.txt").open(encoding="utf-8") as requirements_dev_file:
dev_requirements = requirements_dev_file.read().splitlines()
-with open(os.path.join(here, "README.rst"), encoding="utf-8") as readme_file:
+with Path(here / "README.rst").open(encoding="utf-8") as readme_file:
readme = readme_file.read()
setup(
diff --git a/tests/conftest.py b/tests/conftest.py
index d407136..dc91bb7 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
import sys
import pytest
@@ -6,7 +8,7 @@
@pytest.fixture(autouse=True)
-def setup_teardown():
+def _setup_teardown():
import zfit
old_chunksize = zfit.run.chunking.max_n_points
@@ -14,7 +16,7 @@ def setup_teardown():
old_graph_mode = zfit.run.get_graph_mode()
old_autograd_mode = zfit.run.get_autograd_mode()
- for m in sys.modules.keys():
+ for m in sys.modules:
if m not in init_modules:
del sys.modules[m]
@@ -32,7 +34,7 @@ def setup_teardown():
zfit.run.chunking.max_n_points = old_chunksize
zfit.run.set_graph_mode(old_graph_mode)
zfit.run.set_autograd_mode(old_autograd_mode)
- for m in sys.modules.keys():
+ for m in sys.modules:
if m not in init_modules:
del sys.modules[m]
import gc
diff --git a/tests/test_pdf_novosibirsk.py b/tests/test_pdf_novosibirsk.py
index 27453ec..84750ca 100644
--- a/tests/test_pdf_novosibirsk.py
+++ b/tests/test_pdf_novosibirsk.py
@@ -2,7 +2,6 @@
import numpy as np
import pytest
-import ROOT
import tensorflow as tf
import zfit
from zfit.core.testing import tester
@@ -26,8 +25,9 @@ def create_novosibirsk(mu, sigma, lambd, limits):
novosibirsk = zphys.pdf.Novosibirsk(mu=mu, sigma=sigma, lambd=lambd, obs=obs)
return novosibirsk, obs
-
+@pytest.mark.skip
def create_and_eval_root_novosibirsk_and_integral(mu, sigma, lambd, limits, x, lower, upper):
+ ROOT = pytest.importorskip("ROOT")
obs = ROOT.RooRealVar("obs", "obs", *limits)
peak = ROOT.RooRealVar("peak", "peak", mu)
width = ROOT.RooRealVar("width", "width", sigma)
diff --git a/zfit_physics/models/pdf_argus.py b/zfit_physics/models/pdf_argus.py
index 2b0e155..082ebde 100644
--- a/zfit_physics/models/pdf_argus.py
+++ b/zfit_physics/models/pdf_argus.py
@@ -1,6 +1,6 @@
"""ARGUS PDF (https://en.wikipedia.org/wiki/ARGUS_distribution)"""
-from typing import Optional
+from __future__ import annotations
import numpy as np
import tensorflow as tf
@@ -42,8 +42,7 @@ def argus_func(
m_frac = m / m0
m_factor = 1 - z.square(m_frac)
- argus = m * z.pow(m_factor, p) * (z.exp(c * m_factor))
- return argus
+ return m * z.pow(m_factor, p) * (z.exp(c * m_factor))
class Argus(zfit.pdf.BasePDF):
@@ -54,7 +53,7 @@ def __init__(
c,
p,
name: str = "ArgusPDF",
- extended: Optional[ztyping.ParamTypeInput] = None,
+ extended: ztyping.ParamTypeInput | None = None,
):
r"""`ARGUS shape
`_ describing the invariant mass of a particle
in a continuous background.
@@ -107,12 +106,11 @@ def uppergamma(s, x):
@z.function(wraps="tensor")
def argus_cdf_p_half_nonpositive(lim, c, m0):
lim = tf.clip_by_value(lim, 0.0, m0)
- cdf = tf.cond(
+ return tf.cond(
tf.math.less(c, 0.0),
lambda: argus_cdf_p_half_c_neg(lim=lim, c=c, m0=m0),
lambda: argus_cdf_p_half_c_zero(lim=lim, c=c, m0=m0),
)
- return cdf
# Does not work, why?
@@ -140,8 +138,7 @@ def argus_cdf_p_half_c_neg(lim, c, m0):
def argus_cdf_p_half_c_zero(lim, c, m0):
del c
f1 = 1 - z.square(lim / m0)
- cdf = -z.square(m0) / 3.0 * f1 * z.sqrt(f1)
- return cdf
+ return -z.square(m0) / 3.0 * f1 * z.sqrt(f1)
# TODO: add Faddeev function approximation
@@ -158,6 +155,7 @@ def argus_integral_p_half_func(lower, upper, c, m0):
def argus_integral_p_half(limits, params, model):
+ del model
p = params["p"]
if not isinstance(p, zfit.param.ConstantParameter) or not np.isclose(p.static_value, 0.5):
raise zfit.exception.AnalyticIntegralNotImplementedError()
@@ -169,8 +167,7 @@ def argus_integral_p_half(limits, params, model):
lower, upper = limits.limit1d
lower = z.convert_to_tensor(lower)
upper = z.convert_to_tensor(upper)
- integral = argus_integral_p_half_func(lower=lower, upper=upper, c=c, m0=m0)
- return integral
+ return argus_integral_p_half_func(lower=lower, upper=upper, c=c, m0=m0)
argus_integral_limits = zfit.Space(axes=(0,), limits=(zfit.Space.ANY_LOWER, zfit.Space.ANY_UPPER))
@@ -212,10 +209,8 @@ def argus_integral_p_half(limits, params, model):
integral_expression = m * m_factor**p * (sp.exp(c * m_factor))
# integral_expression = (N * m * (1 - (m / m0) ** 2) ** p * sp.exp(c * (1 - (m / m0) ** 2)))
integral = sp.integrate(integral_expression, m)
- print(integral)
func1 = sp.lambdify(integral.free_symbols, integral, "tensorflow")
import inspect
source = inspect.getsource(func1)
- print(source)
# sp.lambdify()
diff --git a/zfit_physics/models/pdf_cmsshape.py b/zfit_physics/models/pdf_cmsshape.py
index 196d40e..82f57a5 100644
--- a/zfit_physics/models/pdf_cmsshape.py
+++ b/zfit_physics/models/pdf_cmsshape.py
@@ -1,4 +1,4 @@
-from typing import Optional
+from __future__ import annotations
import tensorflow as tf
import zfit
@@ -70,6 +70,7 @@ def cmsshape_integral(limits: ztyping.SpaceType, params: dict, model) -> tf.Tens
Returns:
The calculated integral.
"""
+ del model
lower, upper = limits.limit1d
m = params["m"]
beta = params["beta"]
@@ -89,8 +90,8 @@ def __init__(
gamma: ztyping.ParamTypeInput,
obs: ztyping.ObsTypeInput,
*,
- extended: Optional[ztyping.ExtendedInputType] = None,
- norm: Optional[ztyping.NormInputType] = None,
+ extended: ztyping.ExtendedInputType | None = None,
+ norm: ztyping.NormInputType | None = None,
name: str = "CMSShape",
):
"""CMSShape PDF.
diff --git a/zfit_physics/models/pdf_conv.py b/zfit_physics/models/pdf_conv.py
index 2554508..eddbb5f 100644
--- a/zfit_physics/models/pdf_conv.py
+++ b/zfit_physics/models/pdf_conv.py
@@ -1,4 +1,4 @@
-from typing import Optional
+from __future__ import annotations
import tensorflow as tf
import tensorflow_probability as tfp
@@ -19,7 +19,7 @@ def __init__(
obs: ztyping.ObsTypeInput,
ndraws: int = 20000,
*,
- extended: Optional[ztyping.ParamTypeInput] = None,
+ extended: ztyping.ParamTypeInput | None = None,
name: str = "Convolution",
experimental_pdf_normalized=False,
):
@@ -39,9 +39,11 @@ def __init__(
super().__init__(obs=obs, pdfs=[func, kernel], params={}, name=name, extended=extended)
limits = self._check_input_limits(limits=limits)
if limits.n_limits == 0:
- raise exception.LimitsNotSpecifiedError("obs have to have limits to define where to integrate over.")
+ msg = "obs have to have limits to define where to integrate over."
+ raise exception.LimitsNotSpecifiedError(msg)
if limits.n_limits > 1:
- raise WorkInProgressError("Multiple Limits not implemented")
+ msg = "Multiple Limits not implemented"
+ raise WorkInProgressError(msg)
# if not isinstance(func, zfit.pdf.BasePDF):
# raise TypeError(f"func has to be a PDF, not {type(func)}")
@@ -82,7 +84,8 @@ def _unnormalized_pdf(self, x):
@zfit.supports(norm=True)
@z.function
- def _pdf(self, x, norm_range):
+ def _pdf(self, x, norm):
+ del norm
if not self._experimental_pdf_normalized:
raise FunctionNotImplementedError
diff --git a/zfit_physics/models/pdf_cruijff.py b/zfit_physics/models/pdf_cruijff.py
index 4619a47..86c2d9d 100644
--- a/zfit_physics/models/pdf_cruijff.py
+++ b/zfit_physics/models/pdf_cruijff.py
@@ -1,4 +1,4 @@
-from typing import Optional
+from __future__ import annotations
import zfit
from zfit import z
@@ -35,8 +35,7 @@ def cruijff_pdf_func(x, mu, sigmal, alphal, sigmar, alphar):
tleft / (1 + alphal * tleft),
tright / (1 + alphar * tright),
)
- value = znp.exp(-0.5 * exponent)
- return value
+ return znp.exp(-0.5 * exponent)
class Cruijff(zfit.pdf.BasePDF):
@@ -51,9 +50,10 @@ def __init__(
alphar: ztyping.ParamTypeInput,
obs: ztyping.ObsTypeInput,
*,
- extended: Optional[ztyping.ExtendedInputType] = False,
- norm: Optional[ztyping.NormInputType] = None,
+ extended: ztyping.ExtendedInputType | None = False,
+ norm: ztyping.NormInputType | None = None,
name: str = "Cruijff",
+ label: str | None = None,
):
"""Cruijff PDF, a Gaussian with two width, left and right, and non-Gaussian tails.
@@ -92,9 +92,10 @@ def __init__(
or label of
the PDF for better identification.
Has no programmatical functional purpose as identification. |@docend:pdf.init.name|
+ label: |@doc:pdf.init.label| A human readable label to identify the PDF. |@docend:pdf.init.label|
"""
params = {"mu": mu, "sigmal": sigmal, "alphal": alphal, "sigmar": sigmar, "alphar": alphar}
- super().__init__(obs=obs, params=params, extended=extended, norm=norm)
+ super().__init__(obs=obs, params=params, extended=extended, norm=norm, name=name, label=label)
def _unnormalized_pdf(self, x):
mu = self.params["mu"]
diff --git a/zfit_physics/models/pdf_erfexp.py b/zfit_physics/models/pdf_erfexp.py
index c948dbd..6fb1d10 100644
--- a/zfit_physics/models/pdf_erfexp.py
+++ b/zfit_physics/models/pdf_erfexp.py
@@ -1,4 +1,4 @@
-from typing import Optional
+from __future__ import annotations
import tensorflow as tf
import zfit
@@ -49,9 +49,10 @@ def __init__(
n: ztyping.ParamTypeInput,
obs: ztyping.ObsTypeInput,
*,
- extended: Optional[ztyping.ExtendedInputType] = False,
- norm: Optional[ztyping.NormInputType] = None,
+ extended: ztyping.ExtendedInputType | None = False,
+ norm: ztyping.NormInputType | None = None,
name: str = "ErfExp",
+ label: str | None = None,
):
"""ErfExp PDF, the product of a complementary error function and an exponential function.
@@ -86,9 +87,10 @@ def __init__(
or label of
the PDF for better identification.
Has no programmatical functional purpose as identification. |@docend:pdf.init.name|
+ label: |@doc:pdf.init.label| A human readable label to identify the PDF. |@docend:pdf.init.label|
"""
params = {"mu": mu, "beta": beta, "gamma": gamma, "n": n}
- super().__init__(obs=obs, params=params, extended=extended, norm=norm)
+ super().__init__(obs=obs, params=params, extended=extended, norm=norm, name=name, label=label)
def _unnormalized_pdf(self, x):
mu = self.params["mu"]
diff --git a/zfit_physics/models/pdf_example.py b/zfit_physics/models/pdf_example.py
index e1840e2..9ca304f 100644
--- a/zfit_physics/models/pdf_example.py
+++ b/zfit_physics/models/pdf_example.py
@@ -3,12 +3,17 @@
Create a module for each pdf that you add.
"""
+from __future__ import annotations
+
+import typing
+
import zfit
class Example(zfit.pdf.ZPDF):
- _PARAMS = ["param1"]
+ _PARAMS: typing.ClassVar = ["param1"]
def _unnormalized_pdf(self, x):
"""Documentation here."""
- return [42.0]
+ x0 = x[0]
+ return [42.0 * x0]
diff --git a/zfit_physics/models/pdf_kde.py b/zfit_physics/models/pdf_kde.py
index 00693a0..5c02696 100644
--- a/zfit_physics/models/pdf_kde.py
+++ b/zfit_physics/models/pdf_kde.py
@@ -1,5 +1,6 @@
+from __future__ import annotations
+
from collections import OrderedDict
-from typing import Optional
import tensorflow as tf
import tensorflow_probability.python.distributions as tfd
@@ -19,7 +20,7 @@ def __init__(
obs: ztyping.ObsTypeInput,
name: str = "GaussianKDE",
*,
- extended: Optional[ztyping.ParamTypeInput] = None,
+ extended: ztyping.ParamTypeInput | None = None,
):
"""Gaussian Kernel Density Estimation using Silverman's rule of thumb.
@@ -31,21 +32,21 @@ def __init__(
"""
dtype = zfit.settings.ztypes.float
if isinstance(data, zfit.core.interfaces.ZfitData):
- raise WorkInProgressError("Currently, no dataset supported yet")
+ msg = "Currently, no dataset supported yet"
+ raise WorkInProgressError(msg)
# size = data.nevents
# dims = data.n_obs
# with data.
# data = data.value()
# if data.weights is not None:
- else:
- if not isinstance(data, tf.Tensor):
- data = z.convert_to_tensor(value=data)
- data = z.to_real(data)
+ if not isinstance(data, tf.Tensor):
+ data = z.convert_to_tensor(value=data)
+ data = z.to_real(data)
- shape_data = tf.shape(data)
- size = tf.cast(shape_data[0], dtype=dtype)
- dims = tf.cast(shape_data[-1], dtype=dtype)
+ shape_data = tf.shape(data)
+ size = tf.cast(shape_data[0], dtype=dtype)
+ dims = tf.cast(shape_data[-1], dtype=dtype)
bandwidth = convert_to_container(bandwidth)
# Bandwidth definition, use silverman's rule of thumb for nd
@@ -56,19 +57,18 @@ def reshaped_kerner_factory():
# cov = tf.linalg.diag(cov_diag)
# kernel prob output shape: (n,)
# kernel = tfd.MultivariateNormalFullCovariance(loc=data, covariance_matrix=cov)
- kernel = tfd.MultivariateNormalDiag(loc=data, scale_diag=cov_diag)
+ return tfd.MultivariateNormalDiag(loc=data, scale_diag=cov_diag)
- return kernel
# return tfd.Independent(kernel)
# reshaped_kernel = kernel
probs = tf.broadcast_to(1 / size, shape=(tf.cast(size, tf.int32),))
categorical = tfd.Categorical(probs=probs) # no grad -> no need to recreate
- dist_kwargs = lambda: dict(
- mixture_distribution=categorical,
- components_distribution=reshaped_kerner_factory(),
- )
+
+ def dist_kwargs():
+ return {"mixture_distribution": categorical, "components_distribution": reshaped_kerner_factory()}
+
distribution = tfd.MixtureSameFamily
# TODO lambda for params
params = OrderedDict((f"bandwidth_{i}", h) for i, h in enumerate(bandwidth))
diff --git a/zfit_physics/models/pdf_novosibirsk.py b/zfit_physics/models/pdf_novosibirsk.py
index ef00d58..e1206d4 100644
--- a/zfit_physics/models/pdf_novosibirsk.py
+++ b/zfit_physics/models/pdf_novosibirsk.py
@@ -1,4 +1,4 @@
-from typing import Optional
+from __future__ import annotations
import numpy as np
import tensorflow as tf
@@ -58,6 +58,7 @@ def novosibirsk_integral(limits: ztyping.SpaceType, params: dict, model) -> tf.T
Returns:
The calculated integral.
"""
+ del model
lower, upper = limits.limit1d
mu = params["mu"]
sigma = params["sigma"]
@@ -122,8 +123,8 @@ def __init__(
lambd,
obs,
*,
- extended: Optional[ztyping.ExtendedInputType] = False,
- norm: Optional[ztyping.NormInputType] = None,
+ extended: ztyping.ExtendedInputType | None = False,
+ norm: ztyping.NormInputType | None = None,
name: str = "Novosibirsk",
):
"""Novosibirsk PDF.
diff --git a/zfit_physics/models/pdf_relbw.py b/zfit_physics/models/pdf_relbw.py
index 47b20f4..fa2abeb 100644
--- a/zfit_physics/models/pdf_relbw.py
+++ b/zfit_physics/models/pdf_relbw.py
@@ -1,4 +1,4 @@
-from typing import Optional
+from __future__ import annotations
import numpy as np
import tensorflow as tf
@@ -40,7 +40,7 @@ def __init__(
gamma: ztyping.ParamTypeInput,
obs: ztyping.ObsTypeInput,
name: str = "RelativisticBreitWigner",
- extended: Optional[ztyping.ParamTypeInput] = None,
+ extended: ztyping.ParamTypeInput | None = None,
):
"""Relativistic Breit-Wigner distribution.
@@ -50,7 +50,7 @@ def __init__(
m: the average value
gamma: the width of the distribution
"""
- params = dict(m=m, gamma=gamma)
+ params = {"m": m, "gamma": gamma}
super().__init__(obs=obs, params=params, name=name, extended=extended)
def _unnormalized_pdf(self, x: tf.Tensor) -> tf.Tensor:
@@ -116,8 +116,7 @@ def relbw_cdf_func(x, m, gamma):
norm = z.to_complex(-1) ** (1.0 / 4.0) * k / (2.0 * alpha * m**3)
cdf_ = shape * norm
- cdf_ = z.to_real(cdf_)
- return cdf_
+ return z.to_real(cdf_)
def relbw_integral(limits: ztyping.SpaceType, params: dict, model) -> tf.Tensor:
@@ -131,6 +130,7 @@ def relbw_integral(limits: ztyping.SpaceType, params: dict, model) -> tf.Tensor:
Returns:
The calculated integral.
"""
+ del model
lower, upper = limits.rect_limits
lower_cdf = relbw_cdf_func(x=lower, m=params["m"], gamma=params["gamma"])
upper_cdf = relbw_cdf_func(x=upper, m=params["m"], gamma=params["gamma"])
diff --git a/zfit_physics/models/pdf_tsallis.py b/zfit_physics/models/pdf_tsallis.py
index ab14998..ece5f6c 100644
--- a/zfit_physics/models/pdf_tsallis.py
+++ b/zfit_physics/models/pdf_tsallis.py
@@ -1,4 +1,4 @@
-from typing import Optional
+from __future__ import annotations
import tensorflow as tf
import zfit
@@ -30,7 +30,7 @@ def tsallis_pdf_func(x, m, t, n):
msg = "n > 2 is required"
raise ValueError(msg)
elif run.numeric_checks:
- tf.debugging.assert_greater(n, znp.asarray(2.0), message="n > 2 is required")
+ tf.debugging.assert_greater(n, znp.array(2.0), message="n > 2 is required")
x = z.unstack_x(x)
mt = znp.hypot(m, x)
@@ -61,7 +61,7 @@ def tsallis_cdf_func(x, m, t, n):
msg = "n > 2 is required"
raise ValueError(msg)
elif run.numeric_checks:
- tf.debugging.assert_greater(n, znp.asarray(2.0), message="n > 2 is required")
+ tf.debugging.assert_greater(n, znp.asarray(2.0), "n > 2 is required")
x = z.unstack_x(x)
mt = znp.hypot(m, x)
@@ -80,6 +80,7 @@ def tsallis_integral(limits: ztyping.SpaceType, params: dict, model) -> tf.Tenso
Returns:
The calculated integral.
"""
+ del model
lower, upper = limits._rect_limits_tf
m = params["m"]
t = params["t"]
@@ -99,8 +100,8 @@ def __init__(
n: ztyping.ParamTypeInput,
obs: ztyping.ObsTypeInput,
*,
- extended: Optional[ztyping.ExtendedInputType] = None,
- norm: Optional[ztyping.NormInputType] = None,
+ extended: ztyping.ExtendedInputType | None = None,
+ norm: ztyping.NormInputType | None = None,
name: str = "Tsallis",
):
"""Tsallis-Hagedorn PDF.
diff --git a/zfit_physics/pdf.py b/zfit_physics/pdf.py
index eaa103e..8edd0a1 100644
--- a/zfit_physics/pdf.py
+++ b/zfit_physics/pdf.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
from .models.pdf_argus import Argus
from .models.pdf_cmsshape import CMSShape
from .models.pdf_cruijff import Cruijff
diff --git a/zfit_physics/plot.py b/zfit_physics/plot.py
deleted file mode 100644
index f4d67b1..0000000
--- a/zfit_physics/plot.py
+++ /dev/null
@@ -1,6 +0,0 @@
-"""Simple plotting helpers.
-
-This module contains multiple helpers to plot a PDF.
-"""
-
-# def plot1d(model, limits, npoints)
diff --git a/zfit_physics/unstable/pdf.py b/zfit_physics/unstable/pdf.py
index 508d29a..5877d39 100644
--- a/zfit_physics/unstable/pdf.py
+++ b/zfit_physics/unstable/pdf.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
from ..models.pdf_conv import NumConvPDFUnbinnedV1
from ..models.pdf_kde import GaussianKDE