Skip to main content

Did I Find It? — Evaluate linkage completeness and purity for astronomical surveys

Project description

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.

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

difi-2.0.0.tar.gz (121.3 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

difi-2.0.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.3 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ x86-64

difi-2.0.0-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.15manylinux: glibc 2.17+ x86-64

difi-2.0.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

difi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl (1.9 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

difi-2.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

difi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl (1.9 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

difi-2.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

difi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl (1.9 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

difi-2.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

difi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl (1.9 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

difi-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

File details

Details for the file difi-2.0.0.tar.gz.

File metadata

  • Download URL: difi-2.0.0.tar.gz
  • Upload date:
  • Size: 121.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for difi-2.0.0.tar.gz
Algorithm Hash digest
SHA256 b07feba6e3b48033707b4d11041b5d836168b7131a94c01d33b577a7f6574e0b
MD5 f41235819ef7a9e5d5a0ac8503bc3bd4
BLAKE2b-256 6eb883fe1005507fbfba3e97edccf10a84d8bc566c8ca700180a844c979c22a0

See more details on using hashes here.

Provenance

The following attestation bundles were made for difi-2.0.0.tar.gz:

Publisher: publish.yml on moeyensj/difi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file difi-2.0.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for difi-2.0.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 538ec414b841855710d62bb4f52911f6df9bae05703293271c31e5f70c79b570
MD5 ebeb8a4d198867ed846e4076cfab0c28
BLAKE2b-256 aed6bec7a738a604ca102acbff2928c7d2c1d35ac4cc08ac4bc5faafe298fe6f

See more details on using hashes here.

Provenance

The following attestation bundles were made for difi-2.0.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on moeyensj/difi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file difi-2.0.0-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for difi-2.0.0-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 1dc4d1fa8aa37cf52be481cc092801fb3bcf6aac4ff3fdceb204f56228d668c2
MD5 03e1622eee40d1dc1b9c3567170971b1
BLAKE2b-256 39774e102c25cab5185cdabac551dae68417650800e77438aac646ff4e372aa3

See more details on using hashes here.

Provenance

The following attestation bundles were made for difi-2.0.0-cp315-cp315-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on moeyensj/difi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file difi-2.0.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for difi-2.0.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 2e55269f267cdceb8814f2e2634f5733a198ab91c1c9260587763bfd3167583c
MD5 6d267c9c82822234e95851b272429e50
BLAKE2b-256 047df95a541b5aad6dc4d61262907f4d2fc06b482aa91511e10c5dda7fddc65b

See more details on using hashes here.

Provenance

The following attestation bundles were made for difi-2.0.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on moeyensj/difi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file difi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for difi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 914785f41b0b13d899542e88140f9e88c327fff781ecf44d8aa3c6183733973c
MD5 5759ff7d7742a1e70337e6d8f9cf3d24
BLAKE2b-256 c01c7fb33e9a0ed79f2ec1a48a024c4ce948788a3d161007a31b3a2635acd143

See more details on using hashes here.

Provenance

The following attestation bundles were made for difi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl:

Publisher: publish.yml on moeyensj/difi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file difi-2.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for difi-2.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 8b78e2e38654f4c3b6c202efc099a1962b3ef71e13c890db6a94332f0ce8536d
MD5 ff2bfaca4172cd660293a7a7639de2c7
BLAKE2b-256 c49dafb894379097eedf6b9dfdbd2c682b63f9881976fbfd3e8fa0a68932f3e4

See more details on using hashes here.

Provenance

The following attestation bundles were made for difi-2.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on moeyensj/difi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file difi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for difi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f6214a728cd156252a14727d4a28af9d09bbadc3a1201e61973c5d1d87c4ea72
MD5 78bb2245b19b714e5fbe7006f66be04b
BLAKE2b-256 328c6447cd5444e8412d4a9f8432e993bda44b2e9cf72e332d5b832ed760e0ed

See more details on using hashes here.

Provenance

The following attestation bundles were made for difi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl:

Publisher: publish.yml on moeyensj/difi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file difi-2.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for difi-2.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3fc136c3e7f40b762761918c709f9beadfa8bb7707b89ff6bdba47ffb16fd521
MD5 b142578a28560a4507a5d32ed4f131b2
BLAKE2b-256 3a85ef8e5ff2225d0bc8c35a05ca6954d22dc14c45543c4c929605b1e34bbe18

See more details on using hashes here.

Provenance

The following attestation bundles were made for difi-2.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on moeyensj/difi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file difi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for difi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9015dc20bfaf7181428099d8d4df29cb1a85865d675918cce54984bd807576df
MD5 b0462fa98e07a449a4549b976afd9e9a
BLAKE2b-256 4f53a5d38d1db43032591fb4c3512cfe88efa0684adc6d5cf8da378596885ad3

See more details on using hashes here.

Provenance

The following attestation bundles were made for difi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: publish.yml on moeyensj/difi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file difi-2.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for difi-2.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 db0517acc7d65df7c8a24bf67742cecccb5e28daf47beac27c567c583b744c16
MD5 540824c1831ef6aad32807250b253abd
BLAKE2b-256 83a8cf8d91867bc87f0ca2d179dca84ae5bec2a55fb0fcaa2f5211368fafe6e3

See more details on using hashes here.

Provenance

The following attestation bundles were made for difi-2.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on moeyensj/difi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file difi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for difi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 01d035279e00488f5f151dfa274229e0c6ed3f94f8877d79b9f46f69924faf19
MD5 cc4cc05cee54c88b00aa214fe795ac37
BLAKE2b-256 09eff18cce43a8c3c6febdac31af7523610efd0ea30f25282129766037514e67

See more details on using hashes here.

Provenance

The following attestation bundles were made for difi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl:

Publisher: publish.yml on moeyensj/difi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file difi-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for difi-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d75efe38df1e93c54284d3e2a1b9305e9abb74e5a20cd7a7ed314f4e013a58b3
MD5 38eadff9b11afcfa2d0303bd7ff1047c
BLAKE2b-256 9e88c6ee41ed7e5800434773ef072592df091d6af74e52d146f7aa89718385ae

See more details on using hashes here.

Provenance

The following attestation bundles were made for difi-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on moeyensj/difi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page