[project] name = "HSSM" version = "0.5.1" description = "Bayesian inference for hierarchical sequential sampling models." authors = [ { name = "Alexander Fengler", email = "alexander_fengler@brown.edu" }, { name = "Paul Xu", email = "yang_xu@brown.edu" }, { name = "Carlos Paniagua", email = "carlos_paniagua@brown.edu" }, { name = "Krishn Bera", email = "krishn_bera@brown.edu" }, { name = "Aisulu Omar", email = "aisulu_omar@brown.edu" }, { name = "Michael Frank", email = "michael_frank@brown.edu" }, ] readme = "README.md" license = { file = "LICENSE" } keywords = ["HSSM", "sequential sampling models", "bayesian", "bayes", "mcmc"] requires-python = ">=3.12,<3.15" classifiers = [ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", ] dependencies = [ "absl-py>=2.5.0", "bambi>=0.19.0", "h5netcdf>=1.8.1", "h5py>=3.16.0", "hddm-wfpt>=0.1.6", "huggingface-hub>=1.17.0", "jaxonnxruntime>=0.3.0", "numpy>=2.4.0,<2.5.0", "numpyro>=0.20", "onnx>=1.16.0", # Imported directly throughout hssm; 6.3.0 is the first release where nuts={"jitter": False} # reaches sample_jax_nuts (pymc#8380), which replaced HSSM's monkeypatch of pymc.sampling.jax. "pymc>=6.3.0", # Direct import in hssm.plotting (gaussian_kde, chi2), not merely transitive via pymc. "scipy>=1.10", "ssm-simulators>=0.14.0", ] [project.urls] homepage = "https://lnccbrown.github.io/HSSM/" documentation = "https://lnccbrown.github.io/HSSM/" repository = "https://github.com/lnccbrown/HSSM" [project.optional-dependencies] cuda12 = ["jax[cuda12]>=0.7.0"] cuda13 = ["jax[cuda13]>=0.7.0"] tracking = ["mlflow>=3.14.0", "pyarrow>=20.0.0"] [dependency-groups] dev = [ "coverage>=7.6.4", "mypy>=2.1", "pytest-cov>=6.0.0", "pytest-xdist>=3.6.1", "pytest-random-order>=1.1.1", "pytest-rerunfailures>=15.0", "pytest-timeout>=2.3.1", "types-PyYAML", "psutil>=7.2.2", "prek>=0.4.8", "onnxruntime>=1.27.0", "ruff>=0.16.1", "pytest>=9.1.1", "pyrefly>=1.3.2", "hssm[tracking]", ] notebook = [ "graphviz>=0.20.3", "ipykernel>=6.29.5", "ipython>=8.31.0", "ipywidgets>=8.1.2", "jupyterlab>=4.2.4", "marimo==0.24.0", "mistune>=3.0.2", "nbconvert>=7.16.5", "nb-clean>=4.0.1", "nbval>=0.11.0", "onnxruntime>=1.27.0", "ptpython>=3.0.29", "pyarrow>=20.0.0", # 0.9.0 is the first release whose trainers run under pandas 3 (LANfactory#140). "lanfactory>=0.9.0", "zeus-mcmc>=2.5.4", "bayesflow>=2.0.12", "keras>=3.12", "sbi>=0.26", "nflows>=0.14", ] docs = [ "marimo==0.24.0", "mkdocs==1.6.1", "mkdocs-autorefs==1.4.4", "mkdocs-jupyter==0.26.3", "mkdocs-material==9.7.7", "mkdocs-redirects==1.2.2", "mkdocstrings==1.0.6", "mkdocstrings-python==2.0.5", ] [tool.ruff] line-length = 88 target-version = "py312" exclude = [ ".git", "__pycache__", "venv", ".venv", "notebooks", ] [tool.ruff.format] docstring-code-format = true [tool.ruff.lint] unfixable = ["E711"] select = [ # pydocstyle "D", # pyflakes "F", # pycodestyle "E", "I", "W", # flake8-2020 "YTT", # flake8-bugbear "B", # flake8-quotes "Q", # pylint "PLE", "PLR", "PLW", # misc lints "PIE", # flake8-pyi "PYI", # tidy imports "TID", # type-checking imports "TCH", ] ignore = [ # space before : (needed for how black formats slicing) # "E203", # not yet implemented # module level import not at top of file "E402", # do not assign a lambda expression, use a def "E731", # line break before binary operator # "W503", # not yet implemented # line break after binary operator # "W504", # not yet implemented # controversial "B006", # controversial "B007", # controversial "B008", # setattr is used to side-step mypy "B009", # getattr is used to side-step mypy "B010", # tests use assert False "B011", # tests use comparisons but not their returned value "B015", # false positives "B019", # Loop control variable overrides iterable it iterates "B020", # Function definition does not bind loop variable "B023", # zip()` without an explicit `strict= "B905", # Functions defined inside a loop must not use variables redefined in the loop # "B301", # not yet implemented # Too many arguments to function call "PLR0913", # Too many positional arguments "PLR0917", # Too many returns "PLR0911", # Too many branches "PLR0912", # Too many statements "PLR0915", # Global statements are discouraged "PLW0603", # Implement of __eq__ without __hash__ function "PLW1641", # Docstrings should not be included in stubs "PYI021", # Use typing_extensions.TypeAlias for type aliases # "PYI026", # not yet implemented # Use "collections.abc.*" instead of "typing.*" (PEP 585 syntax) # "PYI027", # not yet implemented # while int | float can be shortened to float, the former is more explicit # "PYI041", # not yet implemented # Additional checks that don't pass yet # Within an except clause, raise exceptions with ... "B904", # Magic number "PLR2004", # Consider `elif` instead of `else` then `if` to remove indentation level "PLR5501", # Ignore "Use `float` instead of `int | float`." "PYI041", # Allow importing from parent modules "TID252", ] exclude = [".github", "docs", "notebook", "tests/*"] [tool.ruff.lint.pydocstyle] convention = "numpy" [tool.mypy] ignore_missing_imports = true [tool.pytest] [tool.pytest.ini_options] testpaths = ["tests"] log_cli = true # WARNING keeps the live log readable; the slow CI path raises it to INFO for # the per-test RSS lines (run_tests.yml). Coverage is opt-in: pass --cov=src/hssm # explicitly (coverage.yml does), so plain runs are not instrumented. log_cli_level = "WARNING" # Reruns are untimed: pytest-timeout arms one timer per test, not per attempt. # Add --rerun-except=pytest-timeout once test_addm_waic_loo is well under 600 s (#1074). addopts = [ "--durations=50", "--durations-min=1", "--timeout=600", "--reruns=1", "--reruns-delay=5", ] markers = [ "slow: marks tests as slow (deselect with -m 'not slow')", ] [build-system] requires = ["uv_build>=0.11.21,<0.12"] build-backend = "uv_build" [[tool.uv.index]] name = "pypi" url = "https://pypi.org/simple/" [[tool.uv.index]] name = "testpypi" url = "https://test.pypi.org/simple/" publish-url = "https://test.pypi.org/legacy/" [tool.uv.sources] hssm = { workspace = true } [tool.pyrefly] preset = "legacy" project-includes = ["src/hssm"] ignore-missing-imports = ["*"] # pyrefly >=1.3's legacy preset turns packages without py.typed (pymc, bambi, # pandas, seaborn, ...) into Any; keep type-checking HSSM's calls into them. replace-untyped-imports-with-any = []