PythiaLabelGenerator 1.1.1__tar.gz → 1.2.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 (71) hide show
  1. pythialabelgenerator-1.2.0/.gitattributes +1 -0
  2. pythialabelgenerator-1.2.0/.github/workflows/publish-pypi.yml +63 -0
  3. pythialabelgenerator-1.2.0/.github/workflows/test-label-generator.yml +89 -0
  4. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/.gitignore +3 -0
  5. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/.pre-commit-config.yaml +2 -2
  6. pythialabelgenerator-1.1.1/README.md → pythialabelgenerator-1.2.0/PKG-INFO +70 -6
  7. pythialabelgenerator-1.1.1/PKG-INFO → pythialabelgenerator-1.2.0/README.md +50 -26
  8. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/labelgenerator/iqtree.py +1 -2
  9. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/labelgenerator/label.py +6 -7
  10. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/labelgenerator/logger.py +2 -1
  11. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/labelgenerator/main.py +6 -6
  12. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/labelgenerator/raxmlng.py +9 -3
  13. pythialabelgenerator-1.2.0/pixi.toml +55 -0
  14. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/pyproject.toml +12 -31
  15. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/conftest.py +14 -3
  16. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/test_label.py +25 -12
  17. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/test_main.py +21 -10
  18. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/test_raxmlng.py +38 -4
  19. pythialabelgenerator-1.1.1/.github/actions/setup-iqtree/action.yml +0 -22
  20. pythialabelgenerator-1.1.1/.github/actions/setup-raxmlng/action.yml +0 -20
  21. pythialabelgenerator-1.1.1/.github/actions/test-label-cli/action.yml +0 -12
  22. pythialabelgenerator-1.1.1/.github/workflows/test-label-generator.yml +0 -72
  23. pythialabelgenerator-1.1.1/etc/environment.yml +0 -9
  24. pythialabelgenerator-1.1.1/tests/test_config.py +0 -2
  25. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/LICENSE +0 -0
  26. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/__init__.py +0 -0
  27. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/examples/example.phy +0 -0
  28. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/labelgenerator/__init__.py +0 -0
  29. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/labelgenerator/iqtree_parser.py +0 -0
  30. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/setup.py +0 -0
  31. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/__init__.py +0 -0
  32. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/AA.phy +0 -0
  33. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/DNA.phy +0 -0
  34. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/MORPH.phy +0 -0
  35. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/logs/AA.iqtree.iqtree +0 -0
  36. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/logs/AA.iqtree.log +0 -0
  37. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/logs/DNA.iqtree.iqtree +0 -0
  38. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/logs/DNA.iqtree.log +0 -0
  39. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/logs/DNA.raxml.log +0 -0
  40. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/logs/MORPH.iqtree.iqtree +0 -0
  41. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/logs/MORPH.iqtree.log +0 -0
  42. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/logs/test.raxml.bestModel +0 -0
  43. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/logs/test.raxml.bestTree +0 -0
  44. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/logs/test.raxml.log +0 -0
  45. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/logs/test.raxml.mlTrees +0 -0
  46. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/logs/test.raxml.rba +0 -0
  47. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/logs/test.raxml.startTree +0 -0
  48. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/logs/test.rfdist.raxml.log +0 -0
  49. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/logs/test.rfdist.raxml.rfDistances +0 -0
  50. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/AA.raxml.bestModel +0 -0
  51. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/AA.raxml.bestTree +0 -0
  52. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/AA.raxml.log +0 -0
  53. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/AA.raxml.mlTrees +0 -0
  54. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/AA.raxml.rba +0 -0
  55. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/AA.raxml.startTree +0 -0
  56. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/DNA.raxml.bestModel +0 -0
  57. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/DNA.raxml.bestTree +0 -0
  58. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/DNA.raxml.bestTreeCollapsed +0 -0
  59. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/DNA.raxml.log +0 -0
  60. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/DNA.raxml.mlTrees +0 -0
  61. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/DNA.raxml.rba +0 -0
  62. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/DNA.raxml.startTree +0 -0
  63. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/MORPH.raxml.bestModel +0 -0
  64. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/MORPH.raxml.bestTree +0 -0
  65. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/MORPH.raxml.bestTreeCollapsed +0 -0
  66. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/MORPH.raxml.log +0 -0
  67. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/MORPH.raxml.mlTrees +0 -0
  68. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/MORPH.raxml.rba +0 -0
  69. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/data/mltrees/MORPH.raxml.startTree +0 -0
  70. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/test_iqtree.py +0 -0
  71. {pythialabelgenerator-1.1.1 → pythialabelgenerator-1.2.0}/tests/test_iqtree_parser.py +0 -0
@@ -0,0 +1 @@
1
+ pixi.lock linguist-generated=true
@@ -0,0 +1,63 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ concurrency:
11
+ group: pypi-${{ github.event.release.tag_name }}
12
+ cancel-in-progress: false
13
+
14
+ jobs:
15
+ validate-release:
16
+ name: Validate release version
17
+ if: github.event_name == 'release' && github.event.action == 'published' && !github.event.release.draft && !github.event.release.prerelease
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - name: Check out released commit
21
+ uses: actions/checkout@v7
22
+ - name: Set up Python
23
+ uses: actions/setup-python@v7
24
+ with:
25
+ python-version: '3.14'
26
+ - name: Check tag matches package version
27
+ env:
28
+ RELEASE_TAG: ${{ github.event.release.tag_name }}
29
+ run: |
30
+ python - <<'PY'
31
+ import os
32
+ import pathlib
33
+ import tomllib
34
+
35
+ version = tomllib.loads(pathlib.Path("pyproject.toml").read_text())["project"]["version"]
36
+ tag = os.environ["RELEASE_TAG"]
37
+ if tag != version:
38
+ raise SystemExit(f"Release tag {tag!r} must match package version {version!r}")
39
+ print(f"Validated release {version}")
40
+ PY
41
+
42
+ test-and-build:
43
+ name: Test and build release
44
+ needs: validate-release
45
+ uses: ./.github/workflows/test-label-generator.yml
46
+
47
+ publish:
48
+ name: Upload distributions to PyPI
49
+ needs: test-and-build
50
+ runs-on: ubuntu-latest
51
+ environment:
52
+ name: pypi
53
+ url: https://pypi.org/project/PythiaLabelGenerator/
54
+ permissions:
55
+ id-token: write
56
+ steps:
57
+ - name: Download tested distributions
58
+ uses: actions/download-artifact@v8
59
+ with:
60
+ name: python-distributions
61
+ path: dist/
62
+ - name: Publish distributions
63
+ uses: pypa/gh-action-pypi-publish@v1.14.2
@@ -0,0 +1,89 @@
1
+ name: Build and test LabelGenerator
2
+ run-name: Build and test the LabelGenerator Python library
3
+
4
+ on:
5
+ pull_request:
6
+ push:
7
+ branches:
8
+ - main
9
+ workflow_dispatch:
10
+ workflow_call:
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ jobs:
16
+ pixi-tests:
17
+ name: Pixi tests (${{ matrix.os }}, ${{ matrix.environment }})
18
+ runs-on: ${{ matrix.os }}
19
+ strategy:
20
+ fail-fast: false
21
+ matrix:
22
+ os: [ubuntu-latest, macos-latest]
23
+ environment: [py311, py314, legacy-raxml]
24
+ steps:
25
+ - name: Check out repository code
26
+ uses: actions/checkout@v7
27
+ - name: Set up Pixi
28
+ uses: prefix-dev/setup-pixi@v0.10.2
29
+ with:
30
+ pixi-version: v0.77.0
31
+ environments: ${{ matrix.environment }}
32
+ frozen: true
33
+ cache: true
34
+ cache-write: ${{ github.event_name == 'push' && github.ref_name == 'main' }}
35
+ - name: Check the lock file
36
+ run: pixi lock --check
37
+ - name: Check RAxML-NG and IQ-TREE
38
+ run: pixi run --frozen --environment ${{ matrix.environment }} binary-smoke
39
+ - name: Run the test suite
40
+ run: pixi run --frozen --environment ${{ matrix.environment }} test
41
+ - name: Check the CLI
42
+ run: pixi run --frozen --environment ${{ matrix.environment }} cli-smoke
43
+
44
+ package-smoke:
45
+ name: Python package smoke test (${{ matrix.os }})
46
+ runs-on: ${{ matrix.os }}
47
+ strategy:
48
+ fail-fast: false
49
+ matrix:
50
+ os: [ubuntu-latest, macos-latest]
51
+ steps:
52
+ - name: Check out repository code
53
+ uses: actions/checkout@v7
54
+ - name: Set up Pixi
55
+ uses: prefix-dev/setup-pixi@v0.10.2
56
+ with:
57
+ pixi-version: v0.77.0
58
+ environments: build
59
+ frozen: true
60
+ cache: true
61
+ - name: Check the lock file
62
+ run: pixi lock --check
63
+ - name: Build and verify distributions
64
+ run: pixi run --frozen package-smoke
65
+ - name: Check distribution filenames
66
+ run: |
67
+ pixi run --frozen --environment build python - <<'PY'
68
+ import pathlib
69
+ import tomllib
70
+
71
+ version = tomllib.loads(pathlib.Path("pyproject.toml").read_text())["project"]["version"]
72
+ expected = {
73
+ f"pythialabelgenerator-{version}-py3-none-any.whl",
74
+ f"pythialabelgenerator-{version}.tar.gz",
75
+ }
76
+ actual = {path.name for path in pathlib.Path("dist").iterdir()}
77
+ if actual != expected:
78
+ raise SystemExit(f"Expected distributions {sorted(expected)}, found {sorted(actual)}")
79
+ PY
80
+ - name: Upload tested distributions
81
+ if: matrix.os == 'ubuntu-latest'
82
+ uses: actions/upload-artifact@v7
83
+ with:
84
+ name: python-distributions
85
+ path: |
86
+ dist/*.whl
87
+ dist/*.tar.gz
88
+ if-no-files-found: error
89
+ overwrite: true
@@ -2,6 +2,9 @@
2
2
  **/*.log
3
3
  **/*.csv
4
4
 
5
+ # Pixi environments
6
+ .pixi/
7
+
5
8
  *.raxml.*
6
9
  !tests/**/*.raxml.*
7
10
 
@@ -1,13 +1,13 @@
1
1
  repos:
2
2
  - repo: https://github.com/pre-commit/pre-commit-hooks
3
- rev: v2.3.0
3
+ rev: v6.0.0
4
4
  hooks:
5
5
  - id: check-yaml
6
6
  - id: end-of-file-fixer
7
7
  - id: trailing-whitespace
8
8
  - id: detect-private-key
9
9
  - repo: https://github.com/astral-sh/ruff-pre-commit
10
- rev: v0.9.7
10
+ rev: v0.16.6
11
11
  hooks:
12
12
  # Run the linter.
13
13
  - id: ruff
@@ -1,3 +1,23 @@
1
+ Metadata-Version: 2.5
2
+ Name: PythiaLabelGenerator
3
+ Version: 1.2.0
4
+ Summary: Command line tool to generate the ground-truth phylogenetic difficulty of MSAs
5
+ Project-URL: Homepage, https://github.com/tschuelia/PythiaLabelGenerator
6
+ Author-email: Julia Haag <info@juliaschmid.com>
7
+ License-Expression: GPL-3.0-or-later
8
+ License-File: LICENSE
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Python :: 3.14
13
+ Requires-Python: <3.15,>=3.11
14
+ Requires-Dist: loguru
15
+ Requires-Dist: pythiaphylopredictor>=2.1.0
16
+ Requires-Dist: regex
17
+ Provides-Extra: test
18
+ Requires-Dist: pytest; extra == 'test'
19
+ Description-Content-Type: text/markdown
20
+
1
21
  # Pythia Difficulty Label Generator (PyDLG)
2
22
 
3
23
  ![Label Generator GH actions CI](https://github.com/tschuelia/PythiaLabelGenerator/actions/workflows/test-label-generator.yml/badge.svg)
@@ -39,6 +59,18 @@ Per default, the difficulty is based on $`N_{\text{all}}=100`$ ML trees.
39
59
  Note that this number can be adjusted by the user, however, the difficulty will only be an approximation if the number
40
60
  of trees is changed.
41
61
 
62
+ ## RAxML-NG 2 Compatibility
63
+
64
+ When using RAxML-NG 2, PyDLG automatically passes the following flags to preserve the label-generation procedure
65
+ used in our publications:
66
+
67
+ - `--adaptive off` disables adaptive search and its early-stopping rule. This ensures that tree searches are not
68
+ cut short based on estimated difficulty and that label computation follows our published difficulty definition.
69
+ - `--extra brlen-start-fixed` restores the initial branch-length behavior of RAxML-NG 1.2, so labels are computed
70
+ using the same initialization as in our publications.
71
+
72
+ These flags are applied automatically; no additional `label` arguments are required.
73
+
42
74
  ## Prediction of Phylogenetic Difficulty
43
75
 
44
76
  As stated above, computing the ground-truth difficulty for an MSA is very time-consuming and requires a lot of
@@ -62,7 +94,7 @@ biological morphological data, Pythia should work just fine 😉
62
94
  To use PyDLG, you need to install
63
95
 
64
96
  - RAxML-NG: See [the RAxML-NG GitHub repository](https://github.com/amkozlov/raxml-ng) for installation instructions.
65
- Please make sure that you install a RAxML-NG version < 2.
97
+ PyDLG supports both RAxML-NG 1.x and 2.x.
66
98
  - IQ-TREE: See [the IQ-TREE website](http://www.iqtree.org) for installation instructions. Please install IQ-TREE
67
99
  version 2 or higher.
68
100
 
@@ -82,6 +114,38 @@ You can install the package using pip:
82
114
  pip install pythialabelgenerator
83
115
  ```
84
116
 
117
+ This installs the Python package but not RAxML-NG or IQ-TREE. Install both programs separately as described in
118
+ [Requirements](#requirements).
119
+
120
+ #### Develop using Pixi
121
+
122
+ Pixi is the supported way to create a development environment containing the Python package and both phylogenetic
123
+ binaries:
124
+
125
+ ```bash
126
+ git clone https://github.com/tschuelia/PythiaLabelGenerator.git
127
+ cd PythiaLabelGenerator
128
+ pixi install --frozen
129
+ pixi run binary-smoke
130
+ pixi run cli-smoke
131
+ pixi run test
132
+ ```
133
+
134
+ Unlike released-package installations, these project-local Pixi environments install the tested binaries from
135
+ Bioconda. The default environment contains RAxML-NG 2.0.2 and IQ-TREE 2.4.0, while `legacy-raxml` contains RAxML-NG
136
+ 1.2.2. PyPythia 2.1.0 or newer is installed from conda-forge.
137
+
138
+ The default environment uses Python 3.14 and RAxML-NG 2.0.2. Use `pixi run --environment py311 ...` or
139
+ `pixi run --environment py314 ...` to reproduce the minimum and maximum Python versions tested in CI, or
140
+ `pixi run --environment legacy-raxml ...` to test with RAxML-NG 1.2.2. PyDLG supports Python 3.11 through Python 3.14.
141
+
142
+ Install the pre-commit hooks once and run all checks on demand using the dedicated environment:
143
+
144
+ ```bash
145
+ pixi run --environment pre-commit pre-commit-install
146
+ pixi run --environment pre-commit pre-commit-run
147
+ ```
148
+
85
149
  ## Usage
86
150
 
87
151
  PyDLG is primarily a command line tool. You can call it using the `label` command, for instance, to
@@ -96,9 +160,9 @@ to the console.
96
160
  The output will look something like this:
97
161
 
98
162
  ```text
99
- PyDLG version 1.0.1 released by The Exelixis Lab
163
+ PyDLG version 1.2.0 released by The Exelixis Lab
100
164
  Developed by: Julia Haag
101
- Latest version: https://github.com/tschuelia/LabelGenerator
165
+ Latest version: https://github.com/tschuelia/PythiaLabelGenerator
102
166
  Questions/problems/suggestions? Please open an issue on GitHub.
103
167
 
104
168
  LabelGenerator was called at 06-Mar-2025 15:15:03 as follows:
@@ -126,14 +190,14 @@ Depending on your system setup, you might need to pass a RAxML-NG and IQ-TREE bi
126
190
  You can do this using the `-r` and `-i` options, respectively. This is required in case `raxml-ng` and/or `iqtree2` are
127
191
  not in your `$PATH`.
128
192
 
129
- Note that this `examply.phy` MSA is not the same exemplary MSA as we provide in the PyPythia repository, so please don't compare this ground-truth lable to the exemplary prediction in PyPythia 😉
193
+ Note that this `example.phy` MSA is not the same exemplary MSA as we provide in the PyPythia repository, so please don't compare this ground-truth label to the exemplary prediction in PyPythia 😉
130
194
 
131
195
  For a full list of command line options, run `label -h`:
132
196
 
133
197
  ```text
134
- PyDLG version 1.0.1 released by The Exelixis Lab
198
+ PyDLG version 1.2.0 released by The Exelixis Lab
135
199
  Developed by: Julia Haag
136
- Latest version: https://github.com/tschuelia/LabelGenerator
200
+ Latest version: https://github.com/tschuelia/PythiaLabelGenerator
137
201
  Questions/problems/suggestions? Please open an issue on GitHub.
138
202
 
139
203
  usage: label [-h] -m MSA -r RAXMLNG -i IQTREE [-t THREADS] [-s SEED] [-p PREFIX] [--model MODEL] [--ntrees NTREES] [--redo] [-V]
@@ -1,23 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: PythiaLabelGenerator
3
- Version: 1.1.1
4
- Summary: Command line tool to generate the ground-truth phylogenetic difficulty of MSAs
5
- Project-URL: Homepage, https://github.com/tschuelia/PythiaLabelGenerator
6
- Author-email: Julia Haag <info@juliaschmid.com>
7
- License-Expression: GPL-3.0-or-later
8
- License-File: LICENSE
9
- Classifier: Programming Language :: Python :: 3.9
10
- Classifier: Programming Language :: Python :: 3.10
11
- Classifier: Programming Language :: Python :: 3.11
12
- Classifier: Programming Language :: Python :: 3.12
13
- Requires-Python: <3.13,>=3.9
14
- Requires-Dist: loguru
15
- Requires-Dist: pythiaphylopredictor>=2.0.0
16
- Requires-Dist: regex
17
- Provides-Extra: test
18
- Requires-Dist: pytest; extra == 'test'
19
- Description-Content-Type: text/markdown
20
-
21
1
  # Pythia Difficulty Label Generator (PyDLG)
22
2
 
23
3
  ![Label Generator GH actions CI](https://github.com/tschuelia/PythiaLabelGenerator/actions/workflows/test-label-generator.yml/badge.svg)
@@ -59,6 +39,18 @@ Per default, the difficulty is based on $`N_{\text{all}}=100`$ ML trees.
59
39
  Note that this number can be adjusted by the user, however, the difficulty will only be an approximation if the number
60
40
  of trees is changed.
61
41
 
42
+ ## RAxML-NG 2 Compatibility
43
+
44
+ When using RAxML-NG 2, PyDLG automatically passes the following flags to preserve the label-generation procedure
45
+ used in our publications:
46
+
47
+ - `--adaptive off` disables adaptive search and its early-stopping rule. This ensures that tree searches are not
48
+ cut short based on estimated difficulty and that label computation follows our published difficulty definition.
49
+ - `--extra brlen-start-fixed` restores the initial branch-length behavior of RAxML-NG 1.2, so labels are computed
50
+ using the same initialization as in our publications.
51
+
52
+ These flags are applied automatically; no additional `label` arguments are required.
53
+
62
54
  ## Prediction of Phylogenetic Difficulty
63
55
 
64
56
  As stated above, computing the ground-truth difficulty for an MSA is very time-consuming and requires a lot of
@@ -82,7 +74,7 @@ biological morphological data, Pythia should work just fine 😉
82
74
  To use PyDLG, you need to install
83
75
 
84
76
  - RAxML-NG: See [the RAxML-NG GitHub repository](https://github.com/amkozlov/raxml-ng) for installation instructions.
85
- Please make sure that you install a RAxML-NG version < 2.
77
+ PyDLG supports both RAxML-NG 1.x and 2.x.
86
78
  - IQ-TREE: See [the IQ-TREE website](http://www.iqtree.org) for installation instructions. Please install IQ-TREE
87
79
  version 2 or higher.
88
80
 
@@ -102,6 +94,38 @@ You can install the package using pip:
102
94
  pip install pythialabelgenerator
103
95
  ```
104
96
 
97
+ This installs the Python package but not RAxML-NG or IQ-TREE. Install both programs separately as described in
98
+ [Requirements](#requirements).
99
+
100
+ #### Develop using Pixi
101
+
102
+ Pixi is the supported way to create a development environment containing the Python package and both phylogenetic
103
+ binaries:
104
+
105
+ ```bash
106
+ git clone https://github.com/tschuelia/PythiaLabelGenerator.git
107
+ cd PythiaLabelGenerator
108
+ pixi install --frozen
109
+ pixi run binary-smoke
110
+ pixi run cli-smoke
111
+ pixi run test
112
+ ```
113
+
114
+ Unlike released-package installations, these project-local Pixi environments install the tested binaries from
115
+ Bioconda. The default environment contains RAxML-NG 2.0.2 and IQ-TREE 2.4.0, while `legacy-raxml` contains RAxML-NG
116
+ 1.2.2. PyPythia 2.1.0 or newer is installed from conda-forge.
117
+
118
+ The default environment uses Python 3.14 and RAxML-NG 2.0.2. Use `pixi run --environment py311 ...` or
119
+ `pixi run --environment py314 ...` to reproduce the minimum and maximum Python versions tested in CI, or
120
+ `pixi run --environment legacy-raxml ...` to test with RAxML-NG 1.2.2. PyDLG supports Python 3.11 through Python 3.14.
121
+
122
+ Install the pre-commit hooks once and run all checks on demand using the dedicated environment:
123
+
124
+ ```bash
125
+ pixi run --environment pre-commit pre-commit-install
126
+ pixi run --environment pre-commit pre-commit-run
127
+ ```
128
+
105
129
  ## Usage
106
130
 
107
131
  PyDLG is primarily a command line tool. You can call it using the `label` command, for instance, to
@@ -116,9 +140,9 @@ to the console.
116
140
  The output will look something like this:
117
141
 
118
142
  ```text
119
- PyDLG version 1.0.1 released by The Exelixis Lab
143
+ PyDLG version 1.2.0 released by The Exelixis Lab
120
144
  Developed by: Julia Haag
121
- Latest version: https://github.com/tschuelia/LabelGenerator
145
+ Latest version: https://github.com/tschuelia/PythiaLabelGenerator
122
146
  Questions/problems/suggestions? Please open an issue on GitHub.
123
147
 
124
148
  LabelGenerator was called at 06-Mar-2025 15:15:03 as follows:
@@ -146,14 +170,14 @@ Depending on your system setup, you might need to pass a RAxML-NG and IQ-TREE bi
146
170
  You can do this using the `-r` and `-i` options, respectively. This is required in case `raxml-ng` and/or `iqtree2` are
147
171
  not in your `$PATH`.
148
172
 
149
- Note that this `examply.phy` MSA is not the same exemplary MSA as we provide in the PyPythia repository, so please don't compare this ground-truth lable to the exemplary prediction in PyPythia 😉
173
+ Note that this `example.phy` MSA is not the same exemplary MSA as we provide in the PyPythia repository, so please don't compare this ground-truth label to the exemplary prediction in PyPythia 😉
150
174
 
151
175
  For a full list of command line options, run `label -h`:
152
176
 
153
177
  ```text
154
- PyDLG version 1.0.1 released by The Exelixis Lab
178
+ PyDLG version 1.2.0 released by The Exelixis Lab
155
179
  Developed by: Julia Haag
156
- Latest version: https://github.com/tschuelia/LabelGenerator
180
+ Latest version: https://github.com/tschuelia/PythiaLabelGenerator
157
181
  Questions/problems/suggestions? Please open an issue on GitHub.
158
182
 
159
183
  usage: label [-h] -m MSA -r RAXMLNG -i IQTREE [-t THREADS] [-s SEED] [-p PREFIX] [--model MODEL] [--ntrees NTREES] [--redo] [-V]
@@ -1,6 +1,5 @@
1
1
  import pathlib
2
2
  import subprocess
3
- from typing import Optional
4
3
 
5
4
  from pypythia.custom_types import DataType
6
5
 
@@ -49,7 +48,7 @@ def run_statstests(
49
48
  model: str,
50
49
  prefix: pathlib.Path,
51
50
  seed: int = 0,
52
- threads: Optional[int] = None,
51
+ threads: int | None = None,
53
52
  is_morph: bool = False,
54
53
  redo: bool = False,
55
54
  ) -> None:
@@ -1,7 +1,6 @@
1
1
  import pathlib
2
- from typing import Optional
3
2
 
4
- from pypythia.msa import DataType, MSA
3
+ from pypythia.msa import MSA, DataType
5
4
 
6
5
  from labelgenerator.iqtree import (
7
6
  filter_plausible_trees,
@@ -92,9 +91,9 @@ def get_label(
92
91
  label = total / 5
93
92
 
94
93
  eps = 1e-9
95
- assert (
96
- -eps <= label <= 1 + eps
97
- ), f"Label {label} is not between 0 and 1. Check the input values."
94
+ assert -eps <= label <= 1 + eps, (
95
+ f"Label {label} is not between 0 and 1. Check the input values."
96
+ )
98
97
 
99
98
  return label
100
99
 
@@ -105,10 +104,10 @@ def compute_label(
105
104
  raxmlng: pathlib.Path,
106
105
  iqtree: pathlib.Path,
107
106
  prefix: pathlib.Path,
108
- model: Optional[str] = None,
107
+ model: str | None = None,
109
108
  n_trees: int = 100,
110
109
  seed: int = 0,
111
- threads: Optional[int] = None,
110
+ threads: int | None = None,
112
111
  redo: bool = False,
113
112
  log_info: bool = True,
114
113
  ) -> float:
@@ -3,6 +3,7 @@ import textwrap
3
3
  import time
4
4
 
5
5
  import loguru
6
+
6
7
  from labelgenerator import __version__
7
8
 
8
9
  SCRIPT_START = time.perf_counter()
@@ -17,7 +18,7 @@ def get_header():
17
18
  return textwrap.dedent(
18
19
  f"PyDLG version {__version__} released by The Exelixis Lab\n"
19
20
  f"Developed by: Julia Haag\n"
20
- f"Latest version: https://github.com/tschuelia/LabelGenerator\n"
21
+ f"Latest version: https://github.com/tschuelia/PythiaLabelGenerator\n"
21
22
  f"Questions/problems/suggestions? Please open an issue on GitHub.\n",
22
23
  )
23
24
 
@@ -3,7 +3,10 @@ import pathlib
3
3
  import shutil
4
4
  import sys
5
5
  import time
6
- from typing import Optional
6
+
7
+ from pypythia.msa import parse_msa
8
+ from pypythia.prediction import collect_features
9
+ from pypythia.raxmlng import RAxMLNG
7
10
 
8
11
  from labelgenerator import __version__
9
12
  from labelgenerator.label import compute_label
@@ -14,9 +17,6 @@ from labelgenerator.logger import (
14
17
  log_runtime_information,
15
18
  logger,
16
19
  )
17
- from pypythia.msa import parse_msa
18
- from pypythia.prediction import collect_features
19
- from pypythia.raxmlng import RAxMLNG
20
20
 
21
21
  DEFAULT_RAXMLNG_EXE = (
22
22
  pathlib.Path(shutil.which("raxml-ng")) if shutil.which("raxml-ng") else None
@@ -27,7 +27,7 @@ DEFAULT_IQTREE_EXE = (
27
27
  )
28
28
 
29
29
 
30
- def _parse_cli(arg_list: Optional[list[str]] = None):
30
+ def _parse_cli(arg_list: list[str] | None = None):
31
31
  parser = argparse.ArgumentParser(
32
32
  description="Generate the ground truth difficulty for the given MSA."
33
33
  )
@@ -118,7 +118,7 @@ def _parse_cli(arg_list: Optional[list[str]] = None):
118
118
  return parser.parse_args(arg_list)
119
119
 
120
120
 
121
- def main(arg_list: Optional[list[str]] = None):
121
+ def main(arg_list: list[str] | None = None):
122
122
  logger.info(get_header())
123
123
  args = _parse_cli(arg_list)
124
124
 
@@ -1,6 +1,5 @@
1
1
  import math
2
2
  import pathlib
3
- from typing import Optional
4
3
 
5
4
  from pypythia.raxmlng import RAxMLNG, get_raxmlng_rfdist_results, run_raxmlng_command
6
5
 
@@ -38,7 +37,7 @@ def infer_ml_trees(
38
37
  prefix: pathlib.Path,
39
38
  n_trees: int = 100,
40
39
  seed: int = 0,
41
- threads: Optional[int] = None,
40
+ threads: int | None = None,
42
41
  redo: bool = False,
43
42
  ) -> None:
44
43
  """
@@ -74,6 +73,8 @@ def infer_ml_trees(
74
73
  if not redo and _inference_results_exist_and_correct(prefix, n_trees):
75
74
  return
76
75
 
76
+ raxmlng_major_version = RAxMLNG(raxmlng)._major_version
77
+
77
78
  n_pars_trees = math.ceil(n_trees / 2)
78
79
  n_rand_trees = n_trees - n_pars_trees
79
80
  rand_string = f",rand{{{n_rand_trees}}}" if n_rand_trees > 0 else ""
@@ -95,6 +96,11 @@ def infer_ml_trees(
95
96
  if threads is not None:
96
97
  cmd.extend(["--threads", threads])
97
98
 
99
+ if raxmlng_major_version >= 2:
100
+ # Preserve the v1.2 search and fixed parsimony starting branch lengths.
101
+ # Disabling adaptive search alone leaves v2's new initialization enabled.
102
+ cmd.extend(["--adaptive", "off", "--extra", "brlen-start-fixed"])
103
+
98
104
  if redo:
99
105
  cmd.append("--redo")
100
106
 
@@ -130,7 +136,7 @@ def rf_distance(
130
136
  ml_trees: pathlib.Path,
131
137
  prefix: pathlib.Path,
132
138
  raxmlng: pathlib.Path,
133
- n_trees: Optional[int] = None,
139
+ n_trees: int | None = None,
134
140
  redo: bool = False,
135
141
  ) -> tuple[int, float]:
136
142
  """
@@ -0,0 +1,55 @@
1
+ [workspace]
2
+ channels = ["conda-forge", "bioconda"]
3
+ platforms = ["linux-64", "osx-64", "osx-arm64"]
4
+ requires-pixi = ">=0.76.1"
5
+
6
+ [dependencies]
7
+ pythiaphylopredictor = ">=2.1.0"
8
+ regex = "*"
9
+ loguru = "*"
10
+ iqtree = "==2.4.0"
11
+
12
+ [pypi-dependencies]
13
+ PythiaLabelGenerator = { path = ".", editable = true }
14
+
15
+ [feature.py311.dependencies]
16
+ python = "3.11.*"
17
+
18
+ [feature.py314.dependencies]
19
+ python = "3.14.*"
20
+
21
+ [feature.test.dependencies]
22
+ pytest = "*"
23
+
24
+ [feature.raxml1.dependencies]
25
+ raxml-ng = "==1.2.2"
26
+
27
+ [feature.raxml2.dependencies]
28
+ raxml-ng = "==2.0.2"
29
+
30
+ [feature.pre-commit.dependencies]
31
+ pre-commit = "*"
32
+
33
+ [feature.pre-commit.tasks]
34
+ pre-commit-install = "pre-commit install"
35
+ pre-commit-run = "pre-commit run --all-files"
36
+
37
+ [feature.build.dependencies]
38
+ hatchling = "*"
39
+ pip = "*"
40
+ python-build = "*"
41
+
42
+ [environments]
43
+ default = { features = ["py314", "raxml2", "test"] }
44
+ py311 = { features = ["py311", "raxml2", "test"] }
45
+ py314 = { features = ["py314", "raxml2", "test"] }
46
+ legacy-raxml = { features = ["py311", "raxml1", "test"] }
47
+ build = { features = ["py314", "build"] }
48
+ pre-commit = { features = ["pre-commit"], no-default-feature = true }
49
+
50
+ [tasks]
51
+ test = "pytest -svx --color=yes"
52
+ binary-smoke = "raxml-ng -v && iqtree2 -v"
53
+ cli-smoke = "label --help"
54
+ build = { cmd = "python -m build", default-environment = "build" }
55
+ package-smoke = { cmd = "python -m pip install --force-reinstall --no-deps dist/*.whl && python -m pip check && python -c 'import labelgenerator' && label --help", depends-on = ["build"], default-environment = "build" }
@@ -3,18 +3,18 @@ name = "PythiaLabelGenerator"
3
3
  description = "Command line tool to generate the ground-truth phylogenetic difficulty of MSAs"
4
4
  readme = {file = "README.md", content-type = "text/markdown"}
5
5
  authors = [{name = "Julia Haag", email = "info@juliaschmid.com"}]
6
- version = "1.1.1"
6
+ version = "1.2.0"
7
7
  license = "GPL-3.0-or-later"
8
8
  classifiers = [
9
- "Programming Language :: Python :: 3.9",
10
- "Programming Language :: Python :: 3.10",
11
9
  "Programming Language :: Python :: 3.11",
12
- "Programming Language :: Python :: 3.12"
10
+ "Programming Language :: Python :: 3.12",
11
+ "Programming Language :: Python :: 3.13",
12
+ "Programming Language :: Python :: 3.14"
13
13
  ]
14
- requires-python = ">= 3.9, < 3.13"
14
+ requires-python = ">=3.11,<3.15"
15
15
 
16
16
  dependencies = [
17
- "pythiaphylopredictor>=2.0.0",
17
+ "pythiaphylopredictor>=2.1.0",
18
18
  "regex",
19
19
  "loguru"
20
20
  ]
@@ -34,34 +34,15 @@ label = "labelgenerator.main:main"
34
34
  requires = ["hatchling"]
35
35
  build-backend = "hatchling.build"
36
36
 
37
- [tool.black]
38
- exclude = '''
39
- /(
40
- \.eggs
41
- | \.git
42
- | \.venv
43
- | build
44
- | dist
45
- )/
46
- '''
47
-
48
- [tool.isort]
49
- multi_line_output = 3
50
- include_trailing_comma = true
51
- ensure_newline_before_comments = true
52
- line_length = 88
53
- known_first_party = "labelgenerator"
54
- skip_glob = '\.eggs/*,\.git/*,\.venv/*,build/*,dist/*'
55
- default_section = 'THIRDPARTY'
56
-
57
- [tool.mypy]
58
- python_version = 3.8
59
- ignore_missing_imports = true
60
- no_implicit_optional = true
61
- check_untyped_defs = true
37
+ [tool.ruff.lint]
38
+ select = ["F", "I", "UP"]
39
+ ignore = ["E501"]
62
40
 
63
41
  [tool.pytest.ini_options]
64
42
  addopts = "--import-mode=importlib"
65
43
 
66
44
  [tool.hatch.build.targets.wheel]
67
45
  packages = ["labelgenerator"]
46
+
47
+ [tool.hatch.build.targets.sdist]
48
+ exclude = ["/pixi.lock"]
@@ -1,18 +1,29 @@
1
+ import os
1
2
  import pathlib
3
+ import shutil
2
4
 
3
5
  import pytest
4
6
 
5
- from .test_config import IQTREE_COMMAND, RAXMLNG_COMMAND
7
+
8
+ def _command_path(environment_variable, executable):
9
+ configured_command = os.environ.get(environment_variable)
10
+ command = configured_command or shutil.which(executable)
11
+ if command is None:
12
+ pytest.fail(
13
+ f"Could not find {executable!r}. Add it to PATH or set "
14
+ f"{environment_variable}."
15
+ )
16
+ return pathlib.Path(command)
6
17
 
7
18
 
8
19
  @pytest.fixture
9
20
  def raxmlng_command():
10
- return pathlib.Path(RAXMLNG_COMMAND)
21
+ return _command_path("RAXMLNG_COMMAND", "raxml-ng")
11
22
 
12
23
 
13
24
  @pytest.fixture
14
25
  def iqtree_command():
15
- return pathlib.Path(IQTREE_COMMAND)
26
+ return _command_path("IQTREE_COMMAND", "iqtree2")
16
27
 
17
28
 
18
29
  @pytest.fixture
@@ -2,12 +2,12 @@ import pathlib
2
2
  import tempfile
3
3
 
4
4
  import pytest
5
-
6
- from labelgenerator.label import get_label, compute_label
7
- from labelgenerator.logger import logger
8
5
  from pypythia.custom_types import DataType
9
6
  from pypythia.msa import parse_msa
10
7
 
8
+ from labelgenerator.label import compute_label, get_label
9
+ from labelgenerator.logger import logger
10
+
11
11
 
12
12
  def test_get_label_fails_for_invalid_input():
13
13
  with pytest.raises(
@@ -88,11 +88,21 @@ def test_get_label(values, expected):
88
88
 
89
89
 
90
90
  @pytest.mark.parametrize(
91
- "data_type, expected_label",
92
- [(DataType.DNA, 0.772), (DataType.AA, 0.04), (DataType.MORPH, 0.173)],
91
+ "data_type, expected_label, tolerance",
92
+ [
93
+ # Native RAxML-NG builds can select different near-optimal DNA trees.
94
+ (DataType.DNA, 0.772, 0.05),
95
+ (DataType.AA, 0.04, 0.01),
96
+ (DataType.MORPH, 0.173, 0.01),
97
+ ],
93
98
  )
94
99
  def test_compute_label(
95
- raxmlng_command, iqtree_command, data_dir, data_type, expected_label
100
+ raxmlng_command,
101
+ iqtree_command,
102
+ data_dir,
103
+ data_type,
104
+ expected_label,
105
+ tolerance,
96
106
  ):
97
107
  msa_file = data_dir / f"{data_type.name}.phy"
98
108
 
@@ -109,7 +119,7 @@ def test_compute_label(
109
119
  log_info=False,
110
120
  seed=42,
111
121
  )
112
- assert label == pytest.approx(expected_label, abs=0.01)
122
+ assert label == pytest.approx(expected_label, abs=tolerance)
113
123
 
114
124
 
115
125
  def test_compute_label_with_logging(raxmlng_command, iqtree_command, data_dir):
@@ -139,8 +149,11 @@ def test_compute_label_with_logging(raxmlng_command, iqtree_command, data_dir):
139
149
  logfile_content = logfile.read_text()
140
150
 
141
151
  assert f"Inferring {n_trees} ML trees using RAxML-NG." in logfile_content
142
- assert "RF-Distance ML trees: 0.23" in logfile_content
143
- assert "Unique topologies ML trees: 2" in logfile_content
144
- assert "Found 10 plausible trees." in logfile_content
145
- assert "RF-Distance plausible trees: 0.23" in logfile_content
146
- assert "Unique topologies plausible trees: 2" in logfile_content
152
+ expected_lines = [
153
+ "RF-Distance ML trees: 0.23",
154
+ "Unique topologies ML trees: 2",
155
+ "Found 10 plausible trees.",
156
+ "RF-Distance plausible trees: 0.23",
157
+ "Unique topologies plausible trees: 2",
158
+ ]
159
+ assert all(line in logfile_content for line in expected_lines)
@@ -1,21 +1,32 @@
1
+ import pathlib
1
2
  import tempfile
2
- import pytest
3
3
 
4
4
  import pandas as pd
5
-
6
- from labelgenerator.main import main
7
- from labelgenerator import __version__
8
- import pathlib
9
-
5
+ import pytest
10
6
  from pypythia.custom_types import DataType
11
7
  from pypythia.msa import parse_msa
12
8
 
9
+ from labelgenerator import __version__
10
+ from labelgenerator.main import main
11
+
13
12
 
14
13
  @pytest.mark.parametrize(
15
- "data_type, expected_label",
16
- [(DataType.DNA, 0.772), (DataType.AA, 0.04), (DataType.MORPH, 0.173)],
14
+ "data_type, expected_label, tolerance",
15
+ [
16
+ # Native RAxML-NG builds can select different near-optimal DNA trees.
17
+ (DataType.DNA, 0.772, 0.05),
18
+ (DataType.AA, 0.04, 0.01),
19
+ (DataType.MORPH, 0.173, 0.01),
20
+ ],
17
21
  )
18
- def test_main(data_type, expected_label, data_dir, raxmlng_command, iqtree_command):
22
+ def test_main(
23
+ data_type,
24
+ expected_label,
25
+ tolerance,
26
+ data_dir,
27
+ raxmlng_command,
28
+ iqtree_command,
29
+ ):
19
30
  with tempfile.TemporaryDirectory() as tmpdir:
20
31
  # Create a temporary directory for the test
21
32
  prefix = pathlib.Path(tmpdir) / "test"
@@ -90,7 +101,7 @@ def test_main(data_type, expected_label, data_dir, raxmlng_command, iqtree_comma
90
101
 
91
102
  # Check if the label is correct
92
103
  label = features_content["difficulty"].values[0]
93
- assert label == pytest.approx(expected_label, abs=0.01)
104
+ assert label == pytest.approx(expected_label, abs=tolerance)
94
105
 
95
106
  # Check if the log file is correct and contains the expected output
96
107
  expected_lines = [
@@ -8,6 +8,7 @@ import pytest
8
8
  from pypythia.custom_types import DataType
9
9
  from pypythia.msa import parse_msa
10
10
 
11
+ import labelgenerator.raxmlng as raxmlng_module
11
12
  from labelgenerator.raxmlng import (
12
13
  _inference_results_exist_and_correct,
13
14
  _rfdist_results_exists_and_correct,
@@ -67,15 +68,48 @@ def test_infer_ml_trees(raxmlng_command, dna_msa, n_trees):
67
68
  expected_random = (
68
69
  f"random ({n_rand_expected}) + " if n_rand_expected > 0 else ""
69
70
  )
70
- expected_parsimony = (
71
- f"parsimony ({n_pars_expected})" if n_pars_expected > 0 else ""
72
- )
73
- expected_log = f"start tree(s): {expected_random}{expected_parsimony}"
71
+ expected_log = f"start tree(s): {expected_random}parsimony ({n_pars_expected})"
74
72
 
75
73
  log_file = prefix.with_suffix(".raxml.log")
76
74
  assert expected_log in log_file.read_text()
77
75
 
78
76
 
77
+ @pytest.mark.parametrize(
78
+ ("major_version", "expected_adaptive_setting"),
79
+ [(1, None), (2, "off"), (3, "off")],
80
+ )
81
+ def test_infer_ml_trees_preserves_v1_search_by_raxmlng_version(
82
+ tmp_path, monkeypatch, major_version, expected_adaptive_setting
83
+ ):
84
+ class RAxMLNGStub:
85
+ def __init__(self, _executable):
86
+ self._major_version = major_version
87
+
88
+ commands = []
89
+ monkeypatch.setattr(raxmlng_module, "RAxMLNG", RAxMLNGStub)
90
+ monkeypatch.setattr(raxmlng_module, "run_raxmlng_command", commands.append)
91
+
92
+ raxmlng_module.infer_ml_trees(
93
+ msa=tmp_path / "msa.phy",
94
+ raxmlng=tmp_path / "raxml-ng",
95
+ model="GTR+G",
96
+ prefix=tmp_path / "inference",
97
+ n_trees=2,
98
+ )
99
+
100
+ command = commands[0]
101
+ if expected_adaptive_setting is None:
102
+ assert "--adaptive" not in command
103
+ assert "--extra" not in command
104
+ else:
105
+ adaptive_index = command.index("--adaptive")
106
+ assert command[adaptive_index + 1] == expected_adaptive_setting
107
+ assert command.count("--adaptive") == 1
108
+ extra_index = command.index("--extra")
109
+ assert command[extra_index + 1] == "brlen-start-fixed"
110
+ assert command.count("--extra") == 1
111
+
112
+
79
113
  @pytest.mark.parametrize("data_type", [DataType.DNA, DataType.AA, DataType.MORPH])
80
114
  def test_infer_ml_trees_for_dtypes(raxmlng_command, data_dir, data_type):
81
115
  msa = data_dir / f"{data_type.name}.phy"
@@ -1,22 +0,0 @@
1
- name: Setup IQ-TREE
2
- runs:
3
- using: composite
4
- steps:
5
- - name: Download IQ-TREE MacOS
6
- if: runner.os == 'macOS'
7
- run: |
8
- wget https://github.com/iqtree/iqtree2/releases/download/v2.4.0/iqtree-2.4.0-macOS.zip
9
- unzip iqtree-*.zip && mv iqtree-*/* .
10
- shell: bash
11
- - name: Download IQ-TREE Linux
12
- if: runner.os == 'Linux'
13
- run: |
14
- wget https://github.com/iqtree/iqtree2/releases/download/v2.4.0/iqtree-2.4.0-Linux-intel.tar.gz
15
- tar xvf iqtree-*.tar.gz && mv iqtree-*/* .
16
- shell: bash
17
- - name: Unzip IQ-TREE and set Env variable
18
- run: echo iqtree2=$(pwd)/bin/iqtree2 >> $GITHUB_ENV
19
- shell: bash
20
- - name: Check IQ-TREE installation
21
- run: $iqtree2 -v
22
- shell: bash
@@ -1,20 +0,0 @@
1
- name: Setup RAxML-NG
2
- runs:
3
- using: composite
4
- steps:
5
- - name: Download RAxML-NG MacOS
6
- if: runner.os == 'macOS'
7
- run: wget https://github.com/amkozlov/raxml-ng/releases/download/1.2.2/raxml-ng_v1.2.2_macos.zip
8
- shell: bash
9
- - name: Download RAxML-NG Linux
10
- if: runner.os == 'Linux'
11
- run: wget https://github.com/amkozlov/raxml-ng/releases/download/1.2.2/raxml-ng_v1.2.2_linux_x86_64.zip
12
- shell: bash
13
- - name: Unzip RAxML-NG and set Env variable
14
- run: |
15
- unzip raxml-ng_*.zip
16
- echo raxmlng=$(pwd)/raxml-ng >> $GITHUB_ENV
17
- shell: bash
18
- - name: Check RAxML-NG installation
19
- run: $raxmlng -v
20
- shell: bash
@@ -1,12 +0,0 @@
1
- name: Test Label CLI
2
- inputs:
3
- msa-file:
4
- description: MSA file to test Label CLI with
5
- default: examples/example.phy
6
- runs:
7
- using: composite
8
- steps:
9
- - name: Run Label CLI with an exemplary MSA to make sure everything is working
10
- run: |
11
- label -m ${{ inputs.msa-file }} -r ${{ env.raxmlng }} -i ${{ env.iqtree2 }} --ntrees 4
12
- shell: bash -el {0}
@@ -1,72 +0,0 @@
1
- name: Build and test LabelGenerator
2
- run-name: Build and run the tests of the LabelGenerator python library.
3
- on:
4
- push:
5
- paths-ignore:
6
- - 'docs/**'
7
- jobs:
8
- Run-Label-Generator-Tests:
9
- runs-on: ${{ matrix.os }}
10
- strategy:
11
- matrix:
12
- os: [ubuntu-latest, macos-latest]
13
- python-version: ["3.9", "3.12"]
14
- steps:
15
- - name: Check out repository code
16
- uses: actions/checkout@v3
17
- - name: Setup Conda
18
- uses: mamba-org/setup-micromamba@v2
19
- with:
20
- environment-file: etc/environment.yml
21
- cache-environment: true
22
- create-args:
23
- python=${{ matrix.python-version }}
24
- generate-run-shell: false
25
- post-cleanup: none
26
- - name: Setup RAxML-NG and RAxML-NG env variable
27
- uses: ./.github/actions/setup-raxmlng
28
- - name: Setup IQ-TREE and IQ-TREE env variable
29
- uses: ./.github/actions/setup-iqtree
30
- - name: Install LabelGenerator and setup requirements
31
- run: |
32
- pip install -e . --no-deps
33
- rm tests/test_config.py
34
- echo "RAXMLNG_COMMAND = '${{ env.raxmlng }}'" >> tests/test_config.py
35
- echo "IQTREE_COMMAND = '${{ env.iqtree2 }}'" >> tests/test_config.py
36
- cat tests/test_config.py
37
- shell: bash -el {0}
38
- # - name: Setup tmate session
39
- # uses: mxschmitt/action-tmate@v3
40
- - name: Run LabelGenerator tests
41
- run: |
42
- PYTHONPATH=. pytest -svx --color=yes
43
- shell: bash -el {0}
44
-
45
- Install-using-conda:
46
- runs-on: ${{ matrix.os }}
47
- strategy:
48
- matrix:
49
- os: [ubuntu-latest, macos-latest]
50
- python-version: ["3.9", "3.12"]
51
- steps:
52
- - name: Check out repository code
53
- uses: actions/checkout@v3
54
- - name: Setup Conda
55
- uses: mamba-org/setup-micromamba@v2
56
- with:
57
- environment-file: etc/environment.yml
58
- cache-environment: true
59
- create-args:
60
- python=${{ matrix.python-version }}
61
- generate-run-shell: false
62
- post-cleanup: none
63
- - name: Install LabelGenerator # Install LabelGenerator manually to get the correct branch
64
- run: |
65
- pip install -e . --no-deps
66
- shell: bash -el {0}
67
- - name: Setup RAxML-NG and RAxML-NG env variable
68
- uses: ./.github/actions/setup-raxmlng
69
- - name: Setup IQ-TREE and IQ-TREE env variable
70
- uses: ./.github/actions/setup-iqtree
71
- - name: Test installation by running the CLI
72
- uses: ./.github/actions/test-label-cli
@@ -1,9 +0,0 @@
1
- name: labelGenerator
2
- channels:
3
- - conda-forge
4
- - nodefaults
5
- dependencies:
6
- - regex
7
- - loguru
8
- - pytest
9
- - pythiaphylopredictor >=2.0.0
@@ -1,2 +0,0 @@
1
- RAXMLNG_COMMAND = "/Users/julia/Software/raxml-ng_v1.2.0/raxml-ng"
2
- IQTREE_COMMAND = "/Users/julia/Software/iqtree-2.1.3-MacOSX/bin/iqtree2"