AGeDi 1.0.1__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 (142) hide show
  1. agedi-1.0.1/.github/ISSUE_TEMPLATE/bug_report.md +41 -0
  2. agedi-1.0.1/.github/ISSUE_TEMPLATE/feature_request.md +25 -0
  3. agedi-1.0.1/.github/pull_request_template.md +23 -0
  4. agedi-1.0.1/.github/workflows/auto-tag.yml +49 -0
  5. agedi-1.0.1/.github/workflows/publish.yml +88 -0
  6. agedi-1.0.1/.github/workflows/python-package.yml +34 -0
  7. agedi-1.0.1/.gitignore +10 -0
  8. agedi-1.0.1/.readthedocs.yaml +32 -0
  9. agedi-1.0.1/CHANGELOG.md +60 -0
  10. agedi-1.0.1/CONTRIBUTING.md +58 -0
  11. agedi-1.0.1/LICENSE +674 -0
  12. agedi-1.0.1/PKG-INFO +154 -0
  13. agedi-1.0.1/README.md +128 -0
  14. agedi-1.0.1/VERSION +1 -0
  15. agedi-1.0.1/docs/Makefile +20 -0
  16. agedi-1.0.1/docs/_autoapi_templates/python/attribute.rst +1 -0
  17. agedi-1.0.1/docs/_autoapi_templates/python/class.rst +60 -0
  18. agedi-1.0.1/docs/_autoapi_templates/python/data.rst +37 -0
  19. agedi-1.0.1/docs/_autoapi_templates/python/exception.rst +1 -0
  20. agedi-1.0.1/docs/_autoapi_templates/python/function.rst +15 -0
  21. agedi-1.0.1/docs/_autoapi_templates/python/method.rst +19 -0
  22. agedi-1.0.1/docs/_autoapi_templates/python/module.rst +114 -0
  23. agedi-1.0.1/docs/_autoapi_templates/python/package.rst +1 -0
  24. agedi-1.0.1/docs/_autoapi_templates/python/property.rst +15 -0
  25. agedi-1.0.1/docs/agedi.svg +42 -0
  26. agedi-1.0.1/docs/diff.gif +0 -0
  27. agedi-1.0.1/docs/make.bat +35 -0
  28. agedi-1.0.1/docs/pure-logo.svg +33 -0
  29. agedi-1.0.1/docs/requirements.txt +4 -0
  30. agedi-1.0.1/docs/source/concepts.rst +112 -0
  31. agedi-1.0.1/docs/source/conf.py +36 -0
  32. agedi-1.0.1/docs/source/images/cli-agedi-sample.svg +172 -0
  33. agedi-1.0.1/docs/source/images/cli-agedi-train.svg +235 -0
  34. agedi-1.0.1/docs/source/images/cli-agedi.svg +116 -0
  35. agedi-1.0.1/docs/source/images/make_images.sh +3 -0
  36. agedi-1.0.1/docs/source/index.rst +20 -0
  37. agedi-1.0.1/docs/source/installation.rst +57 -0
  38. agedi-1.0.1/docs/source/overview.rst +52 -0
  39. agedi-1.0.1/docs/source/references.rst +25 -0
  40. agedi-1.0.1/docs/source/troubleshooting.rst +89 -0
  41. agedi-1.0.1/docs/source/tutorial/agedi-inspect.png +0 -0
  42. agedi-1.0.1/docs/source/tutorial/agedi-train.png +0 -0
  43. agedi-1.0.1/docs/source/tutorial/api.rst +316 -0
  44. agedi-1.0.1/docs/source/tutorial/cli.rst +304 -0
  45. agedi-1.0.1/docs/source/tutorial/objects.rst +361 -0
  46. agedi-1.0.1/docs/source/tutorial/pdo.rst +151 -0
  47. agedi-1.0.1/docs/source/tutorial/train_hydra.rst +206 -0
  48. agedi-1.0.1/docs/source/tutorial/tutorial.rst +14 -0
  49. agedi-1.0.1/docs/tutorial_data/PdO_training_data.traj +0 -0
  50. agedi-1.0.1/docs/tutorial_data/template.traj +0 -0
  51. agedi-1.0.1/float +0 -0
  52. agedi-1.0.1/pyproject.toml +55 -0
  53. agedi-1.0.1/src/agedi/__init__.py +35 -0
  54. agedi-1.0.1/src/agedi/api/__init__.py +29 -0
  55. agedi-1.0.1/src/agedi/api/_display.py +359 -0
  56. agedi-1.0.1/src/agedi/api/_registry.py +360 -0
  57. agedi-1.0.1/src/agedi/api/dataset.py +155 -0
  58. agedi-1.0.1/src/agedi/api/diffusion.py +228 -0
  59. agedi-1.0.1/src/agedi/api/prediction.py +88 -0
  60. agedi-1.0.1/src/agedi/api/sampling.py +141 -0
  61. agedi-1.0.1/src/agedi/api/training.py +681 -0
  62. agedi-1.0.1/src/agedi/cli/__init__.py +0 -0
  63. agedi-1.0.1/src/agedi/cli/inspect.py +170 -0
  64. agedi-1.0.1/src/agedi/cli/main.py +19 -0
  65. agedi-1.0.1/src/agedi/cli/predict.py +91 -0
  66. agedi-1.0.1/src/agedi/cli/sample.py +177 -0
  67. agedi-1.0.1/src/agedi/cli/train.py +422 -0
  68. agedi-1.0.1/src/agedi/cli/train_hydra.py +43 -0
  69. agedi-1.0.1/src/agedi/conf/train.yaml +105 -0
  70. agedi-1.0.1/src/agedi/data/__init__.py +5 -0
  71. agedi-1.0.1/src/agedi/data/atoms_graph.py +1281 -0
  72. agedi-1.0.1/src/agedi/data/callbacks.py +322 -0
  73. agedi-1.0.1/src/agedi/data/dataset.py +414 -0
  74. agedi-1.0.1/src/agedi/data/transforms.py +72 -0
  75. agedi-1.0.1/src/agedi/diffusion/__init__.py +5 -0
  76. agedi-1.0.1/src/agedi/diffusion/agedi.py +440 -0
  77. agedi-1.0.1/src/agedi/diffusion/diffusion.py +1123 -0
  78. agedi-1.0.1/src/agedi/diffusion/distributions/__init__.py +17 -0
  79. agedi-1.0.1/src/agedi/diffusion/distributions/base.py +99 -0
  80. agedi-1.0.1/src/agedi/diffusion/distributions/categorical.py +30 -0
  81. agedi-1.0.1/src/agedi/diffusion/distributions/constant.py +66 -0
  82. agedi-1.0.1/src/agedi/diffusion/distributions/normal.py +153 -0
  83. agedi-1.0.1/src/agedi/diffusion/distributions/uniform.py +171 -0
  84. agedi-1.0.1/src/agedi/diffusion/guidance.py +388 -0
  85. agedi-1.0.1/src/agedi/diffusion/noisers/__init__.py +35 -0
  86. agedi-1.0.1/src/agedi/diffusion/noisers/base.py +277 -0
  87. agedi-1.0.1/src/agedi/diffusion/noisers/pos.py +412 -0
  88. agedi-1.0.1/src/agedi/diffusion/noisers/sde.py +222 -0
  89. agedi-1.0.1/src/agedi/diffusion/noisers/types.py +491 -0
  90. agedi-1.0.1/src/agedi/diffusion/sdes/__init__.py +5 -0
  91. agedi-1.0.1/src/agedi/diffusion/sdes/base.py +177 -0
  92. agedi-1.0.1/src/agedi/diffusion/sdes/noise_schedules.py +118 -0
  93. agedi-1.0.1/src/agedi/diffusion/sdes/ve.py +125 -0
  94. agedi-1.0.1/src/agedi/diffusion/sdes/vp.py +144 -0
  95. agedi-1.0.1/src/agedi/functional.py +61 -0
  96. agedi-1.0.1/src/agedi/models/__init__.py +5 -0
  97. agedi-1.0.1/src/agedi/models/conditionings/__init__.py +6 -0
  98. agedi-1.0.1/src/agedi/models/conditionings/base.py +208 -0
  99. agedi-1.0.1/src/agedi/models/conditionings/integer.py +67 -0
  100. agedi-1.0.1/src/agedi/models/conditionings/scalar.py +63 -0
  101. agedi-1.0.1/src/agedi/models/conditionings/time.py +107 -0
  102. agedi-1.0.1/src/agedi/models/head.py +99 -0
  103. agedi-1.0.1/src/agedi/models/regressor.py +150 -0
  104. agedi-1.0.1/src/agedi/models/schnetpack/__init__.py +2 -0
  105. agedi-1.0.1/src/agedi/models/schnetpack/heads.py +239 -0
  106. agedi-1.0.1/src/agedi/models/schnetpack/regressor_heads.py +277 -0
  107. agedi-1.0.1/src/agedi/models/schnetpack/translator.py +172 -0
  108. agedi-1.0.1/src/agedi/models/score.py +200 -0
  109. agedi-1.0.1/src/agedi/models/translator.py +295 -0
  110. agedi-1.0.1/src/agedi/utils/__init__.py +3 -0
  111. agedi-1.0.1/src/agedi/utils/offsets.py +29 -0
  112. agedi-1.0.1/src/agedi/utils/truncated_normal.py +209 -0
  113. agedi-1.0.1/tests/conftest.py +126 -0
  114. agedi-1.0.1/tests/data/conftest.py +35 -0
  115. agedi-1.0.1/tests/data/test_atoms_graph.py +278 -0
  116. agedi-1.0.1/tests/data/test_callbacks.py +62 -0
  117. agedi-1.0.1/tests/data/test_dataset.py +138 -0
  118. agedi-1.0.1/tests/data/test_dataset_extended.py +124 -0
  119. agedi-1.0.1/tests/data/test_neighborlist.py +248 -0
  120. agedi-1.0.1/tests/data/test_transforms.py +42 -0
  121. agedi-1.0.1/tests/diffusion/conftest.py +1 -0
  122. agedi-1.0.1/tests/diffusion/distributions/test_categorical.py +21 -0
  123. agedi-1.0.1/tests/diffusion/distributions/test_constant_uniform.py +149 -0
  124. agedi-1.0.1/tests/diffusion/noisers/test_distributions.py +81 -0
  125. agedi-1.0.1/tests/diffusion/noisers/test_pos.py +154 -0
  126. agedi-1.0.1/tests/diffusion/noisers/test_sde_noiser.py +66 -0
  127. agedi-1.0.1/tests/diffusion/noisers/test_sdes.py +86 -0
  128. agedi-1.0.1/tests/diffusion/noisers/test_types.py +229 -0
  129. agedi-1.0.1/tests/diffusion/sdes/test_noise_schedules.py +93 -0
  130. agedi-1.0.1/tests/diffusion/test_diffusion.py +55 -0
  131. agedi-1.0.1/tests/diffusion/test_diffusion_extended.py +257 -0
  132. agedi-1.0.1/tests/diffusion/test_sampler.py +190 -0
  133. agedi-1.0.1/tests/models/conditionings/test_integer.py +34 -0
  134. agedi-1.0.1/tests/models/schnetpack/test_heads.py +29 -0
  135. agedi-1.0.1/tests/models/schnetpack/test_heads_extended.py +48 -0
  136. agedi-1.0.1/tests/models/schnetpack/test_regressor_heads.py +47 -0
  137. agedi-1.0.1/tests/models/schnetpack/test_translator.py +82 -0
  138. agedi-1.0.1/tests/models/test_head_conditioning_extras.py +93 -0
  139. agedi-1.0.1/tests/models/test_regressor.py +109 -0
  140. agedi-1.0.1/tests/test_functional.py +755 -0
  141. agedi-1.0.1/tests/utils/test_truncated_normal.py +83 -0
  142. agedi-1.0.1/uv.lock +2986 -0
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: Bug report
3
+ about: Report a problem with AGeDi
4
+ title: "[Bug] "
5
+ labels: bug
6
+ assignees: ''
7
+ ---
8
+
9
+ ## Describe the bug
10
+
11
+ A clear and concise description of what the bug is.
12
+
13
+ ## To reproduce
14
+
15
+ Minimal reproducible example:
16
+
17
+ ```python
18
+ import agedi
19
+ # ...
20
+ ```
21
+
22
+ ## Expected behaviour
23
+
24
+ What you expected to happen.
25
+
26
+ ## Actual behaviour
27
+
28
+ What actually happened (include the full traceback).
29
+
30
+ ```
31
+ Traceback (most recent call last):
32
+ ...
33
+ ```
34
+
35
+ ## Environment
36
+
37
+ - **AGeDi version**: <!-- python -c "import agedi; print(agedi.__version__)" -->
38
+ - **Python version**:
39
+ - **PyTorch version**:
40
+ - **Operating system**:
41
+ - **GPU** (if relevant):
@@ -0,0 +1,25 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest a new feature or improvement
4
+ title: "[Feature] "
5
+ labels: enhancement
6
+ assignees: ''
7
+ ---
8
+
9
+ ## Motivation
10
+
11
+ Describe the use-case or problem that motivates this feature request.
12
+
13
+ ## Proposed solution
14
+
15
+ A clear description of what you would like to happen, including a sketch of
16
+ the proposed API if applicable.
17
+
18
+ ## Alternatives considered
19
+
20
+ Have you considered any alternative approaches? If so, why were they
21
+ rejected?
22
+
23
+ ## Additional context
24
+
25
+ Any other context, references, or screenshots that may be helpful.
@@ -0,0 +1,23 @@
1
+ ## Summary
2
+
3
+ <!-- One-paragraph description of the change and why it is needed. -->
4
+
5
+ ## Type of change
6
+
7
+ - [ ] Bug fix
8
+ - [ ] New feature
9
+ - [ ] Breaking change
10
+ - [ ] Documentation update
11
+ - [ ] Refactor / cleanup
12
+
13
+ ## Checklist
14
+
15
+ - [ ] Tests added / updated for all new behaviour
16
+ - [ ] `CHANGELOG.md` updated under `[Unreleased]`
17
+ - [ ] All existing tests pass (`pytest`)
18
+ - [ ] Docstrings updated for new/changed public API
19
+ - [ ] No new `print()` calls in library code (use `warnings.warn` or Rich `Console`)
20
+
21
+ ## Related issues
22
+
23
+ <!-- Closes #<issue number> -->
@@ -0,0 +1,49 @@
1
+ name: Auto Tag on Version Bump
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ paths:
8
+ - 'VERSION' # The workflow now triggers ONLY when the VERSION file changes
9
+
10
+ jobs:
11
+ create_tag:
12
+ runs-on: ubuntu-latest
13
+ permissions:
14
+ contents: write
15
+
16
+ steps:
17
+ - name: Checkout code
18
+ uses: actions/checkout@v4
19
+
20
+ - name: Extract version from VERSION file
21
+ id: get_version
22
+ # Reading a plain text file is as simple as using 'cat'
23
+ run: |
24
+ VERSION=$(cat VERSION | tr -d '[:space:]') # tr removes trailing newlines just in case
25
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
26
+ echo "Detected version: $VERSION"
27
+
28
+ - name: Check if tag already exists
29
+ id: check_tag
30
+ run: |
31
+ TAG="v${{ steps.get_version.outputs.version }}"
32
+ if git ls-remote --tags origin | grep -q "refs/tags/$TAG"; then
33
+ echo "Tag $TAG already exists."
34
+ echo "exists=true" >> $GITHUB_OUTPUT
35
+ else
36
+ echo "Tag $TAG does not exist. Proceeding."
37
+ echo "exists=false" >> $GITHUB_OUTPUT
38
+ fi
39
+
40
+ - name: Create and push tag
41
+ if: steps.check_tag.outputs.exists == 'false'
42
+ run: |
43
+ TAG="v${{ steps.get_version.outputs.version }}"
44
+
45
+ git config user.name "github-actions[bot]"
46
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
47
+
48
+ git tag "$TAG"
49
+ git push origin "$TAG"
@@ -0,0 +1,88 @@
1
+ name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*' # Triggers on tag pushes
7
+ workflow_dispatch: # Triggers on manual button clicks
8
+
9
+ jobs:
10
+ # ---------------------------------------------------------
11
+ # JOB 1: Build the package (Runs every time)
12
+ # ---------------------------------------------------------
13
+ build:
14
+ name: Build package
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: '3.x'
23
+
24
+ - name: Install build dependencies
25
+ run: python -m pip install --upgrade pip build
26
+
27
+ - name: Build the package
28
+ run: python -m build
29
+
30
+ - name: Store the distribution packages
31
+ uses: actions/upload-artifact@v4
32
+ with:
33
+ name: python-package-distributions
34
+ path: dist/
35
+
36
+ # ---------------------------------------------------------
37
+ # JOB 2: Publish to TestPyPI (ONLY runs on Tag Push)
38
+ # ---------------------------------------------------------
39
+ publish-to-testpypi:
40
+ name: Publish to TestPyPI
41
+ needs: build
42
+ if: github.event_name == 'push' # The magic condition
43
+ runs-on: ubuntu-latest
44
+
45
+ environment:
46
+ name: testpypi
47
+ url: https://test.pypi.org/p/agedi
48
+
49
+ permissions:
50
+ id-token: write
51
+
52
+ steps:
53
+ - name: Download all the dists
54
+ uses: actions/download-artifact@v4
55
+ with:
56
+ name: python-package-distributions
57
+ path: dist/
58
+
59
+ - name: Publish to TestPyPI
60
+ uses: pypa/gh-action-pypi-publish@release/v1
61
+ with:
62
+ repository-url: https://test.pypi.org/legacy/
63
+
64
+ # ---------------------------------------------------------
65
+ # JOB 3: Publish to real PyPI (ONLY runs Manually)
66
+ # ---------------------------------------------------------
67
+ publish-to-pypi:
68
+ name: Publish to PyPI
69
+ needs: build
70
+ if: github.event_name == 'workflow_dispatch' # The magic condition
71
+ runs-on: ubuntu-latest
72
+
73
+ environment:
74
+ name: pypi
75
+ url: https://pypi.org/p/agedi # Replace with your package name
76
+
77
+ permissions:
78
+ id-token: write
79
+
80
+ steps:
81
+ - name: Download all the dists
82
+ uses: actions/download-artifact@v4
83
+ with:
84
+ name: python-package-distributions
85
+ path: dist/
86
+
87
+ - name: Publish to PyPI
88
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,34 @@
1
+ name: Python package
2
+
3
+ on:
4
+ push:
5
+ branches: [ "main" ]
6
+ pull_request:
7
+ branches: [ "main" ]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ jobs:
13
+ build:
14
+
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ python-version: ["3.12", "3.13"]
20
+
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+ - name: Set up Python ${{ matrix.python-version }}
24
+ uses: actions/setup-python@v3
25
+ with:
26
+ python-version: ${{ matrix.python-version }}
27
+ - name: Install dependencies
28
+ run: |
29
+ python -m pip install --upgrade pip
30
+ python -m pip install pytest
31
+ pip install -e ".[test,full]"
32
+ - name: Test with pytest
33
+ run: |
34
+ pytest
agedi-1.0.1/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ .pytest_cache
2
+ .coverage
3
+ .coverage.xml
4
+ .report.xml
5
+ docs/_build
6
+ **/__pycache__/
7
+ logs/
8
+ wandb/
9
+ .coverage-html/
10
+ src/AGeDi.egg-info/
@@ -0,0 +1,32 @@
1
+ # .readthedocs.yaml
2
+ # Read the Docs configuration file
3
+ # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
4
+
5
+ # Required
6
+ version: 2
7
+
8
+ # Set the OS, Python version and other tools you might need
9
+ build:
10
+ os: ubuntu-22.04
11
+ tools:
12
+ python: "3.11"
13
+ # You can also specify other tool versions:
14
+ # nodejs: "19"
15
+ # rust: "1.64"
16
+ # golang: "1.19"
17
+
18
+ # Build documentation in the "docs/" directory with Sphinx
19
+ sphinx:
20
+ configuration: docs/source/conf.py
21
+
22
+ # Optionally build your docs in additional formats such as PDF and ePub
23
+ # formats:
24
+ # - pdf
25
+ # - epub
26
+
27
+ # Optional but recommended, declare the Python requirements required
28
+ # to build your documentation
29
+ # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
30
+ python:
31
+ install:
32
+ - requirements: docs/requirements.txt
@@ -0,0 +1,60 @@
1
+ # Changelog
2
+
3
+ All notable changes to AGeDi will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2026-05-22
9
+
10
+ ### Added
11
+ - Predictor-corrector (Langevin corrector) sampling via `corrector_steps` /
12
+ `corrector_step_size` parameters.
13
+ - Force-field guided sampling (`ForcefieldGuidanceConfig`, `--ff_guidance` /
14
+ `--ff_zeta` CLI flags, `force_field=True` training option).
15
+ - Post-diffusion relaxation loop (auto-triggered when `ff_guidance` is enabled
16
+ and forces exceed `force_threshold`).
17
+ - `torch.compile` support for the reverse diffusion step (`compile=True` /
18
+ `--compile`), compiled per-instance to avoid cross-model interference.
19
+ - `agedi predict` CLI command and `functional.predict()` API for energy/force
20
+ inference with trained regressor heads.
21
+ - `agedi inspect` CLI command for inspecting saved model checkpoints.
22
+ - `agedi train-hydra` CLI command and `train_from_config()` API supporting a
23
+ full YAML config file (`conf/train.yaml`).
24
+ - Resume training from checkpoint (`--checkpoint` / `checkpoint:` config key).
25
+ - Separate `regressor_data_path` support in config-file training for
26
+ non-equilibrium regressor data.
27
+ - `Noiser.register()` class method for registering custom noisers.
28
+ - `register_model()` function for registering custom GNN backbone factories.
29
+ - `save_trajectory` parameter on `sample()` / `functional.sample()` (replaces
30
+ the old `save_path` parameter which has been removed).
31
+ - `print_timings` parameter for per-stage sampling timing breakdown.
32
+ - Skin-based neighbor-list caching in `update_graph()` to skip full rebuilds
33
+ when atoms have moved less than the skin distance.
34
+ - `canonical_cell` option in `from_atoms()` / CLI / config to store cells in
35
+ canonical lower-triangular form.
36
+ - `n_classes` option to explicitly set the number of atom-type classes for the
37
+ `Types` noiser.
38
+ - `repeat` / `repeat_epoch` cell-repeat data augmentation.
39
+ - `batch_naive_neighbor_list` pure-PyTorch fallback neighbor-list (used in the
40
+ compiled path when `nvalchemiops` is not available).
41
+
42
+ ### Changed
43
+ - **Breaking**: `save_path` parameter removed from `Diffusion.sample()`,
44
+ `Diffusion._sample()`, and `functional.sample()`. Use `save_trajectory`
45
+ instead.
46
+ - `nvalchemiops` is now an **optional** dependency (`pip install agedi[cuda]`).
47
+ The non-compiled sampling path works without it.
48
+ - `Agedi.__init__` `optim_config` and `scheduler_config` default to `None`
49
+ (computed internally) rather than shared mutable dicts.
50
+ - `AtomsGraph.from_atoms` cell-canonicalization now emits `warnings.warn`
51
+ instead of `print`.
52
+ - Compiled reverse step is now a lazy per-instance property instead of a
53
+ class-level `@torch.compile` decorator.
54
+ - CI matrix extended to macOS runners; `.[test,full]` installed in one step.
55
+
56
+ ### Fixed
57
+ - Python version badge corrected to `3.12+`.
58
+ - `AtomsGraph` class docstring typo corrected.
59
+ - `from_atoms` `canonical_cell` parameter docstring corrected (default is
60
+ `False`, not `True`).
@@ -0,0 +1,58 @@
1
+ # Contributing to AGeDi
2
+
3
+ Thank you for your interest in contributing to AGeDi! This document describes
4
+ how to set up a development environment and the conventions we follow.
5
+
6
+ ## Setting up the development environment
7
+
8
+ ```bash
9
+ git clone https://github.com/nronne/agedi.git
10
+ cd agedi
11
+ pip install -e ".[test,full]"
12
+ ```
13
+
14
+ The `full` extra installs SchNetPack and the NVIDIA nvalchemi-toolkit-ops package.
15
+ A plain `pip install -e .` omits these for a lightweight install.
16
+
17
+ ## Running the tests
18
+
19
+ ```bash
20
+ pytest
21
+ ```
22
+
23
+ ## Code style
24
+
25
+ We use [Ruff](https://docs.astral.sh/ruff/) for linting and formatting (line
26
+ length 88). Before opening a pull request please run:
27
+
28
+ ```bash
29
+ ruff check src/
30
+ ruff format src/
31
+ ```
32
+
33
+ ## Docstrings
34
+
35
+ Use [NumPy-style docstrings](https://numpydoc.readthedocs.io/en/latest/format.html)
36
+ for all public classes and functions.
37
+
38
+ ## Opening a pull request
39
+
40
+ 1. Fork the repository and create a feature branch from `main`.
41
+ 2. Add tests for any new functionality.
42
+ 3. Run the full test suite (`pytest`) and ensure it passes.
43
+ 4. Update `CHANGELOG.md` under the `[Unreleased]` section.
44
+ 5. Open a pull request against `main` with a clear description of the change.
45
+
46
+ ## Reporting bugs
47
+
48
+ Please open an issue using the **Bug report** template and include:
49
+
50
+ - AGeDi version (`python -c "import agedi; print(agedi.__version__)"`)
51
+ - Python version and operating system
52
+ - Minimal reproducible example
53
+ - Full traceback
54
+
55
+ ## Feature requests
56
+
57
+ Open an issue using the **Feature request** template. Describe the use-case
58
+ and, if possible, a sketch of the proposed API.