Skip to content

Publish a dataset and fetch inputs by DOI/PID

This guide covers the two ends of the reproducibility loop: publishing a consolidated analysis to a DOI-minting repository (Zenodo or HydroShare), and fetching a case study's heavy inputs back by DOI/PID. Both are opt-in — publishing is never triggered by analysis.run() or submit_workflow().

Before you publish

analysis.publish() deposits the analysis-directory set — the consolidated analysis_datatree.zarr, the co-located ro-crate-metadata.json provenance sidecar, and the two configs (cfg_analysis.yaml + cfg_system.yaml). So the analysis must already be consolidated (run through reprocess(start_with="consolidate") or a full run()), or publish has nothing to deposit and no crate to read the license from.

The dataset license is read back from the crate sidecar — it is baked in at consolidation (default CC0-1.0; set analysis_config.dataset_license: CC-BY-NC-4.0 before consolidating to choose the other vocab entry). Publishing does not re-stamp the archived license.

Provide credentials (environment variables)

Live deposits require host credentials, supplied via environment variables so they never land in a config file:

# Zenodo (or the sandbox: set HHEMT_ZENODO_BASE_URL=https://sandbox.zenodo.org)
export HHEMT_ZENODO_TOKEN=<your-zenodo-personal-access-token>

# HydroShare
export HHEMT_HYDROSHARE_USERNAME=<your-hydroshare-username>
export HHEMT_HYDROSHARE_PASSWORD=<your-hydroshare-password>

Publish to Zenodo

Zenodo mints the DOI programmatically (reserve-DOI → deposit → publish):

result = analysis.publish(
    target="zenodo",
    software_doi="10.5281/zenodo.SOFTWARE",   # optional: links data -> software (IsCompiledBy)
)
print(result["data_doi"], result["record_url"])
# {"target": "zenodo", "data_doi": ..., "software_doi": ..., "record_url": ...}

software_doi is optional; when given, the deposit records a DataCite IsCompiledBy relatedIdentifier (data → the software that produced it) and backfills the reciprocal edge onto the software record.

To assert (not re-stamp) the license you expect, pass override_dataset_license. If it disagrees with the license baked into the crate, publish raises PublishError and directs you to set analysis_config.dataset_license and re-consolidate — it will not silently publish a mismatched license:

analysis.publish(target="zenodo", override_dataset_license="CC0-1.0")

Publish to HydroShare

HydroShare is a two-step flow — hsclient (v1.1.6) has no programmatic DOI mint. publish() creates the resource, uploads the deposit set, sets it public, then stops and returns a manual instruction:

result = analysis.publish(target="hydroshare")
print(result["manual_step"])   # open result["record_url"] and use 'Publish' in the web UI

Open result["record_url"], click Publish in the HydroShare web UI to mint the DOI, then re-run publish with the minted software_doi if you want the reciprocal edge.

Publish a sensitivity analysis

A sensitivity analysis deposits its master tree the same way:

sensitivity.publish(target="zenodo")   # deposits sensitivity_datatree.zarr + master sidecar

Fetch a case study's inputs by DOI/PID

A case study's case.yaml is a provenance descriptor of remote heavy inputs. Point it at a durable deposit with host + doi (or pid):

# test_data/<case_name>/case.yaml
case_name: norfolk_coastal_flooding
res_identifier: <32-hex-hydroshare-resource-id>
host: zenodo                       # or: hydroshare
doi: '10.5281/zenodo.1234567'      # host='zenodo' requires a doi OR pid

Then load the case study — the toolkit dispatches on host, fetches over anonymous-first HTTPS, and verifies every file against the manifest sha256 map:

from hhemt.examples import TRITON_SWMM_example

example = TRITON_SWMM_example.from_case_study(
    case_name="norfolk_coastal_flooding",
    download_if_exists=False,   # set True to re-download even if the data is already local
)

The fetch is host-agnostic on verification: the streaming 1 MiB-chunk sha256 check is byte-identical regardless of host, and Globus (when used) stays transport-only.