Skip to main content

Precision AI Logo

PAI AgriStress Utils

Dataset utilities for AgriStress-500 — download the dataset from HuggingFace, look up image and instance metadata, and assemble ready-to-POST payloads for the agrieval embedding evaluator.

PyPI Python License


Installation

python -m venv .venv && source .venv/bin/activate  # Windows: .venv\Scripts\activate

pip install precisionai-agristress-utils

# Full development (tests, pre-commit, type checking)
pip install -e ".[dev]"

Quick start

from precisionai.agristress.utils import AgriStressDataset, download_dataset

download_dataset("/path/to/agristress", repo_id="precisionaiinc/AgriStress-500")
ds = AgriStressDataset("/path/to/agristress")

See examples/ for complete walkthroughs of all three evaluator routes and dataset validation.


Downloading the dataset

from precisionai.agristress.utils import download_dataset

download_dataset("/path/to/agristress", repo_id="precisionaiinc/AgriStress-500")

Single-shot only — partial downloads are not supported. The internal/ directory is always excluded. Returns the resolved local Path.

After downloading, the directory layout is:

/path/to/agristress/
  images/          # source images, one subdirectory per L2 cluster
  instances/       # instance crops, one subdirectory per annotated cluster
  image2image.json
  plant2image.json
  plant2plant.json
  README.md

Pass that directory directly to AgriStressDataset:

ds = AgriStressDataset("/path/to/agristress")

Enumeration and filtering

Before embedding images you need to know what IDs exist. All IDs are relative paths that match the dataset layout exactly (e.g. "images/A1/pai-FvearqMK.png").

# All clusters, images, and instances
clusters      = ds.list_clusters()                        # sorted list of L2 cluster names
all_images    = ds.list_image_ids()                       # all image paths
all_instances = ds.list_instance_ids()                    # all instance paths

# Narrow by cluster or label
a1_images     = ds.list_image_ids(cluster="A1")
soy_instances = ds.list_instance_ids(label="Crop | Soybean")

# Filter by cluster attributes — scalar or list values
drone_images  = ds.filter_images_by_attribute(camera_source="drone")
noon_drone    = ds.filter_images_by_attribute(camera_source="drone", time_period="noon")
soy_clusters  = ds.filter_images_by_attribute(plants="Crop | Soybean")

Path resolution

Map relative IDs to absolute file paths so you can open them with your image loader:

paths = ds.resolve_paths(ds.list_image_ids(cluster="A1"))
# {"images/A1/pai-FvearqMK.png": Path("/path/to/agristress/images/A1/pai-FvearqMK.png"), ...}

from PIL import Image
for abs_path in paths.values():
    img = Image.open(abs_path)
    # … run embedding model

Both image and instance IDs are accepted. The returned paths are resolved but not checked for existence.


Embedding utilities

The agrieval evaluator requires every vector to be L2-normalized (‖v‖₂ = 1.0 ± 1e-3). Use these utilities to normalize and validate before building payloads:

from precisionai.agristress.utils import normalize_embeddings, validate_embeddings

# Normalize raw model output
raw = {"images/A1/pai-FvearqMK.png": model.encode(...)}  # unnormalized
normed = normalize_embeddings(raw)                        # returns new dict, does not mutate

# Validate before posting (raises ValueError if any vector deviates)
validate_embeddings(normed)

normalize_embeddings raises ValueError for zero vectors. validate_embeddings raises ValueError with the offending path and its actual norm if any vector fails the check.


Metadata lookups

IDs are relative paths matching the dataset layout (e.g. "images/A1/pai-FvearqMK.png").

Image metadata

records = ds.image_metadata([
    "images/A1/pai-FvearqMK.png",
    "images/A1/pai-XYZ123.png",
])
for r in records:
    print(r.image_id, r.cluster, r.attributes.plants, r.instances)

Optionally attach embeddings. Embeddings are all-or-nothing — every requested ID must have an entry in the dict, or ValueError is raised:

embeddings = {
    "images/A1/pai-FvearqMK.png": [...],
    "images/A1/pai-XYZ123.png":   [...],
}
records = ds.image_metadata(list(embeddings), embeddings=embeddings)
print(records[0].embedding)   # [...] populated

Instance metadata

records = ds.instance_metadata([
    "instances/A1/pai-FvearqMK-1.png",
])
for r in records:
    print(r.instance_id, r.label, r.parent_image)

Retrieval payload builders

Assemble the exact request body expected by agrieval. All embedding vectors must be L2-normalized flat list[float].

Method Evaluator endpoint
build_i2i_payload(embeddings) POST /v1/embeddings/evaluate/image2image
build_p2i_payload(embeddings) POST /v1/embeddings/evaluate/plant2image
build_p2p_payload(embeddings) POST /v1/embeddings/evaluate/plant2plant
# Image → Image
i2i = ds.build_i2i_payload(image_embeddings, k_values=[5, 10, 20])

# Plant → Image  (embeddings must include BOTH image and instance paths)
p2i = ds.build_p2i_payload(combined_embeddings)

# Plant → Plant  (instance paths only)
p2p = ds.build_p2p_payload(instance_embeddings, sample_pairs=None)

Embedding keys not present in the dataset manifests are ignored. Clusters or instance groups with no matching embedding are dropped from the payload automatically.


Project layout

precisionai/agristress/utils/
  dataset/
    download.py      # HuggingFace single-shot download
    loader.py        # AgriStressDataset — metadata lookups + payload builders
  schemas/
    dataset.py       # ImageRecord, InstanceRecord, ImageAttributes  (Pydantic)
    retrieval.py     # I2IPayload, P2IPayload, P2PPayload  (TypedDicts)
docs/                # Sphinx (HTML + LaTeX/PDF)
tests/               # Mirrors package structure
examples/            # Standalone runnable scripts

Development

See CONTRIBUTING.md for setup, branching, and PR guidelines, and CODE_OF_CONDUCT.md for community expectations. CLAUDE.md documents the code style and conventions enforced in this repo.

# Run all tests with coverage report
python -m pytest

# Run a specific file
pytest tests/test_loader.py

# Run pre-commit hooks manually
pre-commit run --all-files

License

Licensed under the Apache License, Version 2.0. See LICENSE.md.

See CHANGELOG.md for release history.

Metadata

Release files for precisionai-agristress-utils 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for precisionai-agristress-utils 1.0.1
File Size Uploaded
precisionai_agristress_utils-1.0.1.tar.gz 73.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for precisionai-agristress-utils 1.0.1
File Interpreter ABI Platform
precisionai_agristress_utils-1.0.1-py3-none-any.whl Python 3 none any Details

Total release size: 97.5 kB

Release files / precisionai_agristress_utils-1.0.1.tar.gz

Download URL precisionai_agristress_utils-1.0.1.tar.gz
Size 73.2 kB
Tags Source
SHA-256 checksum
How to use checksums
24fcac817a1c9c6b345ea8bbf8ed00e6837a9dd08e582bfcee48b03e5514b59c
BLAKE2b-256 checksum
How to use checksums
e8821a8bad59601ee98803899017b98cd79408e479bf28ae4aa934d7a99e852b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 9, 2026.

Transparency log

Release files / precisionai_agristress_utils-1.0.1-py3-none-any.whl

Download URL precisionai_agristress_utils-1.0.1-py3-none-any.whl
Size 24.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3ab7552eca07141833879b64ce814610ccb0869e7ba5aa8da45b60593dbfa0ce
BLAKE2b-256 checksum
How to use checksums
26606f765a72c2426bc0ea9ec60ffe08c64f3c22d1d13b1c9187873b0c201c51
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 9, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page