get_provenance
- get_provenance(random_state=None, data=None)[source]
Obtain a provenance record describing how a run can be reproduced.
Opt-in and side-effect free: nothing in AAanalysis attaches this record to its output, and no return type changes. Call it next to a run and keep the record with the results.
The one field external code cannot easily recover is the effective resolved seed:
random_stateis resolved here through the very same check the tools use, so the record reports the seed that actually takes effect, including whenoptions['random_state']overrides the value passed in.Added in version 1.1.0.
- Parameters:
random_state (int, optional) – Seed as it would be passed to a tool (its constructor
random_stateor a per-callseed). Resolved through the globaloptions['random_state']override, so the recorded value is the one that takes effect.Nonemeans no seed is in effect (stochastic steps vary between runs).data (array-like, pd.DataFrame, or pd.Series, optional) – Input to fingerprint (e.g.
df_seq,X, orlabels). When given, a stablesha256digest is recorded so a later run can confirm it used the same input. WhenNone,input_hashisNone.
- Returns:
dict_provenance – JSON-serializable record with the following keys:
aaanalysis_version: the installed package version.python_version: the running interpreter version.dependencies:{name: version}for the dependencies whose version can change a computed result (Nonefor any not installed).git_commit: commit of the package checkout, orNonefor a regular (non-source) install.random_state: the effective resolved seed, orNone.deterministic:Truewhen an effective seed is in force, so every stochastic step is reproducible;Falsewhen no seed is in effect. A tool that uses no randomness is reproducible either way.input_hash:sha256:<hex>overdata, orNone.
- Return type:
Notes
The record deliberately carries no timestamp or hostname: every field is something that can change a result, which is what makes two records comparable for equality as a reproducibility key.
Examples
The
get_provenancefunction returns a plain, JSON-serializabledictrecording how a run can be reproduced. It is opt-in: no AAanalysis function attaches it to its output and no return type changes, so results stay plain numpy and pandas. You call it next to a run and keep the record with the results.The one field external code cannot easily recover is the effective resolved seed — the seed that actually takes effect after the
options['random_state']→ constructor → per-call resolution.import json import aaanalysis as aa aa.options["verbose"] = False # 'random_state' is resolved through the same check the tools use, so the record # reports the seed that actually takes effect. provenance = aa.get_provenance(random_state=42) print(json.dumps(provenance, indent=2))
{ "aaanalysis_version": "1.0.3", "python_version": "3.14.0", "dependencies": { "numpy": "2.4.6", "pandas": "3.0.3", "scikit-learn": "1.8.0", "scipy": "1.17.1" }, "git_commit": "c58533da287242645e419ee9c3679e71051e1f05", "random_state": 42, "deterministic": true, "input_hash": null }
Every value is JSON-native, so the record round-trips through
json.dumpsand can be written to disk next to the results it describes.deterministicsays whether a seed is in force: with one, every stochastic step is reproducible; without one (random_state=None), stochastic steps vary between runs.print("round-trips through JSON:", json.loads(json.dumps(provenance)) == provenance) # Without a seed the run is stochastic, and the record says so. unseeded = aa.get_provenance() print("random_state:", unseeded["random_state"], "| deterministic:", unseeded["deterministic"])
round-trips through JSON: True random_state: None | deterministic: False
Pass the run’s input to
datato fingerprint it. A stablesha256digest is recorded, so a later run can confirm it started from the same input.dataaccepts aDataFrame,Series, array, or list — e.g.df_seq, the feature matrixX, orlabels.df_seq = aa.load_dataset(name="DOM_GSEC", n=5) aa.display_df(df=df_seq, n_rows=10, show_shape=True)
DataFrame shape: (10, 9)
entry gene sequence label tmd_start tmd_stop jmd_n tmd jmd_c 1 Q14802 FXYD3 MQKVTLGLLVFLAGF...PGETPPLITPGSAQS 0 37 59 NSPFYYDWHS LQVGGLICAGVLCAMGIIIVMSA KCKCKFGQKS 2 Q86UE4 MTDH MAARSWQDELAQQAE...SPKQIKKKKKARRET 0 50 72 LGLEPKRYPG WVILVGTGALGLLLLFLLGYGWA AACAGARKKR 3 Q969W9 PMEPA1 MHRLMGVNSTAAAAA...AIWSKEKDKQKGHPL 0 41 63 FQSMEITELE FVQIIIIVVVMMVMVVVITCLLS HYKLSARSFI 4 P53801 PTTG1IP MAPGVARGPTPYWRL...GLFKEENPYARFENN 0 97 119 RWGVCWVNFE ALIITMSVVGGTLLLGIAICCCC CCRRKRSRKP 5 Q8IUW5 RELL1 MAPRALPGSAVLAAA...EVPATPVKRERSGTE 0 59 81 NDTGNGHPEY IAYALVPVFFIMGLFGVLICHLL KKKGYRCTTE 6 P05067 APP MLPGLALLLLAAWTA...GYENPTYKFFEQMQN 1 701 723 FAEDVGSNKG AIIGLMVGGVVIATVIVITLVML KKKQYTSIHH 7 P14925 Pam MAGRARSGLLLLLLG...EEEYSAPLPKPAPSS 1 868 890 KLSTEPGSGV SVVLITTLLVIPVLVLLAIVMFI RWKKSRAFGD 8 P70180 Npr3 MRSLLLFTFSACVLL...RELREDSIRSHFSVA 1 477 499 PCKSSGGLEE SAVTGIVVGALLGAGLLMAFYFF RKKYRITIER 9 Q03157 Aplp1 MGPTSPAARGQGRRW...HGYENPTYRFLEERP 1 585 607 APSGTGVSRE ALSGLLIMGAGGGSLIVLSLLLL RKKKPYGTIS 10 Q06481 APLP2 MAATGTAAAAATGRL...GYENPTYKYLEQMQI 1 694 716 LREDFSLSSS ALIGLLVIAVAIATVIVISLVML RKRQYGTISH provenance = aa.get_provenance(random_state=42, data=df_seq) print("input_hash:", provenance["input_hash"]) # The digest tracks the input: a changed value gives a different hash. df_changed = df_seq.copy() df_changed.loc[0, "sequence"] = "MKV" print("changed :", aa.get_provenance(data=df_changed)["input_hash"])
input_hash: sha256:e9c8bdb622b17284b97cc352362556f4866e6b50d6042ac79a38dcf70e46f034 changed : sha256:f620d7700c551e06f05907c1f56cbb329845a487c517e3200abae8119a729f08
This is why the record is worth keeping.
options['random_state']overrides everything, including a seed passed explicitly at the call site. The record reports the seed that actually took effect, which the call site alone does not tell you.aa.options["random_state"] = 7 print("passed random_state=42, but options wins ->", aa.get_provenance(random_state=42)["random_state"]) aa.options["random_state"] = "off" print("options back off, argument applies ->", aa.get_provenance(random_state=42)["random_state"])
passed random_state=42, but options wins -> 7 options back off, argument applies -> 42
Record it next to any seeded run — pass the tool the same
random_stateand its input todata— and store the dict with your results (e.g.json.dump). Two runs that agree on the record reproduce the same output. The record deliberately carries no timestamp or hostname: every field is something that can change a result, which is what makes two records comparable.