Discover genomics table schemas¶
Use INFORMATION_SCHEMA to inspect current column names, types, and available tables in the genomics portion of the CDR, before writing a new query.
Prerequisites¶
- Any workspace with CDR access (Registered or Controlled)
- Python 3,
google-cloud-bigquery
Tier: Registered (for INFORMATION_SCHEMA queries against the CDR dataset)
CDR versions: All
Reference¶
AoU genomics tables have changed across CDR releases: columns have been renamed, new tables have been added, and join keys have been restructured. Code written against one CDR version may fail or silently return wrong results against another.
INFORMATION_SCHEMA.COLUMNS and INFORMATION_SCHEMA.TABLES are BigQuery system views that describe the schema of any dataset you have access to. They are the authoritative source for "what columns exist right now in this CDR?"
Key system views:
| View | What it shows |
|---|---|
INFORMATION_SCHEMA.TABLES |
All tables in the dataset: name, type, creation time |
INFORMATION_SCHEMA.COLUMNS |
All columns in all tables: name, data type, ordinal position, nullability |
Usage¶
Step 1: List all genomics-related tables¶
import os
from google.cloud import bigquery
client = bigquery.Client()
CDR = os.environ["WORKSPACE_CDR"]
# Extract project.dataset from CDR path
# CDR looks like "project.dataset" or "project.dataset"
tables_sql = f"""
SELECT table_name, table_type, creation_time
FROM `{CDR}.INFORMATION_SCHEMA.TABLES`
WHERE table_name LIKE '%variant%'
OR table_name LIKE '%genom%'
OR table_name LIKE '%wgs%'
OR table_name LIKE '%cb_variant%'
ORDER BY table_name
"""
tables = client.query(tables_sql).to_dataframe()
print(tables.to_string(index=False))
assuming column names from old code or documentation
Genomics table schemas have changed across CDR releases. A query that
worked in v7 may reference a column that was renamed or removed in v8.
Always run the INFORMATION_SCHEMA query below before writing a new
genomics query -- especially after a CDR upgrade.
Step 2: Get columns for a specific table¶
# Inspect the schema of cb_variant_to_person
columns_sql = f"""
SELECT
column_name,
data_type,
is_nullable,
ordinal_position
FROM `{CDR}.INFORMATION_SCHEMA.COLUMNS`
WHERE table_name = 'cb_variant_to_person'
ORDER BY ordinal_position
"""
cols = client.query(columns_sql).to_dataframe()
print(cols.to_string(index=False))
Step 3: Compare schemas across genomics tables¶
To understand the join paths between tables, inspect shared column names:
# Find columns shared between variant tables
shared_cols_sql = f"""
SELECT
column_name,
STRING_AGG(table_name, ', ') AS found_in_tables,
COUNT(DISTINCT table_name) AS n_tables
FROM `{CDR}.INFORMATION_SCHEMA.COLUMNS`
WHERE table_name LIKE '%variant%'
GROUP BY column_name
HAVING COUNT(DISTINCT table_name) > 1
ORDER BY n_tables DESC, column_name
"""
shared = client.query(shared_cols_sql).to_dataframe()
print("Columns shared across variant tables:")
print(shared.to_string(index=False))
Step 4: Quick schema dump for all variant tables¶
all_variant_cols_sql = f"""
SELECT
table_name,
column_name,
data_type
FROM `{CDR}.INFORMATION_SCHEMA.COLUMNS`
WHERE table_name LIKE '%variant%'
ORDER BY table_name, ordinal_position
"""
all_cols = client.query(all_variant_cols_sql).to_dataframe()
# Print grouped by table
for table, group in all_cols.groupby("table_name"):
print(f"\n--- {table} ---")
for _, row in group.iterrows():
print(f" {row['column_name']:30s} {row['data_type']}")
Variations¶
Check which CDR version you are running against¶
The CDR path itself encodes the version. Extract and display it:
print(f"CDR path: {CDR}")
# The dataset name typically contains the version, e.g.,
# "fc-aou-cdr-prod.C2022Q4R9" or similar
dataset_parts = CDR.split(".")
if len(dataset_parts) == 2:
project, dataset = dataset_parts
print(f"Project: {project}")
print(f"Dataset (CDR version): {dataset}")
For a programmatic check, query the CDR metadata if available:
metadata_sql = f"""
SELECT table_name
FROM `{CDR}.INFORMATION_SCHEMA.TABLES`
WHERE table_name LIKE '%metadata%' OR table_name LIKE '%cdr_version%'
"""
meta = client.query(metadata_sql).to_dataframe()
if len(meta) > 0:
print("Metadata tables found:")
print(meta.to_string(index=False))
Search for a specific column name across all tables¶
When you have code referencing a column and need to find which table it belongs to:
# Find which tables contain a 'vid' column
find_col_sql = f"""
SELECT table_name, column_name, data_type
FROM `{CDR}.INFORMATION_SCHEMA.COLUMNS`
WHERE column_name = 'vid'
ORDER BY table_name
"""
found = client.query(find_col_sql).to_dataframe()
print(found.to_string(index=False))
List all tables with row counts¶
Get an overview of table sizes to understand query cost implications:
# Approximate row counts from table metadata
size_sql = f"""
SELECT
t.table_name,
t.table_type,
p.total_rows,
p.total_logical_bytes
FROM `{CDR}.INFORMATION_SCHEMA.TABLES` t
LEFT JOIN `{CDR}.INFORMATION_SCHEMA.TABLE_STORAGE` p
ON t.table_name = p.table_name
WHERE t.table_name LIKE '%variant%'
ORDER BY p.total_logical_bytes DESC NULLS LAST
"""
sizes = client.query(size_sql).to_dataframe()
# Convert bytes to GB for readability
sizes["size_gb"] = sizes["total_logical_bytes"] / (1024**3)
print(sizes[["table_name", "total_rows", "size_gb"]].to_string(index=False))
Pull a full variant catalog for a gene¶
Retrieve all annotations for every variant in a gene — useful for exploratory analysis before deciding on filters:
catalog_sql = f"""
SELECT
va.vid, va.cons_str,
va.clinical_significance_string AS clinvar,
va.protein_change, va.allele_frequency, va.participant_count
FROM `{CDR}.cb_variant_attribute` va
JOIN `{CDR}.cb_variant_attribute_genes` vag ON va.vid = vag.vid
WHERE vag.gene_symbol = 'BRCA1'
ORDER BY va.participant_count DESC
"""
catalog = client.query(catalog_sql).to_dataframe()
print(f"Variants: {len(catalog):,}")
print(catalog.head(10))
Parse VID format into genomic coordinates¶
The vid column follows the pattern chromosome-position-ref-alt (e.g., 1-45331833-C-G). No chr prefix.
vid_parts = catalog["vid"].str.split("-", expand=True)
catalog["CHROM"] = vid_parts[0]
catalog["POS"] = vid_parts[1].astype(int)
catalog["REF"] = vid_parts[2]
catalog["ALT"] = vid_parts[3]
This is needed for joining to external databases (e.g., AlphaMissense, gnomAD) that use positional coordinates rather than AoU's vid format.
Troubleshooting¶
| Symptom | Cause |
|---|---|
INFORMATION_SCHEMA query returns empty results |
The table_name LIKE pattern does not match any tables. Try LIKE '%' to list all tables, then refine. |
Not found: Dataset error |
The CDR environment variable may not be set, or the dataset path is malformed. Verify echo $WORKSPACE_CDR in a terminal cell. |
Access Denied on INFORMATION_SCHEMA |
Your workspace may not have read access to the controlled-tier CDR. Verify workspace tier in the Researcher Workbench UI. |
Cost note¶
INFORMATION_SCHEMA queries are free. They do not scan table data and are not billed. Run them as often as needed.
See also¶
- Query carrier status for a gene panel -- uses the tables discovered here
- Filter variants to ClinVar Pathogenic/Likely Pathogenic -- uses
cb_variant_attributecolumns discovered here - Dry-run a query to estimate cost -- estimate cost after discovering the tables you need