Automated cropping of prostate MR images.
Project description
CROPro
CROPro is a Python package for automated cropping of prostate MRI volumes. It was developed for prostate MR preprocessing workflows where a model or reviewer needs consistent image patches around the prostate gland or clinically significant prostate cancer lesions.
The package supports:
- two selectable pipelines: a
croppipeline and aresamplepipeline center,random, andstridecrop strategies- T2W-only and bpMRI cropping workflows
- negative, positive, and unknown patient-status workflows
- configurable in-plane resampling through
pixel_spacing - a configurable dataset layout so the same pipelines work on multiple databases
- Python API and command-line usage
If you use CROPro, please cite the paper listed in Citation:
CROPro: a tool for automated cropping of prostate magnetic resonance images.
Contents
- Installation
- Pipelines
- Quick Start
- Input Data
- Patient Workflows
- Visual Examples
- Pixel Spacing
- PI-CAI Dataset Setup
- Command Line
- Configuration Reference
- Development
- PyPI Release
- Citation
Installation
This repository uses uv for dependency management.
Install uv if needed:
curl -LsSf https://astral.sh/uv/install.sh | sh
Clone the repository and install the environment:
git clone https://github.com/alexofficial/CROPro.git
cd CROPro
uv sync
Check that the CLI is available:
uv run cropro --help
For development tools such as tests and linting:
uv sync --extra dev
When CROPro is published to PyPI, users will be able to install it in a project with:
uv add cropro
For CLI-only use after PyPI publication:
uv tool install cropro
cropro --help
PyPI Release
This repository is configured to publish to PyPI through GitHub Actions using Trusted Publishing.
One-Time Setup
- On PyPI, create a project named
cropro(or claim it if it already exists under your account). - In PyPI project settings, configure a Trusted Publisher for this GitHub repository and workflow:
- owner/repo:
alexofficial/CROPro - workflow filename:
.github/workflows/pypi-publish.yml - environment:
pypi
Release Flow
- Update version in
pyproject.toml. - Commit and push to
main. - Create a GitHub release (for example tag
v0.1.1). - The
Publish to PyPIworkflow builds the package and uploads it to PyPI.
Optional Local Validation
python -m build
python -m twine check dist/*
Pipelines
CROPro exposes two pipelines as command-line subcommands. Pick the one that matches what you need; they can be combined (resample first, then crop).
| Pipeline | Command | What it does |
|---|---|---|
| Resample | cropro resample |
Resamples a whole database onto each case's T2W grid and writes the aligned copies to disk. Use this to prepare a dataset before cropping. |
| Crop | cropro crop |
Crops T2W (and optionally ADC/HBV) around the gland or lesion. For bpMRI it verifies that ADC/HBV are aligned to T2W and stops with a clear message if they are not. |
Running cropro without a subcommand defaults to crop, so existing commands
keep working unchanged.
Resample Pipeline
The resample pipeline aligns every case in a database onto its T2W geometry. It
is database-agnostic: the file layout is described by a configurable
DatasetLayout, which defaults to the PI-CAI conventions but can be pointed at
any dataset through CLI flags or an INI file.
# Resample the PI-CAI database into a new folder
uv run cropro resample \
--images-root dataset/PI-CAI/images \
--output-root dataset/PI-CAI/images_resampled
Resampled T2W/ADC/HBV scans use B-spline interpolation; gland and lesion masks
use nearest-neighbour. The output mirrors the input folder structure. Omit
--output-root to write the aligned copies next to the originals with a
_to_t2w suffix.
If a *.zip image archive is present (for the PI-CAI layout this defaults to
dataset/PI-CAI/archives, i.e. <images-root>/../archives), the pipeline
unpacks it into --images-root before aligning. Existing files are skipped, so
the step is safe to re-run. Point --archives-root at a different directory, or
pass --archives-root none to disable extraction.
To target a different database, override the layout. Either pass the suffixes and mask roots directly:
uv run cropro resample \
--images-root data/my_dataset/images \
--output-root data/my_dataset/resampled \
--t2w-suffix _t2w.nii.gz \
--adc-suffix _adc.nii.gz \
--hbv-suffix _hbv.nii.gz \
--gland-root data/my_dataset/masks/gland \
--lesion-root data/my_dataset/masks/lesion
or keep the paths in an INI file and pass --config:
# config/resample_paths.ini
[paths]
images_root = data/my_dataset/images
output_root = data/my_dataset/resampled
gland_root = data/my_dataset/masks/gland
lesion_root = data/my_dataset/masks/lesion
uv run cropro resample --config config/resample_paths.ini
CLI flags take precedence over values in the INI file, so you can keep shared paths in the file and override individual fields on the command line.
Crop Pipeline
The crop pipeline is the original CROPro behaviour. See Quick Start and Command Line for examples. For bpMRI it first checks that ADC and HBV are aligned to T2W; if they are not, it stops and tells you to run the resample pipeline (or to let it resample on the fly). See Aligning ADC/HBV to T2W (bpMRI).
Quick Start
Crop A Negative Or Unknown Case
Use this when you have a T2W image and a prostate gland mask. For unknown patient status, CROPro uses the same gland-mask workflow as negative, which is useful for inference or review cases where cancer status is not known yet.
from cropro import CROPro, CropConfig
config = CropConfig(
crop_method="stride",
patient_status="negative", # "negative" or "unknown"
sequence_type="T2W",
orig_img_path_t2w="data/patient_001/t2w.nii.gz",
seg_img_path="data/patient_001/prostate_gland_mask.nii.gz",
pixel_spacing=0.4,
crop_image_size=128,
crop_stride=32,
saved_image_type="png",
path_to_save="outputs/patient_001",
)
CROPro(config).run()
Crop A Positive Case
Use this when you have a prostate gland mask and a lesion mask. The gland mask defines the anatomical search region; the lesion mask is used to keep crops that contain enough lesion area.
from cropro import CROPro, CropConfig
config = CropConfig(
crop_method="stride",
patient_status="positive",
sequence_type="T2W",
orig_img_path_t2w="data/patient_002/t2w.nii.gz",
seg_img_path="data/patient_002/prostate_gland_mask.nii.gz",
seg_img_path_lesion="data/patient_002/lesion_mask.nii.gz",
tumor_label_level=1,
c_min_positive=0.2,
pixel_spacing=0.4,
crop_image_size=128,
crop_stride=32,
saved_image_type="png",
path_to_save="outputs/patient_002",
)
CROPro(config).run()
Crop bpMRI
Set sequence_type="bpMRI" and provide T2W, ADC, and HBV images. CROPro saves aligned crops for each modality.
from cropro import CROPro, CropConfig
config = CropConfig(
crop_method="center",
patient_status="negative",
sequence_type="bpMRI",
orig_img_path_t2w="data/patient_003/t2w.nii.gz",
orig_img_path_adc="data/patient_003/adc.nii.gz",
orig_img_path_hbv="data/patient_003/hbv.nii.gz",
seg_img_path="data/patient_003/prostate_gland_mask.nii.gz",
pixel_spacing=0.5,
crop_image_size=128,
saved_image_type="png",
path_to_save="outputs/patient_003",
)
CROPro(config).run()
Input Data
CROPro reads 3D medical image files through SimpleITK. Common formats include .nii, .nii.gz, .mha, .mhd, and other SimpleITK-readable formats.
For a negative or unknown patient, provide:
- T2W image
- prostate gland segmentation mask
For a positive patient, provide:
- T2W image
- prostate gland segmentation mask
- lesion segmentation mask
For sequence_type="bpMRI", also provide:
- ADC image
- HBV image
All images and masks should already be spatially aligned. CROPro resamples the image spacing for crop generation, but it does not perform image registration.
Patient Workflows
| Status | Intended use | Segmentation behavior |
|---|---|---|
negative |
Cancer-free cases | Uses the prostate gland mask to crop the prostate region. |
positive |
Cancer-present cases | Uses the prostate gland mask for crop placement and the lesion mask to keep crops containing enough lesion area. |
unknown |
Inference, testing, or review cases with unknown health status | Uses the prostate gland mask like the negative workflow and returns candidate prostate-region crops. |
Visual Examples
Negative Or Unknown Workflow
For negative and unknown cases, the prostate gland mask defines the region to crop.
Stride-cropped bpMRI output at 0.4 mm/pixel. With crop_image_size=128, the crop covers about 51.2 x 51.2 mm.
The same case at 0.5 mm/pixel covers about 64.0 x 64.0 mm and includes more surrounding context.
Positive Workflow
For positive cases, CROPro uses the prostate gland mask plus a lesion mask. A crop is saved only when the lesion area inside the crop satisfies the configured threshold.
Stride-cropped bpMRI output at 0.4 mm/pixel:
The same positive case at 0.5 mm/pixel:
Pixel Spacing
pixel_spacing controls the target in-plane resolution in millimeters per pixel before cropping. This matters because prostate MRI scans can come from different scanners, protocols, and reconstruction settings. Resampling to a consistent spacing makes crops more comparable across patients.
With crop_image_size=128:
| Pixel spacing | Crop size in pixels | Approximate physical area |
|---|---|---|
0.4 mm/pixel |
128 x 128 |
51.2 x 51.2 mm |
0.5 mm/pixel |
128 x 128 |
64.0 x 64.0 mm |
A 0.4 mm/pixel crop is tighter around the anatomy. A 0.5 mm/pixel crop covers a wider physical region and can preserve more surrounding anatomical context.
from cropro import CROPro, CropConfig
tight_crop = CropConfig(
crop_method="center",
patient_status="negative",
sequence_type="T2W",
orig_img_path_t2w="data/patient_001/t2w.nii.gz",
seg_img_path="data/patient_001/prostate_gland_mask.nii.gz",
pixel_spacing=0.4,
crop_image_size=128,
path_to_save="outputs/patient_001_spacing_0.4",
)
wide_crop = CropConfig(
crop_method="center",
patient_status="negative",
sequence_type="T2W",
orig_img_path_t2w="data/patient_001/t2w.nii.gz",
seg_img_path="data/patient_001/prostate_gland_mask.nii.gz",
pixel_spacing=0.5,
crop_image_size=128,
path_to_save="outputs/patient_001_spacing_0.5",
)
CROPro(tight_crop).run()
CROPro(wide_crop).run()
PI-CAI Dataset Setup
The runnable examples use the official PI-CAI Public Training and Development Dataset. Images are hosted on Zenodo, and annotations are maintained in the DIAGNijmegen/picai_labels repository.
The default download fetches public image fold 0, which is about 5.4 GB, and clones the labels:
uv sync
bash scripts/download_dataset.sh
The script writes data under dataset/PI-CAI/. This directory is ignored by git.
The image download is resumable because the script uses curl -C -. If the download is interrupted, run the same command again:
bash scripts/download_dataset.sh
To download all five public image folds, about 26.9 GB:
CROPRO_PICAI_FOLDS="0 1 2 3 4" bash scripts/download_dataset.sh
To place the PI-CAI data somewhere else:
CROPRO_DATASET_ROOT="/path/to/PI-CAI" bash scripts/download_dataset.sh
Expected layout:
dataset/PI-CAI/
archives/
picai_public_images_fold0.zip
images/
10001/
10001_1000001_t2w.mha
10001_1000001_adc.mha
10001_1000001_hbv.mha
picai_labels/
anatomical_delineations/whole_gland/AI/Bosma22b/
csPCa_lesion_delineations/human_expert/resampled/
Run the examples:
uv run python examples/PI-CAI_negative_crop.py
uv run python examples/PI-CAI_positive_crop.py
Or run both:
bash scripts/examples.sh
PI-CAI notes:
- Public images:
https://zenodo.org/records/6624726 - Labels:
https://github.com/DIAGNijmegen/picai_labels - Official image names use
[patient_id]_[study_id]_t2w.mha,[patient_id]_[study_id]_adc.mha, and[patient_id]_[study_id]_hbv.mha. - Whole-gland masks are used for
negativeandunknowncrops. - Positive crops use the whole-gland mask plus the csPCa lesion mask. Set
tumor_label_levelto the lesion value used by the selected label file. The bundled PI-CAI positive example uses case10032_1000032, whose lesion label is3.
Command Line
After installation, use the cropro command. It has two subcommands, crop
and resample (see Pipelines); running cropro with no
subcommand defaults to crop. From this repository, prefix commands with
uv run.
Negative or unknown patient:
uv run cropro \
--crop_method stride \
--patient_status negative \
--sequence_type T2W \
--orig_img_path_t2w data/patient_001/t2w.nii.gz \
--seg_img_path data/patient_001/prostate_gland_mask.nii.gz \
--pixel_spacing 0.4 \
--crop_image_size 128 \
--crop_stride 32 \
--saved_image_type png \
--path_to_save outputs/patient_001
Positive patient:
uv run cropro \
--crop_method stride \
--patient_status positive \
--sequence_type T2W \
--orig_img_path_t2w data/patient_002/t2w.nii.gz \
--seg_img_path data/patient_002/prostate_gland_mask.nii.gz \
--seg_img_path_lesion data/patient_002/lesion_mask.nii.gz \
--tumor_label_level 1 \
--c_min_positive 0.2 \
--pixel_spacing 0.4 \
--crop_image_size 128 \
--crop_stride 32 \
--saved_image_type png \
--path_to_save outputs/patient_002
Boolean CLI arguments require explicit values:
uv run cropro --keep_all_slice false --do_normalization true ...
Output
CROPro writes cropped files to path_to_save. Filenames include:
- sequence type
- slice number
- crop index when applicable
- crop coordinates
- modality suffix such as
T2W,ADC, orHBV
Example:
outputs/patient_001/
T2W_slice_7_of_21_1_cord_160_166_T2W.png
Configuration Reference
These variables are accepted by the Python CropConfig class and by CLI arguments with the same names.
| Setting | Default | Meaning |
|---|---|---|
crop_method |
center |
Crop strategy: center, random, or stride. |
orig_img_path_t2w |
None |
T2W image path. Required for all workflows. |
orig_img_path_adc |
None |
ADC image path. Required when sequence_type="bpMRI". |
orig_img_path_hbv |
None |
HBV image path. Required when sequence_type="bpMRI". |
seg_img_path |
None |
Prostate gland segmentation mask path. Required for negative, unknown, and positive workflows. |
seg_img_path_lesion |
None |
Lesion segmentation mask path. Required for positive patients unless the gland mask already contains lesion labels. |
prostate_gland_seg_contains_lesion |
False |
Set to True when seg_img_path contains both gland and lesion labels. |
tumor_label_level |
2 |
Label value used for lesion pixels. Use 1 if your lesion mask stores lesions as label 1. |
patient_status |
negative |
negative, positive, or unknown. |
pixel_spacing |
0.5 |
Target in-plane spacing in millimeters per pixel before cropping. |
crop_image_size |
128 |
Output crop width and height in pixels. |
sample_number |
12 |
Number of random crops to try when crop_method="random". |
crop_stride |
32 |
Step size in pixels when crop_method="stride". |
sequence_type |
T2W |
T2W for T2W-only crops, or bpMRI for T2W/ADC/HBV crops. |
resample_bpmri_to_t2w |
False |
When True, resample ADC/HBV onto the T2W grid on-the-fly so all sequences align before cropping. |
resample_first |
False |
When True, run a pre-step that resamples all images (T2W, ADC, HBV and the segmentation masks) onto the common T2W grid before cropping. Implies resample_bpmri_to_t2w and also aligns the masks. |
normalized_image |
True |
Set to True when the source image is already normalized. |
normalized_vmaxNumber |
242 |
Maximum value used by the legacy normalization/saving path. |
do_normalization |
False |
Normalize image intensity before saving. |
t2w_normalization_method |
autoref |
Normalization strategy for T2W: percentile, autoref, gaussian, or zscore_clip. |
adc_normalization_method |
percentile |
Normalization strategy for ADC (percentile, gaussian, zscore_clip; autoref is T2W-only). |
hbv_normalization_method |
percentile |
Normalization strategy for HBV (percentile, gaussian, zscore_clip; autoref is T2W-only). |
min_percentile |
0.5 |
Lower percentile for intensity clipping/normalization. |
max_percentile |
99.5 |
Upper percentile for intensity clipping/normalization. |
saved_image_type |
tiff |
Output type: png, jpg, jpeg, tiff, tif, npy, or nmp. |
path_to_save |
save_crop |
Output directory. |
c_min_positive |
0.2 |
Minimum lesion overlap required for saving a positive crop. |
c_min_negative |
1 |
Minimum gland coverage rule used by negative crop selection. |
percentage_of_allowed_overlapping_betweeing_gland_lesions_mask |
50.0 |
Allowed overlap percentage between gland and lesion masks for mask consistency checks. |
number_of_slices_to_exclude_from_mask_gland |
1 |
Number of gland-mask edge slices to exclude from crop selection. |
keep_all_slice |
True |
Keep all selected slices instead of applying slice filtering. |
Aligning ADC/HBV to T2W (bpMRI)
In PI-CAI the T2W, ADC and HBV sequences are acquired independently and often
differ in slice count and in-plane size/spacing. Since CROPro crops all three at
the same slice index and (x, y) origin, a mismatch can produce misaligned crops
or an IndexError.
By default the crop pipeline checks that ADC and HBV are aligned to T2W before it starts. If they are not, it stops with a clear message instead of producing misaligned crops, and points you to the two ways of fixing it:
-
Resample pipeline (recommended) — run
cropro resampleonce to write aligned copies of the whole database, then crop those.uv run cropro resample --images-root dataset/PI-CAI/images --output-root dataset/PI-CAI/images_resampled
This writes the resampled ADC/HBV files for every case into a new
dataset/PI-CAI/images_resampledfolder (named{patient}_{study}_adc.mhaand{patient}_{study}_hbv.mha). Omit--output-rootto write the aligned copies next to the originals with a_to_t2wsuffix instead. -
On-the-fly during cropping — pass
--resample_bpmri_to_t2w true. CROPro then resamples each ADC/HBV volume onto the resampled T2W grid as it loads them (no extra files written) and the alignment check is skipped. Intensity images use B-spline interpolation; the T2W reference is reused across the case.
uv run cropro --sequence_type bpMRI --resample_bpmri_to_t2w true ...
To resample everything first — including the gland/lesion masks — pass
--resample_first true. This runs an explicit pre-step that aligns T2W, ADC, HBV
and the segmentation masks onto the same T2W grid before any cropping starts, so
the crop coordinates are guaranteed to match across every image. It implies
--resample_bpmri_to_t2w:
uv run cropro --sequence_type bpMRI --resample_first true ...
Intensity normalization
Normalization is configured per sequence: T2W, ADC and HBV each name a
strategy from the registry in
cropro.cropping.normalizers
(percentile, autoref, gaussian, zscore_clip). The defaults are
t2w_normalization_method=autoref, adc_normalization_method=percentile and
hbv_normalization_method=percentile.
By default (do_normalization=False) crops are saved with their raw
intensities, which is the safest choice for quantitative sequences such as ADC.
When do_normalization=True, each sequence's configured strategy selects how its
intensities are scaled. A good general recipe is zscore_clip, which clips each
sequence to its [min_percentile, max_percentile] percentiles and then applies
instance-wise z-score normalization, independently for T2W, ADC and HBV. The
defaults min_percentile=0.5 and max_percentile=99.5 match the
picai_baseline U-Net recipe:
uv run cropro --do_normalization true \
--t2w_normalization_method zscore_clip \
--adc_normalization_method zscore_clip \
--hbv_normalization_method zscore_clip \
--min_percentile 0.5 --max_percentile 99.5 ...
Per-modality normalization
Different sequences benefit from different normalization. T2W has no fixed
quantitative meaning and works well with autoref (AutoRef fat/muscle reference
normalization, via pyAutoRef)
or gaussian, while ADC and HBV are better kept on a robust percentile window —
which is exactly the default configuration. Override any sequence to mix methods
in a single run:
uv run cropro --do_normalization true \
--t2w_normalization_method autoref \
--adc_normalization_method percentile \
--hbv_normalization_method percentile ...
autoref is only valid for T2W (it detects fat/muscle reference tissue in the
T2W volume); setting it for ADC or HBV raises a configuration error. AutoRef runs
once over the full T2W volume and the derived scaling is reused for every crop.
To add a new normalization method, write a Normalizer subclass in
normalizers.py and decorate it with
@register_normalizer; it becomes selectable by name with no changes to the
file-writing code.
Project Structure
CROPro/
src/cropro/ # Python package
cropping/ # Cropping implementation
cli.py # Command-line interface
config.py # CropConfig dataclass
core.py # CROPro runner
examples/ # Runnable examples
tests/ # Tests
config/ # Runtime configuration
assets/readme/ # README images
scripts/ # Dataset and example scripts
pyproject.toml # Package metadata and tooling config
uv.lock # Locked development environment
Development
Install development dependencies:
uv sync --extra dev
Run checks:
uv run ruff check .
uv run pytest
uv run python -m compileall src main.py examples tests
uv build --no-sources
Before publishing, make sure the package name and version in pyproject.toml are correct. After publication, verify installation in a fresh project:
uv init cropro-smoke-test
cd cropro-smoke-test
uv add cropro
uv run python -c "from cropro import CROPro, CropConfig; print(CropConfig().crop_method)"
For publishing, prefer PyPI Trusted Publishing from CI. If publishing manually, use a scoped PyPI token and avoid storing it in shell history or repository files.
Troubleshooting
ModuleNotFoundError: No module named 'cropro'
Install the package from the repository root:
uv sync
Then run commands with uv run.
ModuleNotFoundError: No module named 'SimpleITK'
Install dependencies:
uv sync
No crops are saved
Check that:
patient_statusmatches the case.seg_img_pathpoints to a non-empty prostate mask.- Positive cases include
seg_img_path_lesion, or setprostate_gland_seg_contains_lesion=Trueif lesion labels are inside the gland mask. tumor_label_levelmatches the lesion label value in the mask.crop_image_size,pixel_spacing, andc_min_positiveare not too restrictive.- T2W, ADC, HBV, gland mask, and lesion mask are spatially aligned.
PI-CAI download is interrupted
Run the downloader again. It resumes partial archives:
bash scripts/download_dataset.sh
Citation
If you use CROPro, please cite:
@article{10.1117/1.JMI.10.2.024004,
author = {Alexandros Patsanis and Mohammed R. S. Sunoqrot and Tone F. Bathen and Mattijs Elschot},
title = {{CROPro: a tool for automated cropping of prostate magnetic resonance images}},
volume = {10},
journal = {Journal of Medical Imaging},
number = {2},
publisher = {SPIE},
pages = {024004},
year = {2023},
doi = {10.1117/1.JMI.10.2.024004},
url = {https://doi.org/10.1117/1.JMI.10.2.024004}
}
License
CROPro is distributed under the MIT License. See LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cropro-0.1.4.tar.gz.
File metadata
- Download URL: cropro-0.1.4.tar.gz
- Upload date:
- Size: 56.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6116b3bd4652ee97c4f055b950d13ea62ca2edca274d91b27246f6649d896d10
|
|
| MD5 |
e8d0a0eb34c5372f5e70557d9fe22304
|
|
| BLAKE2b-256 |
ea38ffca7d6f372a6f3de682820aec60acb9828c6998b68f420553696f2c02c2
|
Provenance
The following attestation bundles were made for cropro-0.1.4.tar.gz:
Publisher:
pypi-publish.yml on alexofficial/CROPro
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cropro-0.1.4.tar.gz -
Subject digest:
6116b3bd4652ee97c4f055b950d13ea62ca2edca274d91b27246f6649d896d10 - Sigstore transparency entry: 1758239773
- Sigstore integration time:
-
Permalink:
alexofficial/CROPro@36435980d93a01bc8a805167217ad17d3db61cb1 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/alexofficial
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@36435980d93a01bc8a805167217ad17d3db61cb1 -
Trigger Event:
release
-
Statement type:
File details
Details for the file cropro-0.1.4-py3-none-any.whl.
File metadata
- Download URL: cropro-0.1.4-py3-none-any.whl
- Upload date:
- Size: 48.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
98d5836acef9134095813bf0edbe00fa49bb2fc6010b9c77deaf12827e2aa543
|
|
| MD5 |
bd2c645da0f8c6c161a8d7209fc443e5
|
|
| BLAKE2b-256 |
39a2d8088d006692cc7c4e2f199d16169621cf2b0011cedcf4f84253a3aa16f1
|
Provenance
The following attestation bundles were made for cropro-0.1.4-py3-none-any.whl:
Publisher:
pypi-publish.yml on alexofficial/CROPro
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cropro-0.1.4-py3-none-any.whl -
Subject digest:
98d5836acef9134095813bf0edbe00fa49bb2fc6010b9c77deaf12827e2aa543 - Sigstore transparency entry: 1758239913
- Sigstore integration time:
-
Permalink:
alexofficial/CROPro@36435980d93a01bc8a805167217ad17d3db61cb1 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/alexofficial
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@36435980d93a01bc8a805167217ad17d3db61cb1 -
Trigger Event:
release
-
Statement type: