probixi 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. probixi-0.1.0/.github/workflows/cov.yml +44 -0
  2. probixi-0.1.0/.github/workflows/format.yml +45 -0
  3. probixi-0.1.0/.github/workflows/publish.yml +71 -0
  4. probixi-0.1.0/.gitignore +227 -0
  5. probixi-0.1.0/.readthedocs.yml +24 -0
  6. probixi-0.1.0/LICENSE +21 -0
  7. probixi-0.1.0/PKG-INFO +231 -0
  8. probixi-0.1.0/README.md +183 -0
  9. probixi-0.1.0/codecov.yml +10 -0
  10. probixi-0.1.0/docs/Makefile +20 -0
  11. probixi-0.1.0/docs/conf.py +54 -0
  12. probixi-0.1.0/docs/index.rst +17 -0
  13. probixi-0.1.0/docs/make.bat +35 -0
  14. probixi-0.1.0/docs/requirements.txt +5 -0
  15. probixi-0.1.0/probixi/__init__.py +1 -0
  16. probixi-0.1.0/probixi/cli.py +206 -0
  17. probixi-0.1.0/probixi/indexer/__init__.py +17 -0
  18. probixi-0.1.0/probixi/indexer/forward.py +107 -0
  19. probixi-0.1.0/probixi/indexer/indexer.py +712 -0
  20. probixi-0.1.0/probixi/indexer/integrate.py +93 -0
  21. probixi-0.1.0/probixi/indexer/lattice.py +140 -0
  22. probixi-0.1.0/probixi/indexer/predict.py +149 -0
  23. probixi-0.1.0/probixi/indexer/refine.py +243 -0
  24. probixi-0.1.0/probixi/indexer/seed.py +145 -0
  25. probixi-0.1.0/probixi/io/__init__.py +21 -0
  26. probixi-0.1.0/probixi/io/cell.py +141 -0
  27. probixi-0.1.0/probixi/io/frames.py +241 -0
  28. probixi-0.1.0/probixi/io/geometry.py +181 -0
  29. probixi-0.1.0/probixi/io/metadata.py +100 -0
  30. probixi-0.1.0/probixi/io/writer.py +430 -0
  31. probixi-0.1.0/probixi/peakfinding/__init__.py +29 -0
  32. probixi-0.1.0/probixi/peakfinding/noise/__init__.py +22 -0
  33. probixi-0.1.0/probixi/peakfinding/noise/_diagnostics.py +220 -0
  34. probixi-0.1.0/probixi/peakfinding/noise/_drift.py +39 -0
  35. probixi-0.1.0/probixi/peakfinding/noise/_eigen_background.py +72 -0
  36. probixi-0.1.0/probixi/peakfinding/noise/_panel.py +101 -0
  37. probixi-0.1.0/probixi/peakfinding/noise/_pixel.py +45 -0
  38. probixi-0.1.0/probixi/peakfinding/noise/_radial.py +84 -0
  39. probixi-0.1.0/probixi/peakfinding/noise/calibrate.py +542 -0
  40. probixi-0.1.0/probixi/peakfinding/noise/model.py +480 -0
  41. probixi-0.1.0/probixi/peakfinding/noise/scale.py +147 -0
  42. probixi-0.1.0/probixi/peakfinding/peaks/__init__.py +10 -0
  43. probixi-0.1.0/probixi/peakfinding/peaks/blobs.py +278 -0
  44. probixi-0.1.0/probixi/peakfinding/peaks/neighborhood.py +171 -0
  45. probixi-0.1.0/probixi/peakfinding/peaks/peakfinder.py +754 -0
  46. probixi-0.1.0/probixi/probixi.py +519 -0
  47. probixi-0.1.0/pyproject.toml +83 -0
  48. probixi-0.1.0/tests/conftest.py +67 -0
  49. probixi-0.1.0/tests/fixtures/Eiger4M.geom +49 -0
  50. probixi-0.1.0/tests/fixtures/bR.cell +11 -0
  51. probixi-0.1.0/tests/sim.py +453 -0
  52. probixi-0.1.0/tests/test_cell.py +87 -0
  53. probixi-0.1.0/tests/test_forward.py +80 -0
  54. probixi-0.1.0/tests/test_geometry.py +84 -0
  55. probixi-0.1.0/tests/test_indexing.py +131 -0
  56. probixi-0.1.0/tests/test_io.py +205 -0
  57. probixi-0.1.0/tests/test_lattice.py +93 -0
  58. probixi-0.1.0/tests/test_noise.py +163 -0
  59. probixi-0.1.0/tests/test_peakfinding.py +262 -0
  60. probixi-0.1.0/tests/test_pipeline_cli.py +301 -0
  61. probixi-0.1.0/tests/test_predict_integrate.py +253 -0
  62. probixi-0.1.0/tests/test_seed_refine.py +238 -0
  63. probixi-0.1.0/tests/test_stream.py +228 -0
  64. probixi-0.1.0/tests/test_writer_format.py +100 -0
@@ -0,0 +1,44 @@
1
+ name: Test+Upload probixi
2
+
3
+ on:
4
+ push:
5
+ branches: [ "main" ]
6
+ pull_request:
7
+ branches: [ "main" ]
8
+ workflow_dispatch:
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ jobs:
14
+ test:
15
+ runs-on: ${{ matrix.os }}
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ os: [macos-26]
20
+ python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
21
+
22
+ steps:
23
+ - uses: actions/checkout@v6
24
+
25
+ - name: Install uv
26
+ uses: astral-sh/setup-uv@v8.2.0
27
+
28
+ - name: Set up Python ${{ matrix.python-version }}
29
+ run: uv python install ${{ matrix.python-version }}
30
+
31
+ - name: Install dependencies
32
+ run: |
33
+ uv venv --python ${{ matrix.python-version }}
34
+ uv pip install pytest pytest-cov
35
+ uv pip install -e ".[dev]"
36
+
37
+ - name: Test with pytest
38
+ run: |
39
+ uv run pytest tests/ -v --cov=probixi --cov-report=xml
40
+
41
+ - name: Upload coverage reports to Codecov
42
+ uses: codecov/codecov-action@v7
43
+ with:
44
+ token: ${{ secrets.CODECOV_TOKEN }}
@@ -0,0 +1,45 @@
1
+ name: Auto-format Code
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [main, devel*]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: write
10
+
11
+ jobs:
12
+ format:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v6
16
+ with:
17
+ token: ${{ secrets.GITHUB_TOKEN }}
18
+ ref: ${{ github.head_ref || github.ref_name }}
19
+
20
+ - name: Set up Python
21
+ uses: actions/setup-python@v6
22
+ with:
23
+ python-version: '3.11'
24
+
25
+ - name: Install formatters
26
+ run: pip install black isort ruff
27
+
28
+ - name: Auto-fix lint issues with Ruff
29
+ run: ruff check --fix --exit-zero .
30
+
31
+ - name: Sort imports with isort
32
+ run: isort .
33
+
34
+ - name: Format with Black
35
+ run: black .
36
+
37
+ - name: Commit changes
38
+ run: |
39
+ git config --local user.email "github-actions[bot]@users.noreply.github.com"
40
+ git config --local user.name "github-actions[bot]"
41
+ git diff --quiet || (git add -A && git commit -m "Auto-format code (black, isort, ruff)")
42
+ git push
43
+
44
+ - name: Flag remaining lint issues with Ruff
45
+ run: ruff check --output-format=github .
@@ -0,0 +1,71 @@
1
+ # This workflow will upload a Python Package to PyPI when a release is created
2
+ # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
3
+
4
+ # This workflow uses actions that are not certified by GitHub.
5
+ # They are provided by a third-party and are governed by
6
+ # separate terms of service, privacy policy, and support
7
+ # documentation.
8
+
9
+ name: Upload Python Package
10
+
11
+ on:
12
+ release:
13
+ types: [published]
14
+ workflow_dispatch:
15
+
16
+ permissions:
17
+ contents: read
18
+
19
+ jobs:
20
+ release-build:
21
+ runs-on: ubuntu-latest
22
+
23
+ steps:
24
+ - uses: actions/checkout@v6
25
+
26
+ - uses: actions/setup-python@v6
27
+ with:
28
+ python-version: "3.x"
29
+
30
+ - name: Build release distributions
31
+ run: |
32
+ # NOTE: put your own distribution build steps here.
33
+ python -m pip install build
34
+ python -m build
35
+
36
+ - name: Upload distributions
37
+ uses: actions/upload-artifact@v7
38
+ with:
39
+ name: release-dists
40
+ path: dist/
41
+
42
+ pypi-publish:
43
+ runs-on: ubuntu-latest
44
+ needs:
45
+ - release-build
46
+ permissions:
47
+ # IMPORTANT: this permission is mandatory for trusted publishing
48
+ id-token: write
49
+
50
+ # Dedicated environments with protections for publishing are strongly recommended.
51
+ # For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules
52
+ environment:
53
+ name: pypi
54
+ # OPTIONAL: uncomment and update to include your PyPI project URL in the deployment status:
55
+ # url: https://pypi.org/p/YOURPROJECT
56
+ #
57
+ # ALTERNATIVE: if your GitHub Release name is the PyPI project version string
58
+ # ALTERNATIVE: exactly, uncomment the following line instead:
59
+ # url: https://pypi.org/project/YOURPROJECT/${{ github.event.release.name }}
60
+
61
+ steps:
62
+ - name: Retrieve release distributions
63
+ uses: actions/download-artifact@v8
64
+ with:
65
+ name: release-dists
66
+ path: dist/
67
+
68
+ - name: Publish release distributions to PyPI
69
+ uses: pypa/gh-action-pypi-publish@release/v1
70
+ with:
71
+ packages-dir: dist/
@@ -0,0 +1,227 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ # Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ # poetry.lock
109
+ # poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ # pdm.lock
116
+ # pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ # pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # Redis
135
+ *.rdb
136
+ *.aof
137
+ *.pid
138
+
139
+ # RabbitMQ
140
+ mnesia/
141
+ rabbitmq/
142
+ rabbitmq-data/
143
+
144
+ # ActiveMQ
145
+ activemq-data/
146
+
147
+ # SageMath parsed files
148
+ *.sage.py
149
+
150
+ # Environments
151
+ .env
152
+ .envrc
153
+ .venv
154
+ env/
155
+ venv/
156
+ ENV/
157
+ env.bak/
158
+ venv.bak/
159
+
160
+ # Spyder project settings
161
+ .spyderproject
162
+ .spyproject
163
+
164
+ # Rope project settings
165
+ .ropeproject
166
+
167
+ # mkdocs documentation
168
+ /site
169
+
170
+ # mypy
171
+ .mypy_cache/
172
+ .dmypy.json
173
+ dmypy.json
174
+
175
+ # Pyre type checker
176
+ .pyre/
177
+
178
+ # pytype static type analyzer
179
+ .pytype/
180
+
181
+ # Cython debug symbols
182
+ cython_debug/
183
+
184
+ # PyCharm
185
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
186
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
187
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
188
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
189
+ # .idea/
190
+
191
+ # Abstra
192
+ # Abstra is an AI-powered process automation framework.
193
+ # Ignore directories containing user credentials, local state, and settings.
194
+ # Learn more at https://abstra.io/docs
195
+ .abstra/
196
+
197
+ # Visual Studio Code
198
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
199
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
200
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
201
+ # you could uncomment the following to ignore the entire vscode folder
202
+ # .vscode/
203
+ # Temporary file for partial code execution
204
+ tempCodeRunnerFile.py
205
+
206
+ # Ruff stuff:
207
+ .ruff_cache/
208
+
209
+ # PyPI configuration file
210
+ .pypirc
211
+
212
+ # Marimo
213
+ marimo/_static/
214
+ marimo/_lsp/
215
+ __marimo__/
216
+
217
+ # Streamlit
218
+ .streamlit/secrets.toml
219
+
220
+ # Other
221
+ uv.lock
222
+ .DS_Store
223
+ test_data/
224
+ testing.py
225
+
226
+ tests/test_data/
227
+ tests/*.h5
@@ -0,0 +1,24 @@
1
+ # Read the Docs configuration file
2
+ # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
3
+
4
+ # Required
5
+ version: 2
6
+
7
+ # Set the OS, Python version, and other tools you might need
8
+ build:
9
+ os: ubuntu-24.04
10
+ tools:
11
+ python: "3.13"
12
+
13
+ # Build documentation in the "docs/" directory with Sphinx
14
+ sphinx:
15
+ configuration: docs/conf.py
16
+
17
+ # Optionally, but recommended,
18
+ # declare the Python requirements required to build your documentation
19
+ # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
20
+ python:
21
+ install:
22
+ - requirements: docs/requirements.txt
23
+ - method: pip
24
+ path: .
probixi-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ryan O'Dea
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
probixi-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,231 @@
1
+ Metadata-Version: 2.4
2
+ Name: probixi
3
+ Version: 0.1.0
4
+ Summary: Self-Calibrating Probabilistic Peak Finding for Serial X-Ray Crystallography
5
+ Project-URL: Homepage, https://github.com/ryan-odea/probixi
6
+ Project-URL: Repository, https://github.com/ryan-odea/probixi
7
+ Project-URL: Bug Tracker, https://github.com/ryan-odea/probixi/issues
8
+ Project-URL: Ryan O'Dea (ORCID), https://orcid.org/0009-0000-0103-9546
9
+ Author-email: Ryan O'Dea <ryan.odea@psi.ch>
10
+ Maintainer-email: Ryan O'Dea <ryan.odea@psi.ch>
11
+ License: MIT
12
+ License-File: LICENSE
13
+ Keywords: peak finding,probabilistic,x-ray crystallography
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Requires-Python: >=3.9
24
+ Requires-Dist: click
25
+ Requires-Dist: h5py
26
+ Requires-Dist: hdf5plugin
27
+ Requires-Dist: matplotlib
28
+ Requires-Dist: numpy
29
+ Requires-Dist: pillow
30
+ Requires-Dist: torch
31
+ Provides-Extra: dev
32
+ Requires-Dist: black; extra == 'dev'
33
+ Requires-Dist: isort; extra == 'dev'
34
+ Requires-Dist: myst-parser; extra == 'dev'
35
+ Requires-Dist: piccolo-theme; extra == 'dev'
36
+ Requires-Dist: pytest; extra == 'dev'
37
+ Requires-Dist: ruff; extra == 'dev'
38
+ Requires-Dist: sphinx; extra == 'dev'
39
+ Requires-Dist: sphinx-autodoc-typehints; extra == 'dev'
40
+ Requires-Dist: sphinx-copybutton; extra == 'dev'
41
+ Provides-Extra: docs
42
+ Requires-Dist: myst-parser; extra == 'docs'
43
+ Requires-Dist: piccolo-theme; extra == 'docs'
44
+ Requires-Dist: sphinx; extra == 'docs'
45
+ Requires-Dist: sphinx-autodoc-typehints; extra == 'docs'
46
+ Requires-Dist: sphinx-copybutton; extra == 'docs'
47
+ Description-Content-Type: text/markdown
48
+
49
+ # probixi - Self-Calibrating (PROB)ab(I)listic Peak Detection for Serial (X)-Ray Crystallograph(I)c Data
50
+
51
+ [![Lifecycle:
52
+ experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental)
53
+ [![PyPI version](https://badge.fury.io/py/probixi.svg)](https://pypi.org/project/probixi)
54
+ ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/probixi)
55
+ [![PyTorch](https://img.shields.io/badge/PyTorch-2.4+-ee4c2c.svg)](https://pytorch.org/)
56
+ [![codecov](https://codecov.io/gh/ryan-odea/Probixi/graph/badge.svg?token=DMOVJJUWXP)](https://codecov.io/gh/ryan-odea/Probixi)
57
+ [![CUDA](https://img.shields.io/badge/CUDA-supported-76b900.svg)](https://developer.nvidia.com/cuda-zone)
58
+ [![Apple Silicon MPS](https://img.shields.io/badge/Apple%20Silicon-MPS-000000.svg?logo=apple)](https://developer.apple.com/metal/pytorch/)
59
+ [![Downloads](https://static.pepy.tech/badge/probixi)](https://pepy.tech/project/probixi)
60
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
61
+ [![Documentation Status](https://readthedocs.org/projects/probixi/badge/?version=latest)](https://probixi.readthedocs.io)
62
+ [![Code Style](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
63
+
64
+
65
+ `probixi` proposes that bragg peaks can be found/recovered from a detector image by observing the background noise distributional shape over time, per pixel, and collecting peak candidates from an outlier set. Since this noise model is determined in an unsupervised fashion, the user does not need to tune hyperparameters for finding peaks. We are still testing robustness to different types of data collection (synchrotron, FEL) and random fluence changes, results will be included in this README as they arrive.
66
+
67
+ ## Installing the Package
68
+
69
+ You can install via Pypi with pip:
70
+
71
+ ```bash
72
+ pip install probixi
73
+ ```
74
+
75
+ Or the latest development version with
76
+
77
+ ```bash
78
+ pip install git+https://github.com/ryan-odea/probixi.git
79
+ ```
80
+
81
+ ## Using `probixi`
82
+
83
+ `probixi` can be interacted with either via the command line interface, or through the python API. In it's current implementation, via python, the `Probixi` API returns iterables, which remain on a GPU tensor via pytorch up until collection - meaning that you can further pass information for any downstream processing. Through the CLI, this is currently a one-stop-shop for peakfinding and indexing. **This may change in the future**
84
+
85
+ `probixi` also has a 'burn-in' phase, where the noise model reaches some stable point, this can be further interrogated with a handy gif.
86
+
87
+ Via the CLI:
88
+
89
+ ```bash
90
+ probixi -i files.lst -g myGeometry.geom -p myCell.cell -o stream.stream --device cuda --gif myNoiseModel.gif
91
+ ```
92
+
93
+ Or with python:
94
+
95
+ ```python
96
+ import torch
97
+
98
+ from probixi import Probixi
99
+ from probixi.io import DataOffloader
100
+
101
+ pipeline = Probixi(
102
+ list_file="files.lst",
103
+ geometry_file="myGeometry.geom",
104
+ cell_file="myCell.cell",
105
+ device=torch.device("cuda"),
106
+ )
107
+
108
+ pipeline.noise_diagnostics("myNoiseModel.gif", stop=32)
109
+ cal = pipeline.calibrate(n_seed=1636)
110
+ print(f"kappa={cal.kappa:.2f} prior_peak={cal.prior_peak:.4f} "
111
+ f"threshold={pipeline.threshold_calibration.threshold:.2f}")
112
+
113
+ # Stream every frame through detect -> index -> predict + integrate. The stream
114
+ # is lazy and each result stays on the GPU until you touch it, so you can branch
115
+ # off any downstream processing with torch
116
+ with DataOffloader(
117
+ "stream.stream",
118
+ geometry=pipeline.geometry,
119
+ cell=pipeline.target_cell,
120
+ geometry_file="myGeometry.geom",
121
+ files=pipeline.metadata.files,
122
+ ) as off:
123
+ for result in pipeline.index_stream(pipeline.frames(), batch_size=8):
124
+ off.write(result) # or: pipeline.index_stream(...).to_stream(off)
125
+ print(f"frame {result.frame_index}: "
126
+ f"{result.n_indexed}/{result.n_peaks} indexed (rmsd {result.rmsd:.4f})")
127
+ ```
128
+
129
+ ## Comparison with other works
130
+
131
+ Here, we provide a comparison with other peakfinding algorithms with real data. Using a randomly sampled 10,000 frames from experimentally collected data.
132
+
133
+ Notes:
134
+
135
+ 1. For wall time, because `probixi` handles optimizing internal hyperparameters automatically, I have included time used for loose manual hyperparameter tuning on 10% subsamples to find optimal SNR, threshold, and minimum pixels. CPU time for only peakfinding and indexing is bracketed.
136
+ 2. Percent agreement is calculated as the (set of crystals indexed by probixi) / (set of crystals indexed by the reference) * 100. Greater than 100 indicates that `probixi` was able to index more crystals.
137
+
138
+ Benchmarks were run on:
139
+
140
+ - GPU: A100
141
+ - CPU: TODO which CPU do Ra nodes use?
142
+
143
+ ### `peakfinder8 + indexamajig`
144
+
145
+ | Dataset | Percent Indexed (`probixi`) | GPU time (`probixi`) | Percent Indexed (`peakfinder8+indexamajig`) | CPU Time (`peakfinder8+indexamajig`) [No-Tuning] | Percent Agreement |
146
+ |---------------------------------------|---------------------------|---------------------|-------------------------------------|-------------------------------|-------------------|
147
+ | Lysozyme-Synchrotron | | | | | |
148
+ | Lysozyme-FEL | | | | | |
149
+ | BacterioRhodopsin-Synchrotron | | | | | |
150
+ | BacterioRhodopsin-FEL | | | | | |
151
+ | Randomly Dimmed Lysozyme-FEL | | | | | |
152
+ | Randomly Dimmed BacterioRhodopsin-FEL | | | | | |
153
+
154
+ ### pyFAI + TORO
155
+
156
+ Perhaps a more fair comparison, especially with respect to speed, is [pyFAI][pyfai] (azimuthal
157
+ integration and peak picking) paired with the [TORO][toro] indexer, which both run on the GPU.
158
+
159
+ [pyfai]: https://doi.org/10.1107/S1600576715004306
160
+ [toro]: https://doi.org/10.1107/S1600576724003182
161
+
162
+
163
+ | Dataset | Percent Indexed (`probixi`) | GPU time (`probixi`) | Percent Indexed (`pyFAI+TORO`) | GPU Time (`pyFAI+TORO`) [No-Tuning] | Percent Agreement |
164
+ |---------------------------------------|---------------------------|---------------------|-------------------------------------|-------------------------------|-------------------|
165
+ | Lysozyme-Synchrotron | | | | | |
166
+ | Lysozyme-FEL | | | | | |
167
+ | BacterioRhodopsin-Synchrotron | | | | | |
168
+ | BacterioRhodopsin-FEL | | | | | |
169
+ | Randomly Dimmed Lysozyme-FEL | | | | | |
170
+ | Randomly Dimmed BacterioRhodopsin-FEL | | | | | |
171
+
172
+
173
+ ### Using `probixi` as only a peakfinder
174
+
175
+ Of course, if you only want to use probixi as a peakfinder and prefer to use your own indexing regime, this is possible -- through the CLI's `--peaks-only` flag or the Python API's `peak_stream`.
176
+
177
+ Via the CLI:
178
+
179
+ ```bash
180
+ probixi -i files.lst -g myGeometry.geom -o peaks.stream --peaks-only --device cuda
181
+ ```
182
+
183
+ Or with python:
184
+
185
+ ```python
186
+ import torch
187
+
188
+ from probixi import Probixi
189
+ from probixi.io import PeakOffloader
190
+
191
+ pipeline = Probixi(
192
+ list_file="files.lst",
193
+ geometry_file="myGeometry.geom",
194
+ device=torch.device("cuda"),
195
+ )
196
+
197
+ # Calibrate the noise model + detection threshold on the seed frames, as usual.
198
+ pipeline.calibrate(n_seed=1636)
199
+
200
+ peaks = pipeline.peak_stream(pipeline.frames(), estimate_scale=False)
201
+ with PeakOffloader(
202
+ "peaks.stream",
203
+ geometry=pipeline.geometry,
204
+ geometry_file="myGeometry.geom",
205
+ files=pipeline.metadata.files,
206
+ ) as off:
207
+ for result in peaks:
208
+ if len(result): # skip blanks; export only frames with peaks
209
+ off.write(result)
210
+ ```
211
+
212
+ ## Dependencies
213
+
214
+ - python >= 3.9
215
+ - click
216
+ - h5py
217
+ - hdf5plugin
218
+ - numpy
219
+ - torch
220
+ - matplotlib
221
+ - pillow
222
+
223
+ ## Contributing
224
+
225
+ There are many different ways to contribute to further development of this tool. If you experience a bug or would like an additional feature, please open up a [ticket](https://github.com/ryan-odea/probixi/issues).
226
+
227
+ If you would like to contribute actively by merging code, please open a PR with the following:
228
+
229
+ 1. Code is formatted with `isort`, then `black`, followed by a `ruff --check`. This will initiate on PR, so it might be best to check beforehand.
230
+ 2. Docstrings are minimally on user-facing functions in [`numpy` style](https://numpydoc.readthedocs.io/en/latest/format.html).
231
+ 3. Comments, or some explanation (in PR) for the additions, limited to the scope of the project. If fixing a bug, comments should be included in the PR rather than the code itself.