Skip to content

Commit 8c7c5b3

Browse files
authored
Overhaul package
2 parents 31bef91 + fc274dc commit 8c7c5b3

File tree

17 files changed

+1992
-250
lines changed

17 files changed

+1992
-250
lines changed

.coveragerc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[run]
2+
omit =
3+
rle/tests/*
4+
rle/benchmarks/*
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Run pytest
2+
3+
on:
4+
push:
5+
branches: [ master ]
6+
pull_request:
7+
branches: [ master ]
8+
9+
jobs:
10+
pytest:
11+
runs-on: ubuntu-latest
12+
timeout-minutes: 30
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
python-version: [3.6, 3.7, 3.8, 3.9]
17+
18+
steps:
19+
- uses: actions/checkout@v2
20+
21+
- name: Set up Python ${{ matrix.python-version }}
22+
uses: actions/setup-python@v2
23+
with:
24+
python-version: ${{ matrix.python-version }}
25+
26+
- uses: actions-rs/toolchain@v1
27+
with:
28+
toolchain: stable
29+
30+
- name: Install dependencies
31+
run: |
32+
pip install --upgrade pip
33+
pip install setuptools-rust pytest pydicom coverage pytest-cov
34+
pip install git+https://github.com/pydicom/pylibjpeg-data
35+
pip install -e .
36+
37+
- name: Test with pytest
38+
env:
39+
PYTHON_VERSION: ${{ matrix.python-version }}
40+
run: |
41+
pytest --cov rle
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
name: Build wheels and deploy to PyPI
2+
3+
on:
4+
release:
5+
types: [ published ]
6+
7+
jobs:
8+
build_wheels:
9+
name: Build wheels for ${{ matrix.os }}
10+
runs-on: ${{ matrix.os }}
11+
env:
12+
CIBW_SKIP: "cp35-*"
13+
strategy:
14+
fail-fast: false
15+
matrix:
16+
os: [ubuntu-latest, windows-latest, macos-latest]
17+
python-version: [3.9]
18+
19+
steps:
20+
- uses: actions/checkout@v2
21+
with:
22+
submodules: true
23+
24+
# Install rust
25+
- uses: actions-rs/toolchain@v1
26+
with:
27+
toolchain: stable
28+
29+
# Install Python
30+
- uses: actions/setup-python@v2
31+
name: Install Python
32+
with:
33+
python-version: ${{ matrix.python-version }}
34+
35+
- name: Install requirements
36+
run: |
37+
pip install -U pip
38+
pip install cibuildwheel==1.10.0
39+
pip install setuptools-rust
40+
41+
- name: Build sdist
42+
run: |
43+
python setup.py sdist
44+
45+
- name: Build wheels
46+
run: |
47+
python --version
48+
python -m cibuildwheel --output-dir dist
49+
env:
50+
CIBW_BEFORE_ALL: |
51+
curl -sSf https://sh.rustup.rs | sh -s -- --default-toolchain stable -y && rustup target add i686-pc-windows-msvc
52+
CIBW_ENVIRONMENT: 'PATH="$PATH:$HOME/.cargo/bin"'
53+
54+
- uses: actions/upload-artifact@v2
55+
with:
56+
name: wheels
57+
path: ./dist
58+
59+
# The pypi upload fails with non-linux containers, so grab the uploaded
60+
# artifacts and run using those
61+
# See: https://github.com/pypa/gh-action-pypi-publish/discussions/15
62+
deploy:
63+
name: Upload wheels to PyPI
64+
needs:
65+
- build_wheels
66+
runs-on: ubuntu-latest
67+
68+
steps:
69+
- name: Download the wheels
70+
uses: actions/download-artifact@v2
71+
with:
72+
name: wheels
73+
path: dist/
74+
75+
#- name: Publish package to Test PyPi
76+
# uses: pypa/gh-action-pypi-publish@master
77+
# with:
78+
# user: __token__
79+
# password: ${{ secrets.TEST_PYPI_PASSWORD }}
80+
# repository_url: https://test.pypi.org/legacy/
81+
82+
- name: Publish package to PyPi
83+
uses: pypa/gh-action-pypi-publish@master
84+
with:
85+
user: __token__
86+
password: ${{ secrets.PYPI_PASSWORD }}

rle/src/rustrle/Cargo.lock renamed to Cargo.lock

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
[package]
2-
name = "rle"
3-
version = "0.1.0"
2+
name = "_rle"
3+
version = "1.0.0"
44
authors = ["scaramallion <[email protected]>"]
55
edition = "2018"
66

7-
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8-
9-
[dependencies]
10-
pyo3 = { version = "0.13.1", features = ["extension-module"] }
11-
127

138
[lib]
149
name = "_rle"
1510
crate-type = ["cdylib"]
11+
12+
13+
[dependencies]
14+
pyo3 = { version = "0.13.1", features = ["extension-module"] }

MANIFEST.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
include Cargo.toml
2+
include Cargo.lock
3+
recursive-include src *

README.md

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,76 @@
1-
# pylibjpeg-rle
2-
Fast RLE decoding plugin for pylibjpeg
1+
2+
## pylibjpeg-rle
3+
4+
A fast DICOM RLE decoding plugin for pylibjpeg, written in Rust with a Python 3.6+ wrapper.
5+
6+
Linux, OSX and Windows are all supported.
7+
8+
### Installation
9+
#### Installing the current release
10+
```bash
11+
pip install pylibjpeg-rle
12+
```
13+
#### Installing the development version
14+
15+
Make sure [Python](https://www.python.org/), [Git](https://git-scm.com/) and
16+
[Rust](https://www.rust-lang.org/) are installed. For Windows, you also need to install
17+
[Microsoft's C++ Build Tools](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools&rel=16).
18+
```bash
19+
git clone https://github.com/pydicom/pylibjpeg-rle
20+
cd pylibjpeg-rle
21+
python -m setup.py develop
22+
```
23+
24+
### Supported Transfer Syntaxes
25+
#### Decoding
26+
| UID | Description |
27+
| --- | --- |
28+
| 1.2.840.10008.1.2.5 | RLE Lossless |
29+
30+
### Benchmarks
31+
#### Decoding
32+
33+
Time per 1000 decodes, pydicom's NumPy RLE handler vs. pylibjpeg-rle
34+
35+
| Dataset | Pixels | Bytes | NumPy | pylibjpeg-rle |
36+
| --- | --- | --- | --- | --- |
37+
| OBXXXX1A_rle.dcm | 480,000 | 480,000 | 4.89 s | 0.79 s |
38+
| OBXXXX1A_rle_2frame.dcm | 960,000 | 960,000 | 9.89 s | 1.65 s |
39+
| SC_rgb_rle.dcm | 10,000 | 30,000 | 0.20 s | 0.15 s |
40+
| SC_rgb_rle_2frame.dcm | 20,000 | 60,000 | 0.32 s | 0.18 s |
41+
| MR_small_RLE.dcm | 4,096 | 8,192 | 0.35 s | 0.13 s |
42+
| emri_small_RLE.dcm | 40,960 | 81,920 | 1.13 s | 0.28 s |
43+
| SC_rgb_rle_16bit.dcm | 10,000 | 60,000 | 0.33 s | 0.17 s |
44+
| SC_rgb_rle_16bit_2frame.dcm | 20,000 | 120,000 | 0.56 s | 0.21 s |
45+
| rtdose_rle_1frame.dcm | 100 | 400 | 0.12 s | 0.13 s |
46+
| rtdose_rle.dcm | 1,500 | 6,000 | 0.53 s | 0.26 s |
47+
| SC_rgb_rle_32bit.dcm | 10,000 | 120,000 | 0.56 s | 0.19 s |
48+
| SC_rgb_rle_32bit_2frame.dcm | 20,000 | 240,000 | 1.03 s | 0.28 s |
49+
50+
### Usage
51+
#### With pylibjpeg and pydicom
52+
53+
Because pydicom defaults to the NumPy RLE decoder, you must specify the use
54+
of pylibjpeg when decompressing:
55+
*Pixel Data*:
56+
```python
57+
from pydicom import dcmread
58+
from pydicom.data import get_testdata_file
59+
60+
ds = dcmread(get_testdata_file("OBXXXX1A_rle.dcm"))
61+
ds.decompress("pylibjpeg")
62+
arr = ds.pixel_array
63+
```
64+
65+
Alternatively you can use the included functions to decode a given dataset:
66+
```python
67+
from rle import pixel_array, generate_frames
68+
69+
# Return the entire Pixel Data as an ndarray
70+
arr = pixel_array(ds)
71+
72+
# Generator function that only processes 1 frame at a time,
73+
# may help reduce memory usage when dealing with large Pixel Data
74+
for arr in generate_frames(ds):
75+
print(arr.shape)
76+
```

pyproject.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[build-system]
2+
requires = [
3+
"setuptools-rust",
4+
"wheel"
5+
]

rle/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
"""Set package shortcuts."""
22

3-
from ._version import __version__
3+
from rle._version import __version__
4+
from rle.utils import pixel_array, generate_frames, decode_pixel_data

rle/benchmarks/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)