AI-Driven Research & Agentic Bioinformatics-2026-08-22

Deterministic Retrieval with gget

NM

Nasir Mahmood Abbasi, PhD

Bioinformatics Educator

Deterministic Retrieval with gget

Use gget to query Ensembl-linked metadata and sequence records, then preserve the raw response and enough provenance to interpret it later. Database retrieval is reproducible only when you record the software, query, source state, and response; an LLM can still misread supplied evidence.

Format: Hands-on lab. This guided exercise is for learners comfortable with a Unix-like shell. Use the gget CLI to retrieve gene metadata and translated FASTA for the ACE2 Ensembl ID, then inspect the saved output with R and jsonlite. gget must already be available under its current official instructions; a Python API example is optional. No biological input files are supplied or needed. Live retrieval needs internet access.

Learning objectives and prerequisites

By the end of this lesson you will be able to:

  • Run gget's documented command-line retrievals for an Ensembl gene ID and save the raw JSON and FASTA responses.
  • Use R to inspect the saved CLI outputs without claiming that gget has an R API.
  • Preserve query provenance and assess what the returned records do and do not support.

Prerequisites: basic command-line familiarity, the gget command-line program installed and configured using its current official instructions, an internet connection, and R with the small jsonlite package for JSON parsing. gget's CLI remains the retrieval tool; R reads its saved files. No research data are required. Do not install a new environment or paid service for this lesson unless your local policy permits it.

Why deterministic retrieval matters in bioinformatics

Large Language Models (LLMs) can synthesize text and generate code, but they are not authoritative sources of changing biological facts such as current Ensembl gene IDs, transcript coordinates, or canonical UniProt accessions. Supplying an LLM with a saved database response gives it evidence to inspect, but does not prevent hallucinations or guarantee correct interpretation. Record the query, retrieval time, software version, and relevant database release so another person can assess the result.

gget provides native command-line subcommands for querying bioinformatics resources. The route below uses gget CLI for retrieval, then R only to inspect the saved response. A request made through gget CLI is not the same request or API behavior as a separate gget Python API call. Remote annotations can change between runs; saving the response preserves what you received, not the database service itself.

Reproducible, sequential workflow

The example uses the human ACE2 Ensembl gene ID shown in gget's documented quick start, ENSG00000130234. Commands assume a Unix-like shell and internet access. Gene symbols can be ambiguous; resolve a symbol to an intended Ensembl ID before using this pattern. Responses from external services may change over time.

1) Check the CLI and prepare output files

Start with gget already installed according to its current official documentation. The project does not pin or reinstall Python dependencies for the R inspection route. From a new working directory, create a results folder, check the CLI help and executable path, and record a UTC timestamp:

mkdir -p retrieval-results
if ! command -v gget; then echo "gget CLI is not available; follow its official installation instructions." >&2; exit 127; fi
gget --help > retrieval-results/gget-help.txt 2>&1
printf 'query_start_utc=%s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" > retrieval-results/commands.log

The commands create retrieval-results/gget-help.txt and retrieval-results/commands.log. Record the exact gget version using the installation method's documented version/package-inspection command; no version flag is assumed to be portable across releases. If the CLI is missing, follow gget's official installation documentation and check the version and platform compatibility before continuing.

2) Retrieve the gene record and protein FASTA with native gget CLI

Keep the commands explicit and save standard output as raw response files. gget failures should be diagnosed from the command's exit status and standard error before interpreting any partial file.

# Log start/end, exact command label, and exit status around each CLI query
log_run() {
  label=$1; shift
  started=$(date -u '+%Y-%m-%dT%H:%M:%SZ')
  "$@"
  status=$?
  finished=$(date -u '+%Y-%m-%dT%H:%M:%SZ')
  printf 'start=%s | command=%s | exit=%s | end=%s\n' "$started" "$label" "$status" "$finished" >> retrieval-results/commands.log
  return "$status"
}
# Save the raw command-line JSON and translated FASTA; stop on a failed query.
if log_run 'gget info ENSG00000130234' gget info ENSG00000130234 > retrieval-results/ACE2_info.json; then
  printf 'gget_info_exit=0\n' >> retrieval-results/commands.log
else
  status=$?
  printf 'gget_info_exit=%s\n' "$status" >> retrieval-results/commands.log
  echo "gget info failed; inspect stderr and the partial output before retrying." >&2
  exit "$status"
fi

if log_run 'gget seq --translate ENSG00000130234' gget seq --translate ENSG00000130234 > retrieval-results/ACE2_protein.fasta; then
  printf 'gget_seq_exit=0\n' >> retrieval-results/commands.log
else
  status=$?
  printf 'gget_seq_exit=%s\n' "$status" >> retrieval-results/commands.log
  echo "gget seq failed; inspect stderr and the partial output before retrying." >&2
  exit "$status"
fi
printf 'query_end_utc=%s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" >> retrieval-results/commands.log

retrieval-results/ACE2_info.json holds the raw CLI JSON and retrieval-results/ACE2_protein.fasta holds translated sequence output. The gget manual identifies --translate amino-acid retrieval as coming from UniProt, while nucleotide sequences are fetched from Ensembl. The command itself does not establish a canonical-selection rule: inspect the returned header and source record rather than assuming which isoform was selected. The helper logs UTC start/end times and exit status for each command. This provenance does not freeze upstream database state or identify a database release.

3) Inspect saved CLI JSON and FASTA with R

This primary R utility reads local outputs only; it makes no network request and does not recreate gget. It requires R and jsonlite. Save as inspect_retrieval.R in the same working directory after the CLI files exist, then run Rscript inspect_retrieval.R. The script prints the R and jsonlite versions used for this inspection.

if (!requireNamespace("jsonlite", quietly = TRUE)) {
  stop("Install or load jsonlite according to local policy before parsing JSON")
}
cat("R version:", R.version.string, "\n")
cat("jsonlite version:", as.character(utils::packageVersion("jsonlite")), "\n")
info_path <- "retrieval-results/ACE2_info.json"
if (!file.exists(info_path) || file.info(info_path)$size == 0)
  stop("Missing or empty gget JSON output; inspect the CLI error before retrying")
info <- jsonlite::fromJSON(info_path, simplifyVector = FALSE)
cat("Top-level JSON fields:", paste(names(info), collapse = ", "), "\n")
str(info, max.level = 2)

fasta_path <- "retrieval-results/ACE2_protein.fasta"
if (!file.exists(fasta_path) || file.info(fasta_path)$size == 0)
  stop("Missing or empty FASTA output; inspect the CLI error before retrying")
lines <- readLines(fasta_path, warn = FALSE)
headers <- grep("^>", lines, value = TRUE)
if (!length(headers)) stop("No FASTA header found; inspect the saved file and CLI error")
sequence_lines <- lines[!grepl("^>", lines)]
sequence_length <- sum(nchar(gsub("\\s+", "", sequence_lines, perl = TRUE)))
if (sequence_length == 0L) stop("FASTA header exists but sequence is empty")
cat("FASTA records:", length(headers), "\nFirst header:", headers[[1]],
    "\nSequence characters:", sequence_length, "\n")

Expected result: R prints the JSON top-level field names and a short structure, plus one or more returned FASTA headers and a non-zero character count. A structural pass catches empty files and some error-page responses; it does not prove the record matches the intended gene, validate the sequence, or establish function. Compare the returned identifiers with their source records and report unresolved mapping or isoform identity as unknown.

For a safe offline practice run, create a fresh temporary directory, then create these synthetic fixtures there before running the R script:

mkdir -p /tmp/gget-inspection-fixture/retrieval-results
cd /tmp/gget-inspection-fixture
cat > retrieval-results/ACE2_info.json <<'EOF'
{"id":"SYNTHETIC1","description":"invented test record"}
EOF
cat > retrieval-results/ACE2_protein.fasta <<'EOF'
>SYNTHETIC_PROTEIN invented fixture only
MKT
EOF
# Copy inspect_retrieval.R into this directory first, then run it
Rscript inspect_retrieval.R

The R script tests local file parsing only; the synthetic values are not biological observations. Use a fresh temporary directory and never overwrite a real retrieval directory when practicing.

Optional: gget Python API for Python users

gget also documents a Python API. This is a separate, optional remote request, not an R equivalent and not the same saved response as the CLI query above. Run it only in a compatible Python environment with the version and dependencies required by gget's current documentation. Compare returned fields cautiously; APIs, defaults, and response schemas can differ.

import gget
records = gget.info(["ENSG00000130234"])
records.to_csv("retrieval-results/ACE2_info_python.csv", index=False)
print("Rows:", len(records), "Columns:", list(records.columns))

This Python call sends another query and writes retrieval-results/ACE2_info_python.csv; it is not needed to complete the R-first lesson.

Observed example: an actual ACE2 retrieval

The recorded run used gget==0.28.6, numpy==1.26.4, and pandas==2.2.3. Its direct dependency constraints describe that historical CLI runtime, not universal requirements for R or a recommendation to replace your current environment.

On 23 October 2026 UTC, both CLI queries above completed with exit status zero in the constrained environment. They were executed using the downloadable bounded query runner, which saves raw stdout/stderr, versions, hashes and UTC timestamps and refuses an existing results directory. See its reproduction notes and actual run manifest. The separate Python API export above was not part of this recorded run.

Selected fields from the saved response, not a promise about future queries
Returned fieldObserved valueHow to read it
Ensembl ID / speciesENSG00000130234.15 / homo_sapiensA versioned gene record, not a transcript or protein ID.
Assembly / region / strandGRCh38 / X / -1The returned coordinate context; do not assign another build by assumption.
Canonical transcript fieldENST00000252519.8This field is reported by the gene response; it is not a universal gget sequence-selection rule.
FASTA header / sequenceENST00000252519, UniProt Q9BYF1, 805 amino acidsThe saved header and counted sequence agree on length; that does not validate protein function.

Inspect the complete raw gene response and returned FASTA rather than relying on this table. The response does not establish an explicit annotation release, and missing NCBI/PDB fields are not evidence that no such records exist. These are dated database retrievals, not experimental results or clinical claims.

Output inspection and interpretation

After you save retrieval outputs, inspect them systematically. For each saved file ask:

  • Does the response include the queried Ensembl ID and any linked transcript/protein identifiers?
  • If coordinates are present, can you identify the assembly and annotation release from the returned metadata or source? If not, do not assign an assembly by assumption.
  • Is there a retrieval timestamp and the gget version recorded?

Example: what to look for in the saved JSON from the gget CLI (or, for Python API users, in its separately retrieved CSV). Check actual field names in each response; CLI JSON and API CSV schemas are not assumed to match.

  • Requested ID and linked IDs: distinguish the gene ID from transcript and protein IDs. A successful query for one identifier does not establish that every linked record is current or relevant to your analysis.
  • Coordinates: confirm coordinate convention, assembly, and annotation release using returned metadata or the source database. If any are absent, report them as unknown rather than assuming GRCh38.
  • uniprot_id: link to UniProt canonical accessions, if present. Absence does not mean the protein is uncharacterized; it may reflect lacking cross-reference in that release.
  • description: human-readable gene description. Do not treat this as a definitive function annotation; it's a short text string from the database.

What a plausible result means and does not prove:

  • A returned identifier shows that the service supplied a mapping for the query at that time. It does not validate downstream analyses, nor does an ID alone resolve ambiguity in a symbol-based query.
  • Presence of a UniProt accession means UniProt and Ensembl are cross-referenced in that release; absence could be due to timing or curation differences, not necessarily absence of an actual protein product.
  • For gget seq --translate, the gget manual identifies UniProt as the amino-acid sequence source. Do not label a record canonical unless the returned record establishes which sequence was selected. Sequence retrieval is not experimental validation, and alternative isoforms may exist.

Troubleshooting: symptoms, likely causes, and fixes

Below are common issues when working with gget and how to proceed.

Symptom: gget command not found

  • Likely cause: gget is not installed in the active Python environment or the virtualenv is not activated.
  • Fixes:
    1. Confirm that the environment selected by your documented gget installation is active and command -v gget resolves the intended CLI.
    2. Use that installation method's documented package/version check; do not copy version pins from an unrelated environment or assume a portable gget version flag.
    3. Verify CLI syntax with gget --help and follow current official gget instructions if the executable is missing.

Symptom: empty JSON or no matching record for a gene symbol

  • Likely causes:
    • Ambiguous or species-ambiguous gene symbol (e.g., many species use the same symbol).
    • Symbol is deprecated or not present in the selected species.
  • Fixes:
    1. Resolve the symbol with gget search -s homo_sapiens FOXP3; confirm the intended match before querying its Ensembl ID.
    2. Try a stable identifier (Ensembl ENSG...) if available.
    3. Use gget search -s homo_sapiens FOXP3 to see candidate matches and their species context.

Symptom: FASTA file is truncated or contains HTML/redirect text

  • Likely causes: network interruption, API rate limiting, or gget following an HTTP redirect to a page.
  • Fixes:
    1. Check network connectivity and retry.
    2. Inspect the file start with head -n5 to see if it contains an error HTML page; if so, retry later or check the gget error and upstream service status before retrying. Do not switch endpoints unless gget documentation identifies a supported option.
    3. Inspect the command error and saved file header; check the service status and CLI documentation before retrying. The optional Python API is a different query route, not an R fallback.

Symptom: different results on repeat retrievals

  • Likely causes:
    • Database updates between retrievals (annotation changes, new releases).
    • Different default assembly or species settings in different runs.
  • Fixes:
    1. Record the gget version and query time. Identify the Ensembl release or assembly from returned metadata or source records; do not infer missing values.
    2. If reproducibility is critical, archive the raw JSON/FASTA, gget version and installation details, R/jsonlite versions for inspection, and the retrieval timestamp. Record Python environment details only if you also used the optional Python API.

Limitations, reference-data caveats, and responsible use

Limitations and caveats to keep in mind:

  • Database currency: gget queries external services. Responses reflect service state at retrieval time and can change with database releases or service changes. The saved response preserves the received result, not a snapshot of the database.
  • Identifier granularity: Ensembl has separate namespaces for genes (ENSG), transcripts (ENST) and proteins (ENSP). Ensure you request the correct namespace for your task.
  • Assembly version: Genomic coordinates are meaningful only when paired with an assembly (e.g., GRCh37/hg19 vs GRCh38/hg38). If the response omits the assembly, do not assume one; consult the source record or omit assembly-specific interpretation.
  • LLM interpretation: supplying retrieved records may ground an LLM response, but does not guarantee that the model will use them correctly. Validate critical facts against the saved record and upstream source.
  • Data licensing and usage: check the upstream database terms and licenses for the data and use case. Do not assume one licensing rule applies across these services.

Responsible-use notes:

  • When sharing retrieval outputs in publications or reports, include the exact commands, the gget and dependency versions, retrieval timestamps, and the source (Ensembl/UniProt release).
  • Do not assume that a retrieved gene description equals experimentally validated function. Use appropriate experimental evidence when making biological claims.
  • For human genomic data with privacy concerns, ensure that any identifiers or sequences do not inadvertently reveal participant-level data or violate consent agreements.

Next-step checklist

  1. Confirm the gget CLI is available and record retrieval-results/gget-help.txt, its version using the documented installation method, and the R/jsonlite versions printed by the inspector.
  2. Run the gget CLI retrieval for at least one gene and save the raw JSON and FASTA in retrieval-results/; use the R utility to inspect the saved files.
  3. Record the exact commands and timestamps to retrieval-results/commands.log.
  4. If you provide the saved response to an LLM, ask it to cite the file and quote the relevant field. Verify its interpretation yourself against the source record.
  5. If you will share results externally, include the gget version, retrieval timestamp, and database release numbers in your methods section.

References

Software and package behaviour can change. Please re-check commands against the official documentation. If a command does not work, you find an error, or the tutorial is no longer reproducible, please report it through the Contact page

Author: Nasir Mahmood Abbasi, PhD - Category: AI-Driven Research & Agentic Bioinformatics

Back to topDeterministic Retrieval with gget