rapidtrees 0.2.3__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.
@@ -0,0 +1 @@
1
+ *.trees filter=lfs diff=lfs merge=lfs -text
@@ -0,0 +1,105 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [master, main]
6
+ pull_request:
7
+ branches: [master, main]
8
+
9
+ env:
10
+ CARGO_TERM_COLOR: always
11
+
12
+ jobs:
13
+ rust-test:
14
+ name: Rust Tests
15
+ runs-on: ${{ matrix.os }}
16
+ strategy:
17
+ matrix:
18
+ os: [ubuntu-latest, macos-latest]
19
+ rust: [stable]
20
+
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+ with:
24
+ lfs: true
25
+
26
+ - name: Setup Rust
27
+ uses: dtolnay/rust-toolchain@stable
28
+ with:
29
+ toolchain: ${{ matrix.rust }}
30
+
31
+ - name: Cache cargo registry
32
+ uses: actions/cache@v4
33
+ with:
34
+ path: ~/.cargo/registry
35
+ key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
36
+
37
+ - name: Cache cargo index
38
+ uses: actions/cache@v4
39
+ with:
40
+ path: ~/.cargo/git
41
+ key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
42
+
43
+ - name: Cache cargo build
44
+ uses: actions/cache@v4
45
+ with:
46
+ path: target
47
+ key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
48
+
49
+ - name: Check formatting
50
+ run: cargo fmt --all -- --check
51
+
52
+ - name: Run clippy
53
+ run: cargo clippy --all-targets --all-features -- -D warnings
54
+
55
+ - name: Build
56
+ run: cargo build --verbose
57
+
58
+ - name: Run tests
59
+ run: cargo test --verbose --lib
60
+
61
+ - name: Build release
62
+ run: cargo build --release --verbose
63
+
64
+ python-test:
65
+ name: Python API Tests
66
+ runs-on: ${{ matrix.os }}
67
+ strategy:
68
+ matrix:
69
+ os: [ubuntu-latest, macos-latest]
70
+ python-version: ["3.10", "3.11", "3.12"]
71
+
72
+ steps:
73
+ - uses: actions/checkout@v4
74
+ with:
75
+ lfs: true
76
+
77
+ - name: Setup Python
78
+ uses: actions/setup-python@v5
79
+ with:
80
+ python-version: ${{ matrix.python-version }}
81
+
82
+ - name: Setup Rust
83
+ uses: dtolnay/rust-toolchain@stable
84
+
85
+ - name: Cache cargo build
86
+ uses: actions/cache@v4
87
+ with:
88
+ path: target
89
+ key: ${{ runner.os }}-cargo-build-target-py${{ matrix.python-version }}-${{ hashFiles('**/Cargo.lock') }}
90
+
91
+ - name: Install dependencies
92
+ run: |
93
+ pip install --upgrade pip
94
+ pip install maturin pytest
95
+
96
+ - name: Build and install package
97
+ run: pip install -e . --verbose
98
+ env:
99
+ RUST_BACKTRACE: 1
100
+
101
+ - name: Test Python import
102
+ run: python -c "import rapidtrees; print('Import successful!')"
103
+
104
+ - name: Run Python API tests
105
+ run: pytest tests/test_python_api.py -v
@@ -0,0 +1,77 @@
1
+ name: Coverage
2
+
3
+ on:
4
+ push:
5
+ branches: [master, main]
6
+ pull_request:
7
+ branches: [master, main]
8
+
9
+ env:
10
+ CARGO_TERM_COLOR: always
11
+
12
+ jobs:
13
+ # ── Rust coverage with cargo-llvm-cov ────────────────────────────────
14
+ rust-coverage:
15
+ name: Rust Coverage
16
+ runs-on: ubuntu-latest
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ with:
20
+ lfs: true
21
+
22
+ - name: Setup Rust
23
+ uses: dtolnay/rust-toolchain@stable
24
+ with:
25
+ components: llvm-tools-preview
26
+
27
+ - name: Install cargo-llvm-cov
28
+ uses: taiki-e/install-action@cargo-llvm-cov
29
+
30
+ - name: Generate Rust coverage
31
+ run: cargo llvm-cov --lib --lcov --output-path rust-lcov.info
32
+
33
+ - name: Upload Rust coverage to Codecov
34
+ uses: codecov/codecov-action@v5
35
+ with:
36
+ files: rust-lcov.info
37
+ flags: rust
38
+ fail_ci_if_error: false
39
+ env:
40
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
41
+
42
+ # ── Python coverage with pytest-cov ──────────────────────────────────
43
+ python-coverage:
44
+ name: Python Coverage
45
+ runs-on: ubuntu-latest
46
+ steps:
47
+ - uses: actions/checkout@v4
48
+ with:
49
+ lfs: true
50
+
51
+ - name: Setup Python
52
+ uses: actions/setup-python@v5
53
+ with:
54
+ python-version: "3.12"
55
+
56
+ - name: Setup Rust
57
+ uses: dtolnay/rust-toolchain@stable
58
+
59
+ - name: Install dependencies
60
+ run: |
61
+ pip install --upgrade pip
62
+ pip install maturin pytest pytest-cov
63
+
64
+ - name: Build and install package
65
+ run: pip install -e . --verbose
66
+
67
+ - name: Run Python tests with coverage
68
+ run: pytest tests/test_python_api.py -v --cov=rapidtrees --cov-report=xml:python-coverage.xml
69
+
70
+ - name: Upload Python coverage to Codecov
71
+ uses: codecov/codecov-action@v5
72
+ with:
73
+ files: python-coverage.xml
74
+ flags: python
75
+ fail_ci_if_error: false
76
+ env:
77
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
@@ -0,0 +1,40 @@
1
+ name: Publish to crates.io
2
+
3
+ on:
4
+ release:
5
+ types: ["published"]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ # ── Validate tag matches Cargo.toml version ──────────────────────────
13
+ validate-release-tag:
14
+ name: Validate git tag
15
+ runs-on: ubuntu-latest
16
+ if: github.event_name == 'release'
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ - name: Compare git tag with Cargo.toml version
20
+ run: |
21
+ PUSHED_TAG=${GITHUB_REF##*/}
22
+ CURR_VER=$( grep '^version' Cargo.toml | head -n 1 | awk '{print $3}' | tr -d '"' )
23
+ if [[ "${PUSHED_TAG}" != "${CURR_VER}" ]]; then
24
+ echo "::error::Cargo.toml has version ${CURR_VER}, but tag is ${PUSHED_TAG} (expected ${CURR_VER})"
25
+ exit 1
26
+ fi
27
+
28
+ # ── Publish to crates.io ─────────────────────────────────────────────
29
+ publish-crate:
30
+ name: Publish to crates.io
31
+ needs: validate-release-tag
32
+ if: always() && (needs.validate-release-tag.result == 'success' || needs.validate-release-tag.result == 'skipped')
33
+ runs-on: ubuntu-latest
34
+ steps:
35
+ - uses: actions/checkout@v4
36
+ - uses: dtolnay/rust-toolchain@stable
37
+ - name: Publish to crates.io
38
+ run: cargo publish --no-default-features
39
+ env:
40
+ CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
@@ -0,0 +1,146 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ release:
5
+ types: ["published"]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ # ── Validate tag matches Cargo.toml version ──────────────────────────
13
+ validate-release-tag:
14
+ name: Validate git tag
15
+ runs-on: ubuntu-latest
16
+ if: github.event_name == 'release'
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ - name: Compare git tag with Cargo.toml version
20
+ run: |
21
+ PUSHED_TAG=${GITHUB_REF##*/}
22
+ CURR_VER=$( grep '^version' Cargo.toml | head -n 1 | awk '{print $3}' | tr -d '"' )
23
+ if [[ "${PUSHED_TAG}" != "${CURR_VER}" ]]; then
24
+ echo "::error::Cargo.toml has version ${CURR_VER}, but tag is ${PUSHED_TAG} (expected ${CURR_VER})"
25
+ exit 1
26
+ fi
27
+
28
+ # ── Build PyPI wheels: Linux ─────────────────────────────────────────
29
+ build-linux:
30
+ name: Build wheels (Linux ${{ matrix.target }})
31
+ needs: validate-release-tag
32
+ if: always() && (needs.validate-release-tag.result == 'success' || needs.validate-release-tag.result == 'skipped')
33
+ runs-on: ubuntu-latest
34
+ strategy:
35
+ fail-fast: false
36
+ matrix:
37
+ target: [x86_64, aarch64]
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+ - uses: actions/setup-python@v5
41
+ with:
42
+ python-version: "3.x"
43
+ - name: Build wheels
44
+ uses: PyO3/maturin-action@v1
45
+ with:
46
+ target: ${{ matrix.target }}
47
+ args: --release --out dist --find-interpreter
48
+ sccache: "true"
49
+ manylinux: auto
50
+ - uses: actions/upload-artifact@v4
51
+ with:
52
+ name: wheels-linux-${{ matrix.target }}
53
+ path: dist
54
+
55
+ # ── Build PyPI wheels: macOS ─────────────────────────────────────────
56
+ build-macos:
57
+ name: Build wheels (macOS ${{ matrix.target }})
58
+ needs: validate-release-tag
59
+ if: always() && (needs.validate-release-tag.result == 'success' || needs.validate-release-tag.result == 'skipped')
60
+ runs-on: ${{ matrix.runner }}
61
+ strategy:
62
+ fail-fast: false
63
+ matrix:
64
+ include:
65
+ - runner: macos-15
66
+ target: x86_64
67
+ - runner: macos-latest
68
+ target: aarch64
69
+ steps:
70
+ - uses: actions/checkout@v4
71
+ - uses: actions/setup-python@v5
72
+ with:
73
+ python-version: "3.x"
74
+ - name: Build wheels
75
+ uses: PyO3/maturin-action@v1
76
+ with:
77
+ target: ${{ matrix.target }}
78
+ args: --release --out dist --find-interpreter
79
+ sccache: "true"
80
+ - uses: actions/upload-artifact@v4
81
+ with:
82
+ name: wheels-macos-${{ matrix.target }}
83
+ path: dist
84
+
85
+ # ── Build PyPI wheels: Windows ───────────────────────────────────────
86
+ build-windows:
87
+ name: Build wheels (Windows x64)
88
+ needs: validate-release-tag
89
+ if: always() && (needs.validate-release-tag.result == 'success' || needs.validate-release-tag.result == 'skipped')
90
+ runs-on: windows-latest
91
+ steps:
92
+ - uses: actions/checkout@v4
93
+ - uses: actions/setup-python@v5
94
+ with:
95
+ python-version: "3.x"
96
+ architecture: x64
97
+ - name: Build wheels
98
+ uses: PyO3/maturin-action@v1
99
+ with:
100
+ target: x64
101
+ args: --release --out dist --find-interpreter
102
+ sccache: "true"
103
+ - uses: actions/upload-artifact@v4
104
+ with:
105
+ name: wheels-windows-x64
106
+ path: dist
107
+
108
+ # ── Build source distribution ────────────────────────────────────────
109
+ build-sdist:
110
+ name: Build source distribution
111
+ needs: validate-release-tag
112
+ if: always() && (needs.validate-release-tag.result == 'success' || needs.validate-release-tag.result == 'skipped')
113
+ runs-on: ubuntu-latest
114
+ steps:
115
+ - uses: actions/checkout@v4
116
+ - name: Build sdist
117
+ uses: PyO3/maturin-action@v1
118
+ with:
119
+ command: sdist
120
+ args: --out dist
121
+ - uses: actions/upload-artifact@v4
122
+ with:
123
+ name: wheels-sdist
124
+ path: dist
125
+
126
+ # ── Publish to PyPI ──────────────────────────────────────────────────
127
+ publish-pypi:
128
+ name: Publish to PyPI
129
+ runs-on: ubuntu-latest
130
+ needs: [build-linux, build-macos, build-windows, build-sdist]
131
+ if: always() && needs.build-linux.result == 'success' && needs.build-macos.result == 'success' && needs.build-windows.result == 'success' && needs.build-sdist.result == 'success'
132
+ environment:
133
+ name: pypi
134
+ url: https://pypi.org/p/rapidtrees
135
+ permissions:
136
+ id-token: write
137
+ steps:
138
+ - uses: actions/download-artifact@v4
139
+ with:
140
+ pattern: wheels-*
141
+ merge-multiple: true
142
+ path: dist
143
+ - name: List dist files
144
+ run: ls -lh dist/
145
+ - name: Publish to PyPI
146
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,8 @@
1
+ /target
2
+ bigdata/
3
+ out/
4
+ Cargo.lock
5
+ __pycache__/
6
+ *.pyc
7
+ .venv
8
+ .pytest_cache/
@@ -0,0 +1,30 @@
1
+ # Pre-commit hooks for Rust project
2
+ # Install pre-commit: pip install pre-commit
3
+ # Setup hooks: pre-commit install
4
+
5
+ repos:
6
+ - repo: local
7
+ hooks:
8
+ - id: cargo-fmt
9
+ name: cargo fmt
10
+ description: Format Rust code with cargo fmt
11
+ entry: cargo fmt --all
12
+ language: system
13
+ types: [rust]
14
+ pass_filenames: false
15
+
16
+ - id: cargo-clippy
17
+ name: cargo clippy
18
+ description: Lint Rust code with cargo clippy
19
+ entry: cargo clippy --all-targets --all-features --fix --allow-staged --allow-dirty -- -D warnings
20
+ language: system
21
+ types: [rust]
22
+ pass_filenames: false
23
+
24
+ - id: cargo-check
25
+ name: cargo check
26
+ description: Check if Rust code compiles
27
+ entry: cargo check --all-targets --all-features
28
+ language: system
29
+ types: [rust]
30
+ pass_filenames: false
@@ -0,0 +1,48 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+ This project uses release names based on random words from [codenamegenerator.com](https://www.codenamegenerator.com/):
8
+ - PREFIX: Microsoft Corperation
9
+ - DICTIONARY: Snakes
10
+
11
+ ## [0.2.1] - Slate King Cobra (2025-11-16)
12
+
13
+ ### Changed
14
+
15
+ #### Performance Improvements 🚀
16
+
17
+ - **Major algorithmic optimization**: Replaced HashMap/HashSet-based intersection with sorted merge algorithm for distance calculations
18
+ - Direct array indexing instead of HashMap lookups (10-20× faster for branch length access)
19
+ - Performance: ~2.3M tree comparisons/second on ZIKA dataset (283 taxa, 4000 trees, ~8M comparisons)
20
+ - All three distance metrics (RF, Weighted RF, KF) now complete in ~3.5 seconds, and are deterministic
21
+
22
+ - **Optimized data structures**:
23
+ - `TreeSnapshot` now uses `Vec<Bitset>` instead of `HashSet<Bitset>` for partitions (sorted for merge)
24
+ - Parallel vectors for partitions and branch lengths instead of `HashMap<Bitset, f64>`
25
+ - Switched to `FxHashMap` from `rustc-hash` crate for remaining hash operations (faster than std HashMap)
26
+
27
+ - **Added `#[inline]` annotations** to critical distance calculation functions for better compiler optimization
28
+
29
+ #### Bug Fixes 🐛
30
+
31
+ - Fixed BEAST tree name parsing in `io.rs`:
32
+ - Previously only extracted state numbers, now properly extracts full tree names
33
+ - Handles various BEAST tree name formats (e.g., `classic2_STATE_968940000`, `STATE_8500000`)
34
+
35
+ ### Added
36
+
37
+ - Updated pre-commit configuration
38
+
39
+ ## [0.1.0] - Aero Boa (Initial Release)
40
+
41
+ Initial release with basic functionality for computing phylogenetic tree distances:
42
+
43
+ - Robinson-Foulds distance
44
+ - Weighted Robinson-Foulds distance
45
+ - Kuhner-Felsenstein distance
46
+ - BEAST/NEXUS file format support
47
+ - Python API via maturin
48
+