Install

Docker, the one supported path, and what else works

Installation

Docker is the supported path, and it is the one the rest of this page assumes. One image carries Python, R, the CLI and all 69 bundled clocks at pinned versions, so the same input gives the same numbers on your machine and on a reviewer’s. Nothing else to install. Both images are published on Docker Hub and built from the Dockerfiles in this repository. Two commands from nothing to a proven install:

docker pull bhagesh/falconage:1.0.0-cpu
docker run --rm bhagesh/falconage:1.0.0-cpu python -m pytest /opt/falconage/src/python/tests -q

The second line proves it by running the test suite inside the image, against the source it was built from.

Or build the same image from a clone, which takes about ten minutes the first time and is then cached:

git clone https://github.com/bhagesh-h/FALCONAge.git
cd FALCONAge
docker build -f docker/Dockerfile.cpu -t bhagesh/falconage:1.0.0-cpu .

Then either open a session in the image:

docker run --rm -it -v "$PWD:/work" -w /work bhagesh/falconage:1.0.0-cpu python
docker run --rm -it -v "$PWD:/work" -w /work bhagesh/falconage:1.0.0-cpu R

Or run a single command without opening one:

docker run --rm -v "$PWD:/work" -w /work bhagesh/falconage:1.0.0-cpu \
  report betas.csv --outdir results/

The image’s entrypoint is the falconage CLI, so the first argument is a verb: report, not falconage report. The exceptions are python, R, Rscript, pytest and bash, which are run as given.

On Windows PowerShell write "${PWD}" for "$PWD". Getting started walks the same ground one command at a time, including the GPU image and a native pip / remotes::install_github install for anyone who already manages their own environment.

If you have never used a terminal, start at the step-by-step walkthrough below instead; it assumes nothing and covers fetching real public data.

NoteWhich shell you are typing into

"$PWD" means “the folder I am in now”, and the spelling differs:

Where you are typing Use
macOS Terminal, Linux, Git Bash, WSL "$PWD"
Windows PowerShell "${PWD}"
Windows cmd.exe "%cd%"

Everything else is identical. A path error on Windows is almost always this.

pip install "falconage @ git+https://github.com/bhagesh-h/FALCONAge.git#subdirectory=python"
import falconage as fa
fa.config()
remotes::install_github("bhagesh-h/FALCONAge", subdir = "r")

library(FALCONAge)
falconage_install()   # builds the Python environment R calls into; a few minutes
falconage_config()    # what resolved: versions, devices, registry size

The R package delegates every number to the Python core, so it needs a Python environment either way. On reticulate ≥ 1.41 an ephemeral one is built on first use and falconage_install() is optional; use it when you want a pinned, reproducible one.

Every code example on this page runs unchanged in a native install; only the docker run prefix goes away.

falconage_config() is the first thing to run when anything looks wrong. It reports the interpreter, the registry version, and how many clocks are usable:

FALCONAge 1.0.0
  registry     1.1.0 (178 clocks)
  availability 69 bundled - 52 untraced - 57 licensed
  numpy        2.5.1
  torch        not installed (the CPU path needs none)
  devices      cpu
  python       /usr/local/bin/python

Complete walkthrough, from an empty machine

Everything above, in order, assuming no Python, no R, and no prior experience with either. Each command can be copied one at a time and each says what it does and what you should see. It ends with a scored public dataset and the figures.

Step 0: install Docker

Install Docker Desktop (Windows, macOS) or Docker Engine (Linux), start it, then run:

docker --version

You should get a version string. If instead you get “command not found” or “cannot connect to the Docker daemon”, Docker is not installed or not running; fix that before going further, because nothing below will work.

If a later command fails with a path error: it is almost certainly the "$PWD" spelling for your shell; see the table above.

Step 1: clone the repository

git clone https://github.com/bhagesh-h/FALCONAge.git
cd FALCONAge

Every later command is run from inside this FALCONAge folder.

Step 2: obtain the image

One image carries Python, R, the CLI and all 69 bundled clocks. Pull the published one:

docker pull bhagesh/falconage:1.0.0-cpu

Or build the same thing from the clone, which takes about ten minutes the first time and is then cached:

docker build -f docker/Dockerfile.cpu -t bhagesh/falconage:1.0.0-cpu .

Check it either way:

docker run --rm bhagesh/falconage:1.0.0-cpu python -c "import falconage; print(falconage.__version__)"

Step 3: inspect the corpus before downloading it

A second, deliberately tiny image fetches the test corpus. It is separate on purpose: fetching a fixture is the first thing you do when the package itself is broken, so it must not need the package.

docker build -f docker/Dockerfile.testdata -t falconage-testdata:1.0.0 .

Now the dry run. This transfers nothing. It prints every group, file count and byte total so you can decide before committing to half a gigabyte:

docker run --rm -v "$PWD/test/data:/data" falconage-testdata:1.0.0 plan

You should see:

group          files        size   what it is for
------------------------------------------------------------------------------
bench             14    549.8 MB   ComputAgeBench case/control methylation
clinical           3      5.4 MB   NHANES blood chemistry with mortality linkage
gestational        1     50.8 MB   Umbilical cord blood with gestational age
epicv2             1     41.2 MB   EPIC v2 probe-suffix handling
idat               8     60.4 MB   Raw IDATs, EPIC v1 and EPIC v2
mammalian          4      9.3 MB   Mammalian methylation array, three species
mouse              5     50.2 MB   Mouse blood RRBS across the lifespan
------------------------------------------------------------------------------
selected          36    767.1 MB

Step 4: download and verify

docker run --rm -v "$PWD/test/data:/data" falconage-testdata:1.0.0 python
docker run --rm -v "$PWD/test/data:/data" falconage-testdata:1.0.0 verify

The first fetches 36 files from GEO and Hugging Face into test/data/ on your own disk, never inside the image, so rebuilding never re-downloads. The second re-computes every SHA-256 against checksums.sha256 and fails loudly on a single wrong byte.

Only smaller pieces, if 767 MB is too much:

docker run --rm -v "$PWD/test/data:/data" falconage-testdata:1.0.0 python --groups clinical
TipFetching the corpus from R

Not decoration: the R fetcher writes a byte-identical checksums.sha256, so the two languages are shown to agree on the input before any clock is scored.

docker run --rm -v "$PWD/test/data:/data" falconage-testdata:1.0.0 R

Step 5: score it

docker run --rm -v "$PWD:/work" -w /work bhagesh/falconage:1.0.0-cpu \
  python test/run_all.py

Every clock against every dataset. It writes one folder per input under test/output/, every figure under test/output_figures/, and rewrites the generated tables in test/README.md, so the numbers in that document are the numbers the code just produced and cannot drift from them.

To check the install without the corpus, run the unit suite instead, seconds, no data needed:

docker run --rm -v "$PWD:/work" -w /work bhagesh/falconage:1.0.0-cpu \
  python -m pytest python/tests -q

The same image. R calls the same Python core through reticulate, so these are the same numbers, not a second implementation that agrees approximately.

docker run --rm -v "$PWD:/work" -w /work bhagesh/falconage:1.0.0-cpu \
  Rscript -e 'testthat::test_local("r")'

That suite includes the R-versus-Python conformance tests, which assert equality at tolerance exactly zero.

Scoring from R interactively:

docker run --rm -it -v "$PWD:/work" -w /work bhagesh/falconage:1.0.0-cpu R
library(FALCONAge)
falconage_config()
d   <- read_betas("test/data/bench/GSE40279.csv")
res <- score(prepare(d), clocks = "compatible")
summary(res)

Only worth it if you have an NVIDIA card. Read GPU support first: for the clocks that ship today the GPU is slower than the CPU, which is why device="auto" resolves to CPU even inside this image.

Pull the CUDA image. It is 14.6 GB against the CPU image’s 2.5 GB, because it carries torch built against CUDA 12.4:

docker pull bhagesh/falconage:1.0.0-cuda

Or build it:

docker build -f docker/Dockerfile.cuda -t bhagesh/falconage:1.0.0-cuda .

Check the card is visible inside a container before anything else:

docker run --rm --gpus all bhagesh/falconage:1.0.0-cuda nvidia-smi

No output or an error here means GPU passthrough is not set up, and every command below will fail. On Linux that is usually a missing nvidia-container-toolkit.

docker run --rm --gpus all -v "$PWD:/work" -w /work bhagesh/falconage:1.0.0-cuda \
  python test/gpu_check.py

This reproduces every number on the GPU page, device resolution, CPU-versus-GPU agreement, the speed table and the profile that explains it. On a machine with no CUDA device it stops after the first step with an explanation rather than an error, so it is safe to run anywhere.

Scoring on the GPU needs --gpus all and --device cuda. Without the flag, --device cuda raises rather than falling back, so a run that asked for a GPU cannot quietly become a very slow success:

docker run --rm --gpus all -v "$PWD:/work" -w /work bhagesh/falconage:1.0.0-cuda \
  score --input test/data/prepared.h5ad --device cuda --outdir results

Step 6: score your own data

Put a beta matrix or a clinical table in a folder, mount it read-only, and mount somewhere for the results to land:

docker run --rm \
  -v "$PWD/mydata:/data:ro" \
  -v "$PWD/results:/results" \
  -v falconage-cache:/opt/falconage/cache \
  bhagesh/falconage:1.0.0-cpu \
  score --input /data/betas.csv --clocks compatible --outdir /results

The named falconage-cache volume is worth adding from the start. Nothing bundled needs it; it keeps what FALCONAge downloads on request, the Illumina manifests fetch_manifest() caches (12 to 26 MB each) and data fetched with fa.download, so a new container does not fetch them again.