Skip to main content

difi

Did I Find It?

Rust CI PyPI crates.io docs.rs Coverage Status License DOI
Built with Claude Code Asteroid Institute DIRAC Institute


difi evaluates the completeness and purity of astronomical object linkage results from software such as THOR, HelioLinC, or MOPS. Given observations with known object associations and a set of predicted linkages, difi determines which objects were successfully discovered and how clean each linkage is.

This is difi v2 — a ground-up rewrite in Rust with Python bindings. It uses Rayon for parallelism and Apache Arrow for zero-copy data interchange.

Installation

Python (recommended)

Requires Python 3.10+ and a Rust toolchain (1.85+).

pip install maturin
git clone https://github.com/moeyensj/difi.git && cd difi
maturin develop --release

Verify:

>>> import difi
>>> difi.__version__  # matches the published rc

Rust only

cargo build --release

CLI

The difi binary ships with the crate behind a cli Cargo feature (so library consumers don't pull clap/toml/anyhow transitively):

cargo install difi-rs --features cli
# or from a checkout
cargo build --release --features cli   # binary: ./target/release/difi

Input format

difi requires two input tables:

Observations

Each row is a single detection with an optional ground-truth object label.

Column Type Nullable Description
id string no Unique observation identifier
time struct{days: i64, nanos: i64} no Epoch as MJD days + nanoseconds
ra f64 no Right ascension (degrees, 0-360)
dec f64 no Declination (degrees, -90 to 90)
ra_sigma f64 yes RA uncertainty (degrees)
dec_sigma f64 yes Dec uncertainty (degrees)
observatory_code string no Observatory/telescope identifier
object_id string yes Ground-truth object label (null if unknown)
night i64 no Local observing night identifier

Linkage members

Each row maps a predicted linkage to one of its constituent observations.

Column Type Nullable Description
linkage_id string no Linkage identifier
obs_id string no Observation identifier (foreign key to observations.id)

Both tables are read from Parquet files or passed as quivr/PyArrow objects.

Usage

Python

Each function accepts either a file path (str/Path) or a quivr Table object.

from difi import analyze_observations, analyze_linkages

# Step 1: CIFI — determine which objects are findable
# Pass file paths...
cifi_result = analyze_observations("observations.parquet")

# ...or quivr Tables
from difi import Observations
observations = Observations.from_parquet("observations.parquet")
cifi_result = analyze_observations(observations)

# Step 2: DIFI — classify linkages and compute completeness
difi_result = analyze_linkages(
    "observations.parquet",
    "linkage_members.parquet",
    min_obs=6,
    contamination_percentage=20.0,
)
print(f"Completeness: {difi_result['completeness']:.1f}%")
print(f"Pure: {difi_result['num_pure']}, Mixed: {difi_result['num_mixed']}")
# num_ignored_linkages counts linkages excluded because they had no
# observations inside the analysis partition (non-zero signals a mismatch
# between your --linkages file and the observation set).
print(f"Ignored: {difi_result['num_ignored_linkages']}")

Findability metrics

The metric parameter controls what observation pattern makes an object "findable":

from difi import analyze_observations

# Singleton metric (default): object needs >= min_obs detections
# across >= min_nights distinct nights
result = analyze_observations(
    "observations.parquet",
    metric="singletons",
    min_obs=6,
    min_nights=3,
)

# Tracklet metric: object needs intra-night tracklets (multiple
# detections within max_obs_separation hours showing angular motion)
# on >= min_nights distinct nights
result = analyze_observations(
    "observations.parquet",
    metric="tracklets",
    min_nights=3,
)

In Rust, metrics are structs with full configuration:

use difi::metrics::singleton::SingletonMetric;
use difi::metrics::tracklet::TrackletMetric;

// Singleton: 6 obs across 3 nights, at least 2 obs/night when exactly 3 nights
let singleton = SingletonMetric {
    min_obs: 6,
    min_nights: 3,
    min_nightly_obs_in_min_nights: 2,
};

// Tracklet: 2+ obs per tracklet within 1.5 hours, 1" angular separation,
// tracklets on 3+ nights
let tracklet = TrackletMetric {
    tracklet_min_obs: 2,
    max_obs_separation: 1.5 / 24.0,  // days
    min_linkage_nights: 3,
    min_obs_angular_separation: 1.0,  // arcseconds
};

CLI

A thin wrapper over the library, for shell pipelines and reproducible runs. Subcommand names mirror the Python verbs; short aliases keep shell use ergonomic.

# CIFI: findability from observations  (alias: `difi cifi`)
difi analyze-observations \
    -i observations.parquet \
    -o out/ \
    --metric singletons --min-obs 6 --min-nights 3

# CIFI + DIFI: classify linkages end-to-end  (alias: `difi analyze`)
difi analyze-linkages \
    -i observations.parquet \
    -l linkage_members.parquet \
    -o out/ \
    --contamination-percentage 20

Outputs in <output-dir>/:

File Written by Contents
all_objects.parquet both One row per (object, partition) — CIFI findability flag plus DIFI linkage stats merged in
findable_observations.parquet both One row per findable (object, partition) with discovery night
partition_summaries.parquet both One row per partition with observation / findable / found / completeness counts
all_linkages.parquet analyze-linkages One row per classified (linkage, partition) with pure/contaminated/mixed flags
ignored_linkages.parquet analyze-linkages (only when non-empty) Linkages excluded from classification, with reason + partition
run_manifest.json both argv, input SHA-256 prefixes, host, per-scenario timings, warnings counts, optional reused_cifi provenance

Partitioned CIFI

# Sliding 30-night windows
difi cifi -i observations.parquet -o out/ \
    --partition-mode sliding --partition-window 30

# Tracklets with non-overlapping 15-night blocks
difi cifi -i observations.parquet -o out/ \
    --metric tracklets --min-linkage-nights 3 \
    --partition-mode blocks --partition-window 15

Partition flags also apply to analyze-linkages — the CLI loops DIFI over each partition's summary and writes a combined all_linkages.parquet keyed by partition_id. Linkages whose observations fall entirely outside a given partition are excluded from all_linkages.parquet and reported in a separate ignored_linkages.parquet; the manifest's warnings section surfaces counts so a run with an unexpectedly high orphan_linkages value (linkages that never intersect any partition) flags a likely mismatched --linkages file.

Reusing a CIFI snapshot

CIFI is the expensive phase on survey-scale inputs. Run it once, reuse across multiple linkage sets:

# Produce a reusable CIFI snapshot
difi cifi -i observations.parquet -o cifi_snapshot/

# Classify two independent linkage sets against the same CIFI work
difi analyze-linkages -i observations.parquet -l thor_linkages.parquet \
    --cifi-output-dir cifi_snapshot/ -o difi_thor/
difi analyze-linkages -i observations.parquet -l precovery_linkages.parquet \
    --cifi-output-dir cifi_snapshot/ -o difi_precovery/

--cifi-output-dir is mutually exclusive with partition flags (the snapshot encodes its own partitions). A SHA-256 prefix of the observations file is stored in each manifest; mismatches between the snapshot and the current observations fail fast with a clear error.

Batch scenarios

Declare scenarios in TOML for findability sweeps (LSST baselines, etc.):

# lsst_findability.toml
[defaults]
observations = "/path/to/observations.parquet"

[[scenario]]
name = "singleton_6obs_3nights"
metric = "singletons"
min_obs = 6
min_nights = 3

[[scenario]]
name = "tracklet_3pairs_15nights"
metric = "tracklets"
min_linkage_nights = 3
partition_mode = "sliding"
partition_window = 15
difi cifi --scenarios lsst_findability.toml -o results/
# results/<scenario>/all_objects.parquet, partition_summaries.parquet, ...
# results/run_manifest.json summarizes every scenario

Per-scenario observations = "..." overrides [defaults].

Machine-readable progress

--progress-json emits one NDJSON event per line on stdout; human text still goes to stderr.

difi --progress-json cifi -i observations.parquet -o out/ \
    | jq -c 'select(.event == "scenario_done")'

Errors always produce a human line on stderr; under --progress-json an {"event":"error", ...} line is additionally written to stdout so machine consumers see them too.

Rust

use difi::cifi::analyze_observations;
use difi::difi::analyze_linkages;
use difi::io::{read_observations, read_linkage_members};
use difi::metrics::singleton::SingletonMetric;

// Load from Parquet
let (obs, mut interner, _) = read_observations(Path::new("observations.parquet"))?;
let lm = read_linkage_members(Path::new("linkage_members.parquet"), &mut interner)?;

// Step 1: CIFI — determine findability
let metric = SingletonMetric::default();
let (mut all_objects, findable, mut summaries) =
    analyze_observations(&obs, None, &metric)?;

// Step 2: DIFI — classify linkages. Returns (AllLinkages, IgnoredLinkages).
// Linkages whose observations all fall outside summaries[0]'s night range
// are redirected to `ignored` with reason NoObservationsInPartition, instead
// of producing phantom pure/contaminated/mixed rows.
let (all_linkages, ignored) = analyze_linkages(
    &obs, &lm, &mut all_objects, &mut summaries[0], 6, 20.0,
)?;

For multi-partition DIFI, loop over summaries and concatenate each partition's AllLinkages / IgnoredLinkages. The update_all_objects call inside analyze_linkages scopes its writes to the current partition's rows in AllObjects, so multi-partition loops are safe.

Cross-crate usage (e.g. from THOR)

difi defines ObservationTable and LinkageMemberTable traits. Implement them for your own types to call difi directly without data conversion:

impl difi::types::ObservationTable for MyObservations {
    fn len(&self) -> usize { self.ids.len() }
    fn ids(&self) -> &[u64] { &self.ids }
    fn nights(&self) -> &[i64] { &self.nights }
    fn object_ids(&self) -> &[u64] { &self.object_ids }
    // ...
}

let (objects, findable, summaries) =
    difi::cifi::analyze_observations(&my_obs, None, &metric)?;

Pipeline

difi operates in two phases:

  1. CIFI (Can I Find It?) — Determines which objects are "findable" based on observation patterns. Supports two metrics:

    • SingletonMetric: >= min_obs observations across >= min_nights nights
    • TrackletMetric: intra-night tracklets with temporal and angular separation constraints
  2. DIFI (Did I Find It?) — Classifies each linkage as exactly one of:

    • Pure — all observations belong to one object
    • Pure complete — pure + contains all partition observations of that object
    • Contaminated — mostly one object, contamination <= threshold
    • Mixed — too contaminated to attribute to a single object

    Completeness = (found objects / findable objects) × 100%, where found counts objects for which at least one pure linkage contains ≥ min_obs observations inside the partition. Single-partition runs see no difference from the whole-linkage interpretation; multi-partition runs stay bounded by in-partition evidence instead of inflating when a cross-boundary linkage has enough total obs but few inside any one window.

Per-partition vs. cross-partition (survey-wide) counts

partition_summaries.parquet carries per-partition rows with the same completeness formula scoped to each window. For a sliding-window run, the same real object typically appears in many windows, so naively summing findable / found across partitions double-counts.

run_manifest.json → scenarios[0] carries both views:

Field Meaning
findable_count Sum across partitions. Useful for workload sizing
found_count Sum across partitions (DIFI runs only)
unique_findable_count Distinct objects findable in ≥ 1 partition
unique_found_count Distinct objects with ≥ 1 found-pure linkage across all partitions (DIFI runs only)
unique_completeness unique_found_count / unique_findable_count × 100 — the number to quote for "how many asteroids did the linker recover?" (DIFI runs only)

In single-partition runs the unique_* values equal the sum counterparts by construction. In multi-partition sliding-window runs they diverge: for a 76-partition survey run, findable_count can be ~200k (object, partition) pairs while unique_findable_count is ~15k distinct objects.

Performance

Benchmarked on the neomod_quads survey dataset (166M observations, 15,935 objects):

Scale Python (v2rc3) Rust (v2rc4) Speedup
55M obs (30 nights) 23.0s 0.42s 55x
111M obs (60 nights) 67.3s 0.85s 80x
166M obs (90 nights) 132.9s 1.24s 107x

Memory at 100M observations: ~3.2 GB (DIFI), ~5.6 GB (CIFI with tracklets).

Development

# Build the library
cargo build

# Build the library + CLI binary
cargo build --features cli

# Verify lib-only build pulls no CLI deps
cargo build --no-default-features

# Full test suite (library + CLI integration tests)
cargo test --features cli

# Lint
cargo clippy --all-targets --features cli -- -D warnings

# Verify Cargo.toml and pyproject.toml versions agree (CI runs this on every
# PR; the publish workflow also checks tag vs both files before any upload)
./scripts/check_versions.sh

# Benchmarks
cargo bench

# Build Python package
maturin develop --release

Acknowledgments

This work was supported by the Asteroid Institute (a program of the B612 Foundation) and the DIRAC Institute at the University of Washington.

License

BSD 3-Clause. See LICENSE.md for details.

Metadata

Release files for difi 2.0.0

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

Source distribution (sdist)

Source distribution for difi 2.0.0
File Size Uploaded
difi-2.0.0.tar.gz 121.3 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for difi 2.0.0
File
difi-2.0.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl PyPy 3.11 PyPy 3.11 7.3 Linux glibc 2.17+ x86-64 Details
difi-2.0.0-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.15 CPython 3.15 Linux glibc 2.17+ x86-64 Details
difi-2.0.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.14 CPython 3.14 Linux glibc 2.17+ x86-64 Details
difi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl CPython 3.14 CPython 3.14 macOS 11.0+ ARM64 Details
difi-2.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.17+ x86-64 Details
difi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
difi-2.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.17+ x86-64 Details
difi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details
difi-2.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.17+ x86-64 Details
difi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details
difi-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.17+ x86-64 Details

Total release size: 24.2 MB

Release files / difi-2.0.0.tar.gz

Download URL difi-2.0.0.tar.gz
Size 121.3 kB
Tags Source
SHA-256 checksum
How to use checksums
b07feba6e3b48033707b4d11041b5d836168b7131a94c01d33b577a7f6574e0b
BLAKE2b-256 checksum
How to use checksums
6eb883fe1005507fbfba3e97edccf10a84d8bc566c8ca700180a844c979c22a0
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 May 21, 2026.

Transparency log

Release files / difi-2.0.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL difi-2.0.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 2.3 MB
Tags Linux glibc 2.17+ x86-64 PyPy 3.11 PyPy 3.11 7.3
SHA-256 checksum
How to use checksums
538ec414b841855710d62bb4f52911f6df9bae05703293271c31e5f70c79b570
BLAKE2b-256 checksum
How to use checksums
aed6bec7a738a604ca102acbff2928c7d2c1d35ac4cc08ac4bc5faafe298fe6f
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 May 21, 2026.

Transparency log

Release files / difi-2.0.0-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL difi-2.0.0-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 2.3 MB
Tags CPython 3.15 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
1dc4d1fa8aa37cf52be481cc092801fb3bcf6aac4ff3fdceb204f56228d668c2
BLAKE2b-256 checksum
How to use checksums
39774e102c25cab5185cdabac551dae68417650800e77438aac646ff4e372aa3
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 May 21, 2026.

Transparency log

Release files / difi-2.0.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL difi-2.0.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 2.3 MB
Tags CPython 3.14 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
2e55269f267cdceb8814f2e2634f5733a198ab91c1c9260587763bfd3167583c
BLAKE2b-256 checksum
How to use checksums
047df95a541b5aad6dc4d61262907f4d2fc06b482aa91511e10c5dda7fddc65b
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 May 21, 2026.

Transparency log

Release files / difi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl

Download URL difi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl
Size 1.9 MB
Tags CPython 3.14 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
914785f41b0b13d899542e88140f9e88c327fff781ecf44d8aa3c6183733973c
BLAKE2b-256 checksum
How to use checksums
c01c7fb33e9a0ed79f2ec1a48a024c4ce948788a3d161007a31b3a2635acd143
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 May 21, 2026.

Transparency log

Release files / difi-2.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL difi-2.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 2.3 MB
Tags CPython 3.13 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
8b78e2e38654f4c3b6c202efc099a1962b3ef71e13c890db6a94332f0ce8536d
BLAKE2b-256 checksum
How to use checksums
c49dafb894379097eedf6b9dfdbd2c682b63f9881976fbfd3e8fa0a68932f3e4
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 May 21, 2026.

Transparency log

Release files / difi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl

Download URL difi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl
Size 1.9 MB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
f6214a728cd156252a14727d4a28af9d09bbadc3a1201e61973c5d1d87c4ea72
BLAKE2b-256 checksum
How to use checksums
328c6447cd5444e8412d4a9f8432e993bda44b2e9cf72e332d5b832ed760e0ed
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 May 21, 2026.

Transparency log

Release files / difi-2.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL difi-2.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 2.3 MB
Tags CPython 3.12 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
3fc136c3e7f40b762761918c709f9beadfa8bb7707b89ff6bdba47ffb16fd521
BLAKE2b-256 checksum
How to use checksums
3a85ef8e5ff2225d0bc8c35a05ca6954d22dc14c45543c4c929605b1e34bbe18
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 May 21, 2026.

Transparency log

Release files / difi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl

Download URL difi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl
Size 1.9 MB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
9015dc20bfaf7181428099d8d4df29cb1a85865d675918cce54984bd807576df
BLAKE2b-256 checksum
How to use checksums
4f53a5d38d1db43032591fb4c3512cfe88efa0684adc6d5cf8da378596885ad3
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 May 21, 2026.

Transparency log

Release files / difi-2.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL difi-2.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 2.3 MB
Tags CPython 3.11 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
db0517acc7d65df7c8a24bf67742cecccb5e28daf47beac27c567c583b744c16
BLAKE2b-256 checksum
How to use checksums
83a8cf8d91867bc87f0ca2d179dca84ae5bec2a55fb0fcaa2f5211368fafe6e3
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 May 21, 2026.

Transparency log

Release files / difi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl

Download URL difi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl
Size 1.9 MB
Tags CPython 3.11 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
01d035279e00488f5f151dfa274229e0c6ed3f94f8877d79b9f46f69924faf19
BLAKE2b-256 checksum
How to use checksums
09eff18cce43a8c3c6febdac31af7523610efd0ea30f25282129766037514e67
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 May 21, 2026.

Transparency log

Release files / difi-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL difi-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 2.3 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
d75efe38df1e93c54284d3e2a1b9305e9abb74e5a20cd7a7ed314f4e013a58b3
BLAKE2b-256 checksum
How to use checksums
9e88c6ee41ed7e5800434773ef072592df091d6af74e52d146f7aa89718385ae
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 May 21, 2026.

Transparency log
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