{"id":13688874,"url":"https://github.com/mad-lab-fau/tpcp","last_synced_at":"2026-02-04T22:44:15.639Z","repository":{"id":38395276,"uuid":"424304448","full_name":"mad-lab-fau/tpcp","owner":"mad-lab-fau","description":"Pipeline and Dataset helpers for complex algorithm evaluation.","archived":false,"fork":false,"pushed_at":"2025-07-24T12:40:07.000Z","size":19933,"stargazers_count":19,"open_issues_count":12,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-02-02T10:58:10.900Z","etag":null,"topics":["algorithms","biosignals","data-management","data-science","machine-learning","python"],"latest_commit_sha":null,"homepage":"https://tpcp.readthedocs.io/en/latest/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mad-lab-fau.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-11-03T16:40:10.000Z","updated_at":"2026-01-23T14:05:59.000Z","dependencies_parsed_at":"2023-10-12T21:31:21.695Z","dependency_job_id":"2090b6a7-052a-4ff8-a043-5b53f1e96e02","html_url":"https://github.com/mad-lab-fau/tpcp","commit_stats":{"total_commits":817,"total_committers":8,"mean_commits":102.125,"dds":0.3072215422276622,"last_synced_commit":"ae1ab527409908bca6252d4b5d2d282255bf6535"},"previous_names":[],"tags_count":59,"template":false,"template_full_name":null,"purl":"pkg:github/mad-lab-fau/tpcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mad-lab-fau%2Ftpcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mad-lab-fau%2Ftpcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mad-lab-fau%2Ftpcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mad-lab-fau%2Ftpcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mad-lab-fau","download_url":"https://codeload.github.com/mad-lab-fau/tpcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mad-lab-fau%2Ftpcp/sbom","scorecard":{"id":609958,"data":{"date":"2025-08-11","repo":{"name":"github.com/mad-lab-fau/tpcp","commit":"b889fecbebeb338948a5c0fe46da4d8e94b5dd26"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/publish.yml:1","Warn: no topLevel permission defined: .github/workflows/test-and-lint.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":5,"reason":"6 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 5","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/15 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/mad-lab-fau/tpcp/publish.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/mad-lab-fau/tpcp/publish.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test-and-lint.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/mad-lab-fau/tpcp/test-and-lint.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test-and-lint.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/mad-lab-fau/tpcp/test-and-lint.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test-and-lint.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/mad-lab-fau/tpcp/test-and-lint.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test-and-lint.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/mad-lab-fau/tpcp/test-and-lint.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test-and-lint.yml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/mad-lab-fau/tpcp/test-and-lint.yml/main?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/publish.yml:23","Warn: pipCommand not pinned by hash: .github/workflows/publish.yml:24","Info:   0 out of   5 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned","Info:   0 out of   2 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 17 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"17 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-cpwx-vrp4-4pq7","Warn: Project is vulnerable to: GHSA-gmj6-6f8f-6699","Warn: Project is vulnerable to: GHSA-q2x7-8rv6-6q7h","Warn: Project is vulnerable to: GHSA-48g7-3x6r-xfhp","Warn: Project is vulnerable to: GHSA-c9rc-mg46-23w3","Warn: Project is vulnerable to: GHSA-cjgq-5qmw-rcj6","Warn: Project is vulnerable to: GHSA-8qvm-5x2c-j2w7","Warn: Project is vulnerable to: PYSEC-2022-42969","Warn: Project is vulnerable to: GHSA-9hjg-9r4m-mvj7","Warn: Project is vulnerable to: PYSEC-2025-49 / GHSA-5rjg-fvgr-3xxf","Warn: Project is vulnerable to: GHSA-3749-ghw9-m3mg","Warn: Project is vulnerable to: PYSEC-2025-41 / GHSA-53q9-r3pm-6pq6","Warn: Project is vulnerable to: GHSA-887c-mr87-cxwp","Warn: Project is vulnerable to: GHSA-48p4-8xcf-vxj5","Warn: Project is vulnerable to: GHSA-pq67-6m6q-mj2v","Warn: Project is vulnerable to: GHSA-f9vj-2wh5-fj8j","Warn: Project is vulnerable to: GHSA-q34m-jh98-gwm2"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-21T02:23:54.322Z","repository_id":38395276,"created_at":"2025-08-21T02:23:54.322Z","updated_at":"2025-08-21T02:23:54.322Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29067647,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-04T03:31:03.593Z","status":"ssl_error","status_checked_at":"2026-02-04T03:29:50.742Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithms","biosignals","data-management","data-science","machine-learning","python"],"created_at":"2024-08-02T15:01:25.756Z","updated_at":"2026-02-04T22:44:15.633Z","avatar_url":"https://github.com/mad-lab-fau.png","language":"Python","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"\u003cimg src=\"./docs/_static/logo/tpcp_logo_with_text.png\" height=\"150\"\u003e\n\n[![PyPI](https://img.shields.io/pypi/v/tpcp)](https://pypi.org/project/tpcp/)\n[![Documentation Status](https://readthedocs.org/projects/tpcp/badge/?version=latest)](https://tpcp.readthedocs.io/en/latest/?badge=latest)\n[![codecov](https://codecov.io/gh/mad-lab-fau/tpcp/branch/main/graph/badge.svg?token=ZNVT5LNYHO)](https://codecov.io/gh/mad-lab-fau/tpcp)\n[![Test and Lint](https://github.com/mad-lab-fau/tpcp/actions/workflows/test-and-lint.yml/badge.svg?branch=main)](https://github.com/mad-lab-fau/tpcp/actions/workflows/test-and-lint.yml)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n![PyPI - Downloads](https://img.shields.io/pypi/dm/tpcp)\n[![DOI](https://joss.theoj.org/papers/10.21105/joss.04953/status.svg)](https://doi.org/10.21105/joss.04953)\n\n# tpcp - Tiny Pipelines for Complex Problems\n\nA generic way to build object-oriented datasets and algorithm pipelines and tools to evaluate them.\n\nEasily install `tpcp` via pip:\n```bash\npip install tpcp\n```\n\nOr add it to your project with [poetry](https://python-poetry.org/):\n```bash\npoetry add tpcp\n```\n\n## Why?\n\nEvaluating Algorithms - in particular when they contain machine learning - is hard.\nBesides understanding required concepts (cross validation, bias, overfitting, ...), you need to implement the required \nsteps and make them work together with your algorithms and data.\nIf you are doing something \"regular\" like training an SVM on tabular data, amazing libraries like [sklearn](https://scikit-learn.org), \n[tslearn](https://github.com/tslearn-team/tslearn), [pytorch](https://pytorch.org), and many others, have your back.\nBy using their built-in tools (e.g. `sklearn.evaluation.GridSearchCV`) you prevent implementation errors, and you are\nprovided with a sensible structure to organize your code that is well understood in the community.\n\nHowever, often the problems we are trying to solve are not regular.\nThey are **complex**.\nAs an example, here is the summary of the method from one of our [recent papers](https://jneuroengrehab.biomedcentral.com/articles/10.1186/s12984-021-00883-7):\n- We have continuous multi-dimensional sensor recordings from multiple participants from a hospital visit and multiple days at home\n- For each participant we have global metadata (age, diagnosis) and daily annotations\n- We want to train a Hidden-Markov-Model that can find events in the data streams\n- We need to tune hyper-parameters of the algorithm using a participant-wise cross validation\n- We want to evaluate the final performance of the algorithm for the settings trained on the hospital data -\u003e tested on home data and trained on home data -\u003e tested on home data\n- Using the same structure we want to evaluate a state-of-the-art algorithm to compare the results\n\nNone of the standard frameworks can easily abstract this problem, because here we have none-tabular data, multiple data \nsources per participant, a non-traditional ML algorithm, and a complex train-test split logic.\n\nWith `tpcp` we want to provide a flexible framework to approach such complex problems with structure and confidence.\n\n## How?\n\nTo make `tpcp` easy to use, we try to focus on a couple of key ideas:\n\n- Datasets are Python classes (think of [`pytorch.datasets`](https://pytorch.org/tutorials/beginner/basics/data_tutorial.html), but more flexible) that can be split, iterated over, and queried.\n- Algorithms and Pipelines are Python classes with a simple `run` and `optimize` interface, that can be implemented to fit any problem.\n- Everything is a parameter and everything is optimization: In regular ML we differentiate *training* and *hyper-parameter optimization*.\n  In `tpcp` we consider everything that modifies parameters or weights as an *optimization*.\n  This allows to use the same concepts and code interfaces from simple algorithms that just require a grid search to optimize a parameter to neuronal network pipelines with hyperparameter tuning.\n- Provide what is difficult, allow to change everything else:\n  `tpcp` implements complicated constructs like cross validation and grid search and, whenever possible, tries to catch obvious errors in your approach.\n  However, for the actual algorithm and dataset you are free to do whatever is required to solve your current research question.\n\n## Should you use tpcp?\n\n### Datasets\n\n**Yes** - the object-oriented Datasets have proven themselves to be a really nice and flexible way to encapsulate Datasets with data from multiple modalities.\nThere is a clear path of integrating lazy-loading, load-cashing, data filtering, or pre-processing on loading.\nFrom our experience, even if you ignore all the other tpcp features, Datasets can greatly simplify how you interact with your data sources and can serve as a self-documenting API for your data.\n\n[Learn more](https://tpcp.readthedocs.io/en/latest/guides/algorithms_pipelines_datasets.html#datasets) \n([Examples](https://tpcp.readthedocs.io/en/latest/auto_examples/index.html#datasets))\n\nOther projects using Datasets:\n- [gaitmap-datasets](https://github.com/mad-lab-fau/gaitmap-datasets)\n- [cold-face-test-analysis](https://github.com/mad-lab-fau/cft-analysis/tree/main/cft_analysis/datasets)\n- [carwatch-analysis](https://github.com/mad-lab-fau/carwatch-analysis/tree/main/carwatch_analysis/datasets)\n- [mobgap](https://github.com/mobilise-d/mobgap)\n\n### Parameter Optimization and Cross Validation\n\n**Maybe** - All parameter optimization features in tpcp exist to provide a unified API, in case other specific frameworks are too specialised.\nIn cases where all your algorithms can be abstracted by `sklearn`, `pytorch` (with the `skorch` wrapper), `tensorflow`/`Keras` (with the `scikeras` wrapper), \nor any other framework that provides a nice scikit-learn API, you will get all the features tpcp can provide with much less boilerplate by just using `sklearn` and `optuna` directly.\nEven, if you need to implement completely custom algorithms, we would encourage you to see if you can emulate a sklearn-like API to make use of its vast ecosystem.\n\nThis will usually work well for all algorithms that can be abstracted by the fit-predict paradigm.\nHowever, for more \"traditional\" algorithms with no \"fit\" step or complicated optimizations, the `run` (with optional `self_optimize`) API of tpcp might be a better fit.\nSo if you are using or developing algorithms across library domains, that don't all work well with a sklearn API, then **Yes**, tpcp is a good choice.\n\nLearn more:\n[General Concepts](https://tpcp.readthedocs.io/en/latest/guides/index.html#user-guides),\n[Custom Algorithms](https://tpcp.readthedocs.io/en/latest/auto_examples/index.html#algorithms), \n[Parameter Optimization](https://tpcp.readthedocs.io/en/latest/auto_examples/index.html#parameter-optimization), \n[Cross Validation](https://tpcp.readthedocs.io/en/latest/auto_examples/index.html#validation)\n\nOther projects using tpcp features:\n- [gaitmap](https://github.com/mad-lab-fau/gaitmap) - uses tpcp as basis for custom class based algorithms\n- [gaitmap-bench](https://github.com/mad-lab-fau/gaitmap-bench) - uses all tpcp features (from pipelines to optuna integration) for standardized evaluation of algorithms\n- [eargait](https://github.com/mad-lab-fau/eargait) - uses tpcp as basis for custom class based algorithms\n- [mobgap](https://github.com/mobilise-d/mobgap) - uses tpcp as basis for custom class based algorithms and to implement reproducible evaluation tools\n\n## Citation\n\nIf you use `tpcp` in your research, we would appreciate a citation to our JOSS paper.\nThis helps us to justify putting time into maintaining and improving the library.\n\n```\nKüderle et al., (2023). tpcp: Tiny Pipelines for Complex Problems - \nA set of framework independent helpers for algorithms development and evaluation. \nJournal of Open Source Software, 8(82), 4953,\nhttps://doi.org/10.21105/joss.04953\n```\n\n```bibtex\n@article{\n  Küderle2023, \n  doi = {10.21105/joss.04953},\n  url = {https://doi.org/10.21105/joss.04953},\n  year = {2023}, publisher = {The Open Journal},\n  volume = {8}, number = {82}, pages = {4953},\n  author = {Arne Küderle and Robert Richer and Raul C. Sîmpetru and Bjoern M. Eskofier},\n  title = {tpcp: Tiny Pipelines for Complex Problems - \n           A set of framework independent helpers for algorithms development and evaluation},\n  journal = {Journal of Open Source Software}\n}\n```\n\n## Contribution\n\nThe entire development is managed via [GitHub](https://github.com/mad-lab-fau/tpcp).\nIf you run into any issues, want to discuss certain decisions, want to contribute features or feature requests, just \nreach out to us by [opening a new issue](https://github.com/mad-lab-fau/tpcp/issues/new/).\n\n## Dev Setup\n\nWe are using [poetry](https://python-poetry.org/) to manage dependencies and \n[poethepoet](https://github.com/nat-n/poethepoet) to run and manage dev tasks.\n\nTo set up the dev environment *including* the required dependencies for using and developing on `tpcp` run the following\ncommands: \n```bash\ngit clone https://github.com/mad-lab-fau/tpcp\ncd tpcp\npoetry install --all-extras\n```\n\nAfterward, you can start to develop and change things.\nIf you want to run tests, format your code, build the docs, ..., you can run one of the following `poethepoet` commands\n\n```\nCONFIGURED TASKS\n  format            \n  format_unsafe     \n  lint              Lint all files with ruff.\n  ci_check          Check all potential format and linting issues.\n  test              Run Pytest with coverage.\n  docs              Build the html docs using Sphinx.\n  docs_clean        Remove all old build files and build a clean version of the docs.\n  docs_preview      Preview the built html docs.\n  version   \n```\n\nby calling\n\n```bash\npoetry run poe \u003ccommand name\u003e\n````\n\nIf you installed `poethepoet` globally, you can skip the `poetry run` part at the beginning.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmad-lab-fau%2Ftpcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmad-lab-fau%2Ftpcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmad-lab-fau%2Ftpcp/lists"}