All tutorialsTutorial

BigQuery Guide for IDC

**Tested with:** IDC data version v23

Claude Code Knowledge Pack7/10/2026

BigQuery Guide for IDC

Tested with: IDC data version v23

For most queries and downloads, use idc-index (see main SKILL.md). This guide covers BigQuery for advanced use cases requiring full DICOM metadata or complex joins.

Prerequisites

Requirements:

  1. Google account
  2. Google Cloud project with billing enabled (first 1 TB/month free)
  3. google-cloud-bigquery Python package or BigQuery console access

Authentication setup:

# Install Google Cloud SDK, then:
gcloud auth application-default login

When to Use BigQuery

Use BigQuery instead of idc-index when you need:

  • Full DICOM metadata (all 4000+ tags, not just the ~50 in idc-index)
  • Complex joins across clinical data tables
  • DICOM sequence attributes (nested structures)
  • Queries on fields not in the idc-index mini-index
  • Private DICOM elements (vendor-specific tags in OtherElements column)
  • Per-segment detail from DICOM Segmentation objectsidc-index seg_index gives series-level metadata, but not individual segment anatomy codes; use segmentations BigQuery table to query by structure name
  • Quantitative measurements from DICOM SR — radiomics features (volume, diameter, shape descriptors) without downloading and parsing SR files; no idc-index equivalent
  • Qualitative measurements from DICOM SR — coded evaluations (malignancy rating, texture, margin) without parsing SR files; no idc-index equivalent

Accessing IDC in BigQuery

Dataset Structure

All IDC tables are in the bigquery-public-data BigQuery project.

Current version (recommended for exploration):

  • bigquery-public-data.idc_current.*
  • bigquery-public-data.idc_current_clinical.*

Versioned datasets (recommended for reproducibility):

  • bigquery-public-data.idc_v{IDC version}.*
  • bigquery-public-data.idc_v{IDC version}_clinical.*

Always use versioned datasets for reproducible research!

Key Tables

dicom_all

Primary table joining complete DICOM metadata with IDC-specific columns (collection_id, gcs_url, license). Contains all DICOM tags from dicom_metadata plus collection and administrative metadata. See dicom_all.sql for the exact derivation.

SELECT 
  collection_id,
  PatientID,
  StudyInstanceUID, 
  SeriesInstanceUID,
  Modality,
  BodyPartExamined,
  SeriesDescription,
  gcs_url,
  license_short_name
FROM `bigquery-public-data.idc_current.dicom_all`
WHERE Modality = 'CT'
  AND BodyPartExamined = 'CHEST'
LIMIT 10

Derived Tables

These tables are derived from DICOM objects (Segmentation and Structured Report) and have no equivalent in idc-index. Use them to query per-segment anatomy, radiomics features, and qualitative assessments without downloading DICOM files.

segmentations — one row per segment within a DICOM SEG object. Lets you search by anatomical structure name or DICOM coded concept. The idc-index seg_index gives series-level metadata; this table gives per-segment detail.

measurement_groups — one row per SR TID1500 measurement group. The parent grouping for quantitative and qualitative measurements; links measurements to segmentations and source images.

quantitative_measurements — one row per numeric measurement within an SR TID1500 group. Contains radiomics features (volume, diameter, shape descriptors, texture) extracted from DICOM SR without downloading or parsing SR files.

qualitative_measurements — one row per coded evaluation within an SR TID1500 group. Contains assessed findings (malignancy likelihood, texture, margin type) using coded concept values.

See the Derived Tables: Detailed Documentation section below for schemas, column descriptions, and query examples.

Collection Metadata

original_collections_metadata - Collection-level descriptions

SELECT
  collection_id,
  CancerTypes,
  TumorLocations,
  Subjects,
  src.source_doi,
  src.ImageTypes,
  src.license.license_short_name
FROM `bigquery-public-data.idc_current.original_collections_metadata`,
UNNEST(Sources) AS src
WHERE CancerTypes LIKE '%Lung%'

Common Query Patterns

Find Collections by Criteria

SELECT 
  collection_id,
  COUNT(DISTINCT PatientID) as patient_count,
  COUNT(DISTINCT SeriesInstanceUID) as series_count,
  ARRAY_AGG(DISTINCT Modality) as modalities
FROM `bigquery-public-data.idc_current.dicom_all`
WHERE BodyPartExamined LIKE '%BRAIN%'
GROUP BY collection_id
HAVING patient_count > 50
ORDER BY patient_count DESC

Get Download URLs

SELECT
  SeriesInstanceUID,
  gcs_url
FROM `bigquery-public-data.idc_current.dicom_all`
WHERE collection_id = 'rider_pilot'
  AND Modality = 'CT'

Find Studies with Multiple Modalities

SELECT
  StudyInstanceUID,
  ARRAY_AGG(DISTINCT Modality) as modalities,
  COUNT(DISTINCT SeriesInstanceUID) as series_count
FROM `bigquery-public-data.idc_current.dicom_all`
GROUP BY StudyInstanceUID
HAVING ARRAY_LENGTH(ARRAY_AGG(DISTINCT Modality)) > 1
LIMIT 100

License Filtering

SELECT
  collection_id,
  license_short_name,
  COUNT(*) as instance_count
FROM `bigquery-public-data.idc_current.dicom_all`
WHERE license_short_name = 'CC BY 4.0'
GROUP BY collection_id, license_short_name

Find Segmentations with Source Images

SELECT
  src.collection_id,
  seg.SeriesInstanceUID as seg_series,
  seg.SegmentedPropertyType,
  src.SeriesInstanceUID as source_series,
  src.Modality as source_modality
FROM `bigquery-public-data.idc_current.segmentations` seg
JOIN `bigquery-public-data.idc_current.dicom_all` src
  ON seg.segmented_SeriesInstanceUID = src.SeriesInstanceUID
WHERE src.collection_id = 'qin_prostate_repeatability'
LIMIT 10

Derived Tables: Detailed Documentation

segmentations

One row per segment within a DICOM Segmentation (SEG) object. Unlike idc-index seg_index (one row per SEG series), this table exposes each labeled region individually so you can search by anatomical structure or finding type.

Key columns:

ColumnTypeDescription
SeriesInstanceUIDSTRINGSEG series UID
SOPInstanceUIDSTRINGSEG instance UID
PatientIDSTRINGPatient identifier
StudyInstanceUIDSTRINGStudy UID
SegmentNumberINTEGERSegment index within the SEG (starting from 1)
SegmentedPropertyCategoryRECORDCoded category (e.g., "Anatomical Structure", "Morphologically Altered Structure")
SegmentedPropertyTypeRECORDSpecific structure (e.g., "Liver", "Kidney", "Neoplasm")
AnatomicRegionRECORDOptional anatomic region modifier
SegmentAlgorithmTypeSTRINGAUTOMATIC, SEMIAUTOMATIC, or MANUAL
SegmentAlgorithmNameSTRING (REPEATED)Algorithm name array (e.g., ["TotalSegmentator"])
TrackingUIDSTRINGLinks segment to SR measurements
TrackingIDSTRINGHuman-readable tracking label
segmented_SeriesInstanceUIDSTRINGSource image series UID — join to dicom_all to get collection/modality
viewer_urlSTRINGDirect IDC viewer link for the SEG

SegmentedPropertyCategory and SegmentedPropertyType are RECORD types with sub-fields CodeValue, CodingSchemeDesignator, and CodeMeaning. Use .CodeMeaning for human-readable filtering.

idc-index gap: seg_index in idc-index has total_segments, AlgorithmName, and aggregated codes, but does not expose individual segment anatomy per row. Use this BigQuery table when you need to find SEG series that contain a specific structure (e.g., all series with a "Liver" segment).

Discover what structures are segmented across IDC:

SELECT
  SegmentedPropertyCategory.CodeMeaning AS category,
  SegmentedPropertyType.CodeMeaning AS structure,
  SegmentAlgorithmType,
  COUNT(DISTINCT SeriesInstanceUID) AS seg_series_count
FROM `bigquery-public-data.idc_current.segmentations`
GROUP BY 1, 2, 3
ORDER BY seg_series_count DESC
LIMIT 20

Find all SEG series containing a specific structure, with source image context:

SELECT
  seg.SeriesInstanceUID AS seg_series,
  seg.SegmentNumber,
  seg.SegmentedPropertyType.CodeMeaning AS structure,
  seg.SegmentAlgorithmType,
  seg.SegmentAlgorithmName,
  img.collection_id,
  img.PatientID,
  img.Modality,
  seg.viewer_url
FROM `bigquery-public-data.idc_current.segmentations` seg
JOIN `bigquery-public-data.idc_current.dicom_all` img
  ON seg.segmented_SeriesInstanceUID = img.SeriesInstanceUID
WHERE seg.SegmentedPropertyType.CodeMeaning = 'Liver'
  AND seg.SegmentAlgorithmType = 'AUTOMATIC'
LIMIT 20

Find all segment types present in a collection:

SELECT
  seg.SegmentedPropertyType.CodeMeaning AS structure,
  seg.SegmentAlgorithmType,
  COUNT(DISTINCT seg.SeriesInstanceUID) AS seg_series_count
FROM `bigquery-public-data.idc_current.segmentations` seg
JOIN `bigquery-public-data.idc_current.dicom_all` img
  ON seg.segmented_SeriesInstanceUID = img.SeriesInstanceUID
WHERE img.collection_id = 'nlst'
GROUP BY 1, 2
ORDER BY seg_series_count DESC

Link segments to SR measurements using TrackingUID:

-- Find segments that have corresponding SR measurements
SELECT
  seg.SeriesInstanceUID AS seg_series,
  seg.SegmentNumber,
  seg.SegmentedPropertyType.CodeMeaning AS structure,
  qm.Quantity.CodeMeaning AS measurement,
  ROUND(CAST(qm.Value AS FLOAT64), 2) AS value,
  qm.Units.CodeMeaning AS units
FROM `bigquery-public-data.idc_current.segmentations` seg
JOIN `bigquery-public-data.idc_current.quantitative_measurements` qm
  ON seg.SeriesInstanceUID = qm.segmentationSeriesUID
  AND seg.SegmentNumber = qm.segmentationSegmentNumber
WHERE seg.SegmentedPropertyType.CodeMeaning = 'Neoplasm'
  AND qm.Quantity.CodeMeaning = 'Volume from Voxel Summation'
LIMIT 10

quantitative_measurements

One row per numeric measurement in a DICOM SR TID1500 Measurement Report. Contains radiomics features (shape, intensity, texture) and clinical measurements (volume, diameter, SUV). These measurements are pre-extracted from SR — no download or DICOM parsing needed.

No idc-index equivalent. This table is only accessible via BigQuery.

Key columns:

ColumnTypeDescription
SOPInstanceUIDSTRINGSR instance UID
SeriesInstanceUIDSTRINGSR series UID — join to dicom_all for collection/modality
SeriesDescriptionSTRINGSR series description (e.g., "TotalSegmentator(v1.5.6) shape Measurements")
PatientIDSTRINGPatient identifier
measurementGroup_numberINTEGERGroup index within the SR (0-based); join key with measurement_groups and qualitative_measurements
QuantityRECORDWhat was measured — CodeValue, CodingSchemeDesignator, CodeMeaning (e.g., "Volume from Voxel Summation")
ValueNUMERICThe numeric measurement value
UnitsRECORDUnits — CodeMeaning (e.g., "cubic millimeter", "no units", "Hounsfield Unit")
derivationModifierRECORDHow the value was derived (e.g., "Mean", "Minimum", "Maximum")
lateralityModifierRECORDLaterality qualifier
findingRECORDWhat finding was measured — CodeMeaning (e.g., "Nodule", "Organ", "Anatomical Structure")
findingSiteRECORDWhere the finding is — CodeMeaning (e.g., "Liver", "Esophagus", "Lung")
trackingIdentifierSTRINGHuman-readable tracking label (e.g., "Nodule 1", "Measurements group 26")
trackingUniqueIdentifierSTRINGTracking UID — links back to segmentations.TrackingUID
segmentationInstanceUIDSTRINGSOPInstanceUID of the referenced SEG object
segmentationSeriesUIDSTRINGSeriesInstanceUID of the referenced SEG object
segmentationSegmentNumberINTEGERSegment number within the SEG — join to segmentations.SegmentNumber
sourceSegmentedSeriesUIDSTRINGSource image series — join to dicom_all.SeriesInstanceUID

Discover available measurement types:

SELECT
  Quantity.CodeMeaning AS measurement,
  Units.CodeMeaning AS units,
  COUNT(*) AS measurement_count,
  COUNT(DISTINCT SeriesInstanceUID) AS sr_series_count
FROM `bigquery-public-data.idc_current.quantitative_measurements`
GROUP BY 1, 2
ORDER BY measurement_count DESC
LIMIT 20

Query measurements for a specific structure (e.g., liver volume across collections):

SELECT
  qm.PatientID,
  ROUND(CAST(qm.Value AS FLOAT64) / 1000, 1) AS volume_cm3,
  img.collection_id,
  qm.segmentationSeriesUID
FROM `bigquery-public-data.idc_current.quantitative_measurements` qm
JOIN `bigquery-public-data.idc_current.dicom_all` img
  ON qm.sourceSegmentedSeriesUID = img.SeriesInstanceUID
WHERE qm.Quantity.CodeMeaning = 'Volume from Voxel Summation'
  AND qm.findingSite.CodeMeaning = 'Liver'
ORDER BY volume_cm3 DESC
LIMIT 20

Retrieve all measurements for a specific patient and finding:

SELECT
  qm.measurementGroup_number,
  qm.finding.CodeMeaning AS finding,
  qm.findingSite.CodeMeaning AS finding_site,
  qm.lateralityModifier.CodeMeaning AS laterality,
  qm.Quantity.CodeMeaning AS feature,
  ROUND(CAST(qm.Value AS FLOAT64), 3) AS value,
  qm.Units.CodeMeaning AS units
FROM `bigquery-public-data.idc_current.quantitative_measurements` qm
WHERE qm.PatientID = 'LIDC-IDRI-0001'
  AND qm.finding.CodeMeaning = 'Nodule'
ORDER BY qm.measurementGroup_number, qm.Quantity.CodeMeaning

qualitative_measurements

One row per coded evaluation in a DICOM SR TID1500 Measurement Report. Instead of numeric values, these record assessed characteristics using coded concept pairs (e.g., Quantity="Malignancy", Value="4 out of 5 (Moderately Suspicious for Cancer)").

No idc-index equivalent. This table is only accessible via BigQuery.

Key columns:

ColumnTypeDescription
SOPInstanceUIDSTRINGSR instance UID
SeriesInstanceUIDSTRINGSR series UID — join to dicom_all for collection/modality
PatientIDSTRINGPatient identifier
measurementGroup_numberINTEGERGroup index within the SR — join key with quantitative_measurements
QuantityRECORDWhat was assessed — CodeMeaning (e.g., "Malignancy", "Calcification", "Texture")
ValueRECORDThe coded answer — CodeMeaning (e.g., "4 out of 5 (Moderately Suspicious for Cancer)")
findingRECORDWhat finding was assessed — CodeMeaning (e.g., "Nodule")
findingSiteRECORDAnatomic site — CodeMeaning (e.g., "Lung")
trackingIdentifierSTRINGHuman-readable tracking label
segmentationInstanceUIDSTRINGSOPInstanceUID of the referenced SEG object
segmentationSeriesUIDSTRINGSeriesInstanceUID of the referenced SEG object
`segmentationSegmentNum