Research workflows
Reproduce a Python analysis in a fresh project
Run a complete example twice, compare input hashes and saved results, and record the research environment.
Reproduce a small Python analysis in a new project, starting from its saved inputs and code. You will check the input bytes and numeric result, and record the software used. Reopening a notebook's old output is not this check.
Before you start
Use two projects that you can edit, with Python 3 available. This example uses
only the Python standard library. It does not require a GPU or installation of
analysis packages. Use a new research-workflow folder so existing work is not
overwritten. The commands below run in a CoCalc project terminal, not on your
laptop. See Create a project and
Use the terminal.
The complete example files
are in the public source repository. Download measurements.csv and analyze.py
using each file's Download raw file control, then upload them into the same
project folder. For scripted transfer, use
Run an analysis from your laptop.
Run the original analysis
In the project terminal, go to that folder. These examples assume the standard
project home; use pwd and adjust the path if yours differs.
cd /home/user/research-workflow
python3 --version
python3 analyze.py measurements.csv result.json
Expected output:
count=4 mean=5.0
The CSV contains a value header followed by 2, 4, 6, and 8. The script writes
result.json with count, mean, and input_sha256. Check the saved result,
rather than treating an exit message as evidence that the right file was used:
python3 - <<'CHECK'
import hashlib
import json
from pathlib import Path
r = json.loads(Path("result.json").read_text())
assert r["count"] == 4
assert r["mean"] == 5.0
assert r["input_sha256"] == hashlib.sha256(Path("measurements.csv").read_bytes()).hexdigest()
print("PASS: saved result and input hash match")
CHECK
A hash checks identical input bytes; it does not establish whether research data are correct. A changed line ending also changes the hash.
Record the environment and evidence
Create a small manifest beside the result:
python3 - <<'MANIFEST'
import hashlib
import json
import platform
from pathlib import Path
manifest = {
"python": platform.python_version(),
"system": platform.system(),
"machine": platform.machine(),
"files": {
name: hashlib.sha256(Path(name).read_bytes()).hexdigest()
for name in ("analyze.py", "measurements.csv", "result.json")
},
}
Path("manifest.json").write_text(json.dumps(manifest, indent=2) + "\n")
print("Saved manifest.json")
MANIFEST
Add a README.md with the question, the run command, expected output, Python
version, selected runtime image or catalog identifier, and what you checked.
For a real analysis, also record package versions or a lockfile, data provenance,
seeds, and appropriate numerical tolerances. Do not copy credentials into the
manifest or publish private data to make an example reproducible.
Rerun independently
- Create a new project and a new
research-workflowfolder. - Transfer
analyze.py,measurements.csv,manifest.json, and the README from the first project. Do not copyresult.jsonyet; the second run must create it. You may use download/upload or the CLI transfer guide. - In the second project's terminal, change to the new folder and verify the transferred inputs against the first run's manifest:
python3 - <<'CHECK'
import hashlib
import json
from pathlib import Path
m = json.loads(Path("manifest.json").read_text())
for name in ("analyze.py", "measurements.csv"):
assert hashlib.sha256(Path(name).read_bytes()).hexdigest() == m["files"][name], name
print("PASS: input and code match the original")
CHECK
python3 analyze.py measurements.csv result.json
- Repeat the saved-result check above. For this deterministic example, compare the new artifact with the original manifest as well:
python3 - <<'CHECK'
import hashlib
import json
from pathlib import Path
m = json.loads(Path("manifest.json").read_text())
assert hashlib.sha256(Path("result.json").read_bytes()).hexdigest() == m["files"]["result.json"]
print("PASS: independent result matches the original")
CHECK
- Record the second project's Python version and image independently. Keep the original manifest; do not overwrite it with a new manifest before comparing. Matching this simple result does not prove all software environments are equivalent. For real floating-point or GPU workloads, compare the scientific acceptance criteria rather than assuming byte-for-byte output equality.
Reproduce software as well as files
A custom kernel can isolate notebook dependencies.
Record its executable and recreate its packages in the new project. A
published RootFS can share installed system
software, but publishing excludes /home/user, /root, and /tmp.
Research files and a virtual environment under HOME are not automatically
included. Transfer the files and recreate HOME-based environments separately.
Do not assume an image label alone captures a dataset or an external service.
For a notebook version of this analysis, follow Move a Jupyter or Colab notebook. Then use Research handoff to let a collaborator repeat the same checks, with the correct access to the files.
Diagnose a mismatch
- File not found: run
pwdand check that code and CSV are in the same folder. A remote Jupyter kernel reads a different machine's filesystem; see Remote kernels. - CSV or assertion error: inspect the header and values before changing the test. Compare input and code hashes first.
- A real package is missing: install it into the interpreter or kernel actually running the analysis, not an unrelated terminal Python.
- Same inputs, different scientific output: record both environments and investigate software versions, randomness, hardware, and tolerances. Do not replace the expected result merely to make the comparison pass.
After review, retain the source, manifest, and result together. Remove only the example folders or disposable projects you no longer need through the normal project controls.