How to Define Spatial Data Provenance Models

Part of: Provenance Models for Spatial Data

To define spatial data provenance models, construct a directed acyclic graph (DAG) that explicitly links geospatial entities, transformation activities, and responsible agents while capturing spatial-specific metadata such as coordinate reference systems (CRS), geometry types, spatial resolution, and topology constraints. The process requires aligning your lineage schema with the W3C PROV-O standard and extending it with ISO 19115 spatial attributes, then instrumenting your ETL or GIS processing pipelines to emit machine-readable provenance records at every transformation step. This architecture ensures full auditability, supports regulatory compliance, and enables reproducible spatial analytics across government and enterprise environments.

For teams establishing baseline data governance, reviewing Geospatial Lineage Fundamentals & Architecture before implementation will clarify how spatial lineage integrates with broader enterprise metadata catalogs.

Core Components of a Spatial Provenance Model

A functional spatial provenance model tracks four interconnected dimensions that differentiate it from generic tabular data lineage:

  1. Entities: Source and derived datasets, raster tiles, vector layers, spatial indexes, and cached map services. Each entity requires persistent identifiers (URIs or UUIDs) and mandatory spatial descriptors: CRS, bounding box, feature count, geometry type, and spatial resolution.
  2. Activities: Geoprocessing operations such as projection transformations, spatial joins, clipping, buffering, raster resampling, or topology validation. Activities must record input/output entities, execution timestamps, algorithm parameters, and spatial tolerance thresholds.
  3. Agents: Human analysts, automated Python scripts, GIS desktop applications (QGIS, ArcGIS Pro), or cloud processing services (AWS Location, Google Earth Engine). Agents are linked to activities via prov:wasAssociatedWith or prov:actedOnBehalfOf relationships.
  4. Spatial Context: Unlike tabular data, spatial models must explicitly capture CRS transformations, datum shifts, coordinate precision loss, and topology rule violations. These attributes directly impact analytical validity, cartographic accuracy, and compliance reporting.

When mapping these relationships, align your taxonomy with established patterns in Provenance Models for Spatial Data to prevent schema fragmentation and ensure cross-system interoperability.

The four components in one worked derivation Input entity, activity, output entity and agent for a single raster resampling, showing which spatial attributes attach to which component. Entity · input_dem crs EPSG:4326 resolution 30m geometry Grid Activity · resample algorithm bilinear tolerance 0.001 start / end time Entity · output_dem crs EPSG:32610 resolution 10m geometry Grid used wasGeneratedBy Agent · dem-etl-svc actedOnBehalfOf: terrain steward wasAssociatedWith SPATIAL ATTRIBUTES BELONG ON ENTITIES; PROCESS ATTRIBUTES ON THE ACTIVITY The CRS pair is readable from the two entities — never store it only on the activity.

The placement rule in that diagram is worth stating explicitly because it is the most common modelling error at this level. CRS, resolution and geometry type describe a dataset, so they belong on entities; algorithm, tolerance and timing describe a process, so they belong on the activity. Storing the CRS pair only as activity parameters seems economical — one record instead of two — but it makes the entity un-interpretable on its own, so any query that reaches a dataset without traversing its producing activity cannot tell what coordinate system it is in. Since half of all lineage queries arrive at entities directly, that shortcut costs more than it saves.

Step-by-Step Definition Process

1. Inventory Spatial Assets

Catalog all input datasets, intermediate outputs, and final deliverables. Extract embedded metadata from .prj, .cpg, ISO 19115 XML, or GeoPackage metadata tables using command-line utilities like ogrinfo or gdalsrsinfo. Automate extraction with Python’s osgeo or geopandas to capture bounding boxes, CRS EPSG codes, and layer geometry types at ingestion.

2. Select a Serialization Format

PROV-JSON is recommended for Python automation due to native library support (prov package) and straightforward schema validation. Use JSON-LD if you require semantic web integration, linked data publishing, or RDF triplestore storage. Avoid proprietary formats that break cross-platform lineage queries.

3. Define Spatial Extensions

Extend PROV-O with a custom namespace (e.g., spatial:) to attach geospatial attributes. Common extensions include:

  • spatial:crs (URI or EPSG code)
  • spatial:geometry_type (Point, LineString, Polygon, etc.)
  • spatial:resolution (pixel size or vertex precision)
  • spatial:tolerance (snap distance, buffer radius, or topology threshold)
  • spatial:datum_shift (boolean or transformation parameters)

4. Instrument Processing Pipelines

Embed provenance capture directly into your ETL/GIS workflows. Wrap geoprocessing functions with decorators or context managers that automatically log input entities, activity parameters, and output entities. Ensure every spatial operation emits a prov:wasGeneratedBy and prov:used relationship.

5. Validate & Store Lineage Records

Run emitted records through a PROV validator to check DAG acyclicity, required property presence, and namespace consistency. Store validated records in a graph database (Neo4j, Amazon Neptune) or a PROV-compliant metadata catalog. Index by CRS, project ID, and agent to accelerate compliance audits.

Implementation & Validation Example

Below is a minimal PROV-JSON structure demonstrating how to attach spatial metadata to a raster resampling activity:

{
  "entity": {
    "ex:input_dem": {
      "prov:type": "ex:RasterDataset",
      "spatial:crs": "EPSG:4326",
      "spatial:resolution": "30m",
      "spatial:geometry_type": "Grid"
    },
    "ex:output_dem_resampled": {
      "prov:type": "ex:RasterDataset",
      "spatial:crs": "EPSG:32610",
      "spatial:resolution": "10m",
      "spatial:geometry_type": "Grid"
    }
  },
  "activity": {
    "ex:resample_activity": {
      "prov:type": "ex:RasterResampling",
      "ex:algorithm": "bilinear",
      "ex:tolerance": "0.001",
      "prov:startTime": "2024-05-12T14:30:00Z",
      "prov:endTime": "2024-05-12T14:31:15Z"
    }
  },
  "wasGeneratedBy": {
    "ex:output_dem_resampled": { "activity": "ex:resample_activity" }
  },
  "used": {
    "ex:resample_activity": { "entity": "ex:input_dem" }
  }
}

In Python, use the prov library to generate this programmatically:

from prov.model import ProvDocument

doc = ProvDocument()
doc.add_namespace("spatial", "http://example.org/spatial/")
doc.add_namespace("ex", "http://example.org/provenance/")

input_dem = doc.entity("ex:input_dem", {
    "prov:type": "ex:RasterDataset",
    "spatial:crs": "EPSG:4326",
    "spatial:resolution": "30m"
})

resample_act = doc.activity(
    "ex:resample_activity",
    "2024-05-12T14:30:00Z",
    "2024-05-12T14:31:15Z",
    {"ex:algorithm": "bilinear", "spatial:tolerance": "0.001"}
)

output_dem = doc.entity("ex:output_dem_resampled", {
    "prov:type": "ex:RasterDataset",
    "spatial:crs": "EPSG:32610",
    "spatial:resolution": "10m"
})

doc.wasGeneratedBy(output_dem, resample_act)
doc.used(resample_act, input_dem)

print(doc.serialize(format="json"))

Validate output against the official PROV schema using prov.model.ProvDocument.is_valid() or the W3C PROV-JSON validator before committing to production storage.

Verification

Schema validity is necessary and not sufficient — a document can be perfectly well-formed PROV and still describe nothing useful. Run these four checks after every emission, in order of how cheaply they fail.

Four verification checks, cheapest first A left-to-right sequence of four checks with the specific defect each one catches, ending in the CRS chain check that only spatial provenance requires. 1 · Schema valid is_valid() 2 · Acyclic no derivation loop 3 · Reachable no orphan entity 4 · CRS chain continuous CATCHES missing namespace, wrong property type CATCHES two pipelines each feeding the other CATCHES an output nothing claims to produce CATCHES an unlogged reprojection Only check 4 is spatial — and it is the one no generic PROV validator performs.

Check four is the one to write yourself, because no PROV tooling knows what a CRS is. Walk each derivation path and assert that the output CRS of one entity equals the input CRS of the next, unless an activity between them explicitly declares a reprojection. A break in that chain means a projection happened that nothing recorded — the exact failure that makes a lineage record unfalsifiable, since the geometry no longer means what the earliest record says it means.

Run all four in CI against a fixture document that is deliberately broken in each of the four ways, and confirm each check rejects its own case. A validator suite that has never rejected anything is not evidence that emissions are clean; it may simply be asserting conditions that cannot fail.

Compliance & Operational Considerations

Government and enterprise GIS teams must ensure provenance records survive data migrations, format conversions, and cloud deployments. Implement the following controls:

  • CRS Chain Tracking: Record every projection change. Unlogged datum shifts are a primary cause of spatial misalignment in multi-agency data sharing.
  • Precision Auditing: Log coordinate precision loss during vector generalization or raster downscaling. Attach spatial:precision_loss metrics to activities that modify geometry fidelity.
  • Agent Attribution: Map automated scripts to organizational roles using prov:wasAttributedTo. This satisfies audit requirements for regulated environments (e.g., FEMA flood mapping, EPA watershed modeling).
  • Immutable Storage: Write provenance records to append-only logs or write-once object storage when regulatory frameworks require tamper-evident lineage trails.

By standardizing spatial extensions, automating pipeline instrumentation, and enforcing PROV-O compliance, organizations transform opaque geoprocessing workflows into transparent, queryable lineage graphs. This foundation enables rapid impact analysis, reproducible spatial modeling, and defensible compliance reporting across complex geospatial ecosystems.

Gotchas & Edge Cases

Three edge cases that break a naive model Each row pairs a situation that a simple entity-activity-entity model handles badly with the modelling adjustment that resolves it. SITUATION RESOLUTION Mosaic from 400 tiles 400 used edges on one activity Keep all 400 edges — do not summarise Generate the prose statement at publish time In-place edit overwrites source entity appears to derive from itself Two entities, one URI, distinct versions The digest is what makes them different things PROJ datum grid absent at runtime silent fallback to a coarser transform Record the resolved pipeline string, not the request What PROJ chose ≠ what you asked for

The third row is the one that silently corrupts otherwise careful models. pyproj will happily perform a transformation using a lower-accuracy fallback when the preferred datum grid is not installed, and unless you interrogate the resolved transformer, your record says you requested a high-accuracy pipeline while the coordinates reflect something else. Capture transformer.description or the resolved pipeline string after construction — the value PROJ actually selected — rather than the parameters you passed in.

The second row matters for any workflow with an editing step. When a dataset is edited in place, the pre-edit and post-edit states are two different entities that happen to share a filesystem path, and modelling them as one produces a self-referential edge that fails the acyclicity check. Give each state its own identifier derived from its digest, and let the shared URI be an attribute rather than the identity. This also solves a question that otherwise has no good answer: which version of the file a downstream product consumed. With digest-derived identifiers the answer is recorded rather than inferred, and a later edit cannot retroactively change what an earlier analysis is documented as having used.

The first row is worth resisting the temptation on. Four hundred used edges look excessive next to a one-line prose summary, and every team that collapses them regrets it the first time a single bad tile has to be traced to the products it contaminated. Edges are cheap, they are exactly what impact analysis traverses, and the readable summary can always be generated from them; the reverse derivation is impossible.