Skill Tracer
Skills › Scientific Agent Skills › imaging-data-commons › bigquery_guide.md

bigquery_guide.md

886 lines · skills/imaging-data-commons/references/bigquery_guide.md at 5f2bc03

Open on GitHub
1# BigQuery Guide for IDC
2
3**Reviewed 2026-09-30:** current IDC table documentation and Google BigQuery API/cost guidance.
4The GoogleSQL examples below are illustrative; no authenticated BigQuery jobs were run.
5Use a dry run against your pinned dataset before executing them.
6
7For 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.
8

BigQuery Guide for IDC

Reviewed 2026-09-30: current IDC table documentation and Google BigQuery API/cost guidance. The GoogleSQL examples below are illustrative; no authenticated BigQuery jobs were run. Use a dry run against your pinned dataset before executing them.

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.

Raw lines 1 to 8
9## Prerequisites
11**Requirements:**
121. Google account
132. Google Cloud project with BigQuery access ([sandbox](https://docs.cloud.google.com/bigquery/docs/sandbox) supports limited public queries without a billing account; billing applies beyond applicable limits)
143. `google-cloud-bigquery[pandas]` Python package for `.to_dataframe()`, or BigQuery console access
16**Authentication setup:**
17```bash
18# Install Google Cloud SDK, then:
19gcloud auth application-default login
20```

Prerequisites

Requirements:

  1. Google account
  2. Google Cloud project with BigQuery access (sandbox supports limited public queries without a billing account; billing applies beyond applicable limits)
  3. google-cloud-bigquery[pandas] Python package for .to_dataframe(), or BigQuery console access

Authentication setup:

# Install Google Cloud SDK, then:
gcloud auth application-default login
Raw lines 9 to 21
22## When to Use BigQuery
24Use BigQuery instead of `idc-index` when you need:
25- Instance-level DICOM metadata beyond the compact series-level index; extraction has depth/size limits
26- Hosted queries across large clinical/imaging tables (local DuckDB and REST also support clinical joins)
27- DICOM sequence attributes (nested structures)
28- Queries on fields not in the idc-index mini-index
29- Private DICOM elements (vendor-specific tags in OtherElements column)
30- **Per-segment detail from DICOM Segmentation objects** — `idc-index` `seg_index` gives series-level metadata, but not per-segment rows/number associations; use the `segmentations` table when those details are needed
31- **Quantitative measurements from DICOM SR** — radiomics features (volume, diameter, shape descriptors) without downloading and parsing SR files; no idc-index equivalent
32- **Qualitative measurements from DICOM SR** — coded evaluations (malignancy rating, texture, margin) without parsing SR files; no idc-index equivalent

When to Use BigQuery

Use BigQuery instead of idc-index when you need:

  • Instance-level DICOM metadata beyond the compact series-level index; extraction has depth/size limits
  • Hosted queries across large clinical/imaging tables (local DuckDB and REST also support clinical joins)
  • 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 objects — idc-index seg_index gives series-level metadata, but not per-segment rows/number associations; use the segmentations table when those details are needed
  • 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
Raw lines 22 to 33
34## Accessing IDC in BigQuery
36The same metadata is also exported as public Parquet in `idc-open-metadata`, including
37clinical tables and SR measurements. For an unauthenticated alternative see
38`references/parquet_access_guide.md`; large instance-level joins may still favor BigQuery.

Accessing IDC in BigQuery

The same metadata is also exported as public Parquet in idc-open-metadata, including clinical tables and SR measurements. For an unauthenticated alternative see references/parquet_access_guide.md; large instance-level joins may still favor BigQuery.

Raw lines 34 to 39
40### Dataset Structure
42All IDC tables are in the `bigquery-public-data` BigQuery project.
44**Current version (recommended for exploration):**
45- `bigquery-public-data.idc_current.*`
46- `bigquery-public-data.idc_current_clinical.*`
48**Versioned datasets (recommended for reproducibility):**
50- `bigquery-public-data.idc_v{IDC version}.*`
51- `bigquery-public-data.idc_v{IDC version}_clinical.*`
53Always use versioned datasets for reproducible research!

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!

Raw lines 40 to 54
55## Key Tables
57### dicom_all
58Primary table joining complete DICOM metadata with IDC-specific columns (collection_id, gcs_url, license). Contains exported DICOM fields plus collection and administrative metadata, one row per instance. See [dicom_all.sql](https://github.com/ImagingDataCommons/etl_flow/blob/master/bq/generate_tables_and_views/derived_tables/BQ_Table_Building/derived_data_views/sql/dicom_all.sql) for the exact derivation.
60```sql
61SELECT
62 collection_id,
63 PatientID,
64 StudyInstanceUID,
65 SeriesInstanceUID,
66 Modality,
67 BodyPartExamined,
68 SeriesDescription,
69 gcs_url,
70 license_short_name
71FROM `bigquery-public-data.idc_current.dicom_all`
72WHERE Modality = 'CT'
73 AND BodyPartExamined = 'CHEST'
74LIMIT 10
75```

dicom_all

Primary table joining complete DICOM metadata with IDC-specific columns (collection_id, gcs_url, license). Contains exported DICOM fields plus collection and administrative metadata, one row per instance. 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
Raw lines 57 to 76
77### Derived Tables
79These 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.
81**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.
83**measurement_groups** — one row per SR TID1500 measurement group. The parent grouping for quantitative and qualitative measurements; links measurements to segmentations and source images.
85**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.
87**qualitative_measurements** — one row per coded evaluation within an SR TID1500 group. Contains assessed findings (malignancy likelihood, texture, margin type) using coded concept values.
89See the [Derived Tables: Detailed Documentation](#derived-tables-detailed-documentation) section below for schemas, column descriptions, and query examples.

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.

Raw lines 77 to 90
91### Collection Metadata
93**original_collections_metadata** - Collection-level descriptions
95```sql
96SELECT
97 collection_id,
98 cancer_types,
99 tumor_locations,
100 subjects,
101 src.source_doi,
102 src.modalities,
103 src.license.license_short_name
104FROM `bigquery-public-data.idc_current.original_collections_metadata`,
105UNNEST(sources) AS src
106WHERE cancer_types LIKE '%Lung%'
107```

Collection Metadata

original_collections_metadata - Collection-level descriptions

SELECT
  collection_id,
  cancer_types,
  tumor_locations,
  subjects,
  src.source_doi,
  src.modalities,
  src.license.license_short_name
FROM `bigquery-public-data.idc_current.original_collections_metadata`,
UNNEST(sources) AS src
WHERE cancer_types LIKE '%Lung%'
Raw lines 91 to 108
109## Common Query Patterns

Common Query Patterns

Raw lines 109 to 110
111### Find Collections by Criteria
113```sql
114SELECT
115 collection_id,
116 COUNT(DISTINCT PatientID) as patient_count,
117 COUNT(DISTINCT SeriesInstanceUID) as series_count,
118 ARRAY_AGG(DISTINCT Modality) as modalities
119FROM `bigquery-public-data.idc_current.dicom_all`
120WHERE BodyPartExamined LIKE '%BRAIN%'
121GROUP BY collection_id
122HAVING patient_count > 50
123ORDER BY patient_count DESC
124```

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
Raw lines 111 to 125
126### Get Download URLs
128```sql
129SELECT
130 SeriesInstanceUID,
131 gcs_url
132FROM `bigquery-public-data.idc_current.dicom_all`
133WHERE collection_id = 'rider_pilot'
134 AND Modality = 'CT'
135```

Get Download URLs

SELECT
  SeriesInstanceUID,
  gcs_url
FROM `bigquery-public-data.idc_current.dicom_all`
WHERE collection_id = 'rider_pilot'
  AND Modality = 'CT'
Raw lines 126 to 136
137### Find Studies with Multiple Modalities
139```sql
140SELECT
141 StudyInstanceUID,
142 ARRAY_AGG(DISTINCT Modality) as modalities,
143 COUNT(DISTINCT SeriesInstanceUID) as series_count
144FROM `bigquery-public-data.idc_current.dicom_all`
145GROUP BY StudyInstanceUID
146HAVING ARRAY_LENGTH(ARRAY_AGG(DISTINCT Modality)) > 1
147LIMIT 100
148```

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
Raw lines 137 to 149
150### License Filtering
152```sql
153SELECT
154 collection_id,
155 license_short_name,
156 COUNT(*) as instance_count
157FROM `bigquery-public-data.idc_current.dicom_all`
158WHERE license_short_name = 'CC BY 4.0'
159GROUP BY collection_id, license_short_name
160```

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
Raw lines 150 to 161
162### Find Segmentations with Source Images
164```sql
165SELECT
166 src.collection_id,
167 seg.SeriesInstanceUID as seg_series,
168 seg.SegmentedPropertyType,
169 src.SeriesInstanceUID as source_series,
170 src.Modality as source_modality
171FROM `bigquery-public-data.idc_current.segmentations` seg
172JOIN (SELECT DISTINCT SeriesInstanceUID, collection_id, PatientID, Modality
173 FROM `bigquery-public-data.idc_current.dicom_all`) src
174 ON seg.segmented_SeriesInstanceUID = src.SeriesInstanceUID
175WHERE src.collection_id = 'qin_prostate_repeatability'
176LIMIT 10
177```

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 (SELECT DISTINCT SeriesInstanceUID, collection_id, PatientID, Modality
      FROM `bigquery-public-data.idc_current.dicom_all`) src
  ON seg.segmented_SeriesInstanceUID = src.SeriesInstanceUID
WHERE src.collection_id = 'qin_prostate_repeatability'
LIMIT 10
Raw lines 162 to 178
179## Derived Tables: Detailed Documentation
181`dicom_all` is instance-level. The examples below project distinct series metadata before
182joining it to segment/measurement rows, preventing one measurement from being duplicated
183for every image slice. Retain SOPInstanceUID plus measurementGroup_number as measurement
184keys, and inspect units and derivation modifiers before comparing quantities.

Derived Tables: Detailed Documentation

dicom_all is instance-level. The examples below project distinct series metadata before joining it to segment/measurement rows, preventing one measurement from being duplicated for every image slice. Retain SOPInstanceUID plus measurementGroup_number as measurement keys, and inspect units and derivation modifiers before comparing quantities.

Raw lines 179 to 185
186### segmentations
188One 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.
190**Key columns:**
192| Column | Type | Description |
193|--------|------|-------------|
194| `SeriesInstanceUID` | STRING | SEG series UID |
195| `SOPInstanceUID` | STRING | SEG instance UID |
196| `PatientID` | STRING | Patient identifier |
197| `StudyInstanceUID` | STRING | Study UID |
198| `SegmentNumber` | INTEGER | Segment index within the SEG (starting from 1) |
199| `SegmentedPropertyCategory` | RECORD | Coded category (e.g., "Anatomical Structure", "Morphologically Altered Structure") |
200| `SegmentedPropertyType` | RECORD | Specific structure (e.g., "Liver", "Kidney", "Neoplasm") |
201| `AnatomicRegion` | RECORD | Optional anatomic region modifier |
202| `SegmentAlgorithmType` | STRING | AUTOMATIC, SEMIAUTOMATIC, or MANUAL |
203| `SegmentAlgorithmName` | STRING | Algorithm name (e.g., "TotalSegmentator") |
204| `TrackingUID` | STRING | Links segment to SR measurements |
205| `TrackingID` | STRING | Human-readable tracking label |
206| `segmented_SeriesInstanceUID` | STRING | Source image series UID — join to `dicom_all` to get collection/modality |
207| `viewer_url` | STRING | Direct IDC viewer link for the SEG |
209`SegmentedPropertyCategory` and `SegmentedPropertyType` are RECORD types with sub-fields `CodeValue`, `CodingSchemeDesignator`, and `CodeMeaning`. Use `.CodeMeaning` for human-readable filtering.
211**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 table when segment-level details are required. For screening series that contain a structure, the aggregated `SegmentedPropertyType_CodeMeanings` array in `seg_index` can suffice.
213**Discover what structures are segmented across IDC:**
215```sql
216SELECT
217 SegmentedPropertyCategory.CodeMeaning AS category,
218 SegmentedPropertyType.CodeMeaning AS structure,
219 SegmentAlgorithmType,
220 COUNT(DISTINCT SeriesInstanceUID) AS seg_series_count
221FROM `bigquery-public-data.idc_current.segmentations`
222GROUP BY 1, 2, 3
223ORDER BY seg_series_count DESC
224LIMIT 20
225```
227**Find all SEG series containing a specific structure, with source image context:**
229```sql
230SELECT
231 seg.SeriesInstanceUID AS seg_series,
232 seg.SegmentNumber,
233 seg.SegmentedPropertyType.CodeMeaning AS structure,
234 seg.SegmentAlgorithmType,
235 seg.SegmentAlgorithmName,
236 img.collection_id,
237 img.PatientID,
238 img.Modality,
239 seg.viewer_url
240FROM `bigquery-public-data.idc_current.segmentations` seg
241JOIN (SELECT DISTINCT SeriesInstanceUID, collection_id, PatientID, Modality
242 FROM `bigquery-public-data.idc_current.dicom_all`) img
243 ON seg.segmented_SeriesInstanceUID = img.SeriesInstanceUID
244WHERE seg.SegmentedPropertyType.CodeMeaning = 'Liver'
245 AND seg.SegmentAlgorithmType = 'AUTOMATIC'
246LIMIT 20
247```
249**Find all segment types present in a collection:**
251```sql
252SELECT
253 seg.SegmentedPropertyType.CodeMeaning AS structure,
254 seg.SegmentAlgorithmType,
255 COUNT(DISTINCT seg.SeriesInstanceUID) AS seg_series_count
256FROM `bigquery-public-data.idc_current.segmentations` seg
257JOIN (SELECT DISTINCT SeriesInstanceUID, collection_id, PatientID, Modality
258 FROM `bigquery-public-data.idc_current.dicom_all`) img
259 ON seg.segmented_SeriesInstanceUID = img.SeriesInstanceUID
260WHERE img.collection_id = 'nlst'
261GROUP BY 1, 2
262ORDER BY seg_series_count DESC
263```
265**Link segments to SR measurements using the referenced SEG instance and segment number:**
267```sql
268-- Find segments that have corresponding SR measurements
269SELECT
270 seg.SeriesInstanceUID AS seg_series,
271 seg.SegmentNumber,
272 seg.SegmentedPropertyType.CodeMeaning AS structure,
273 qm.Quantity.CodeMeaning AS measurement,
274 ROUND(CAST(qm.Value AS FLOAT64), 2) AS value,
275 qm.Units.CodeMeaning AS units
276FROM `bigquery-public-data.idc_current.segmentations` seg
277JOIN `bigquery-public-data.idc_current.quantitative_measurements` qm
278 ON seg.SOPInstanceUID = qm.segmentationInstanceUID
279 AND seg.SegmentNumber = qm.segmentationSegmentNumber
280WHERE seg.SegmentedPropertyType.CodeMeaning = 'Neoplasm'
281 AND qm.Quantity.CodeMeaning = 'Volume from Voxel Summation'
282LIMIT 10
283```
285---

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
SegmentAlgorithmNameSTRINGAlgorithm name (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 table when segment-level details are required. For screening series that contain a structure, the aggregated SegmentedPropertyType_CodeMeanings array in seg_index can suffice.

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 (SELECT DISTINCT SeriesInstanceUID, collection_id, PatientID, Modality
      FROM `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 (SELECT DISTINCT SeriesInstanceUID, collection_id, PatientID, Modality
      FROM `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 the referenced SEG instance and segment number:

-- 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.SOPInstanceUID = qm.segmentationInstanceUID
  AND seg.SegmentNumber = qm.segmentationSegmentNumber
WHERE seg.SegmentedPropertyType.CodeMeaning = 'Neoplasm'
  AND qm.Quantity.CodeMeaning = 'Volume from Voxel Summation'
LIMIT 10

Raw lines 186 to 286
287### quantitative_measurements
289One 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.
291**No compact idc-index equivalent.** Available in BigQuery and its public Parquet export.
293**Key columns:**
295| Column | Type | Description |
296|--------|------|-------------|
297| `SOPInstanceUID` | STRING | SR instance UID |
298| `SeriesInstanceUID` | STRING | SR series UID — join to `dicom_all` for collection/modality |
299| `SeriesDescription` | STRING | SR series description (e.g., "TotalSegmentator(v1.5.6) shape Measurements") |
300| `PatientID` | STRING | Patient identifier |
301| `measurementGroup_number` | INTEGER | Group index within the SR (0-based); join key with `measurement_groups` and `qualitative_measurements` |
302| `Quantity` | RECORD | What was measured — `CodeValue`, `CodingSchemeDesignator`, `CodeMeaning` (e.g., "Volume from Voxel Summation") |
303| `Value` | NUMERIC | The numeric measurement value |
304| `Units` | RECORD | Units — `CodeMeaning` (e.g., "cubic millimeter", "no units", "Hounsfield Unit") |
305| `derivationModifier` | RECORD | How the value was derived (e.g., "Mean", "Minimum", "Maximum") |
306| `lateralityModifier` | RECORD | Laterality qualifier |
307| `finding` | RECORD | What finding was measured — `CodeMeaning` (e.g., "Nodule", "Organ", "Anatomical Structure") |
308| `findingSite` | RECORD | Where the finding is — `CodeMeaning` (e.g., "Liver", "Esophagus", "Lung") |
309| `trackingIdentifier` | STRING | Human-readable tracking label (e.g., "Nodule 1", "Measurements group 26") |
310| `trackingUniqueIdentifier` | STRING | Tracking UID — links back to `segmentations.TrackingUID` |
311| `segmentationInstanceUID` | STRING | SOPInstanceUID of the referenced SEG object |
312| `segmentationSeriesUID` | STRING | SeriesInstanceUID of the referenced SEG object |
313| `segmentationSegmentNumber` | INTEGER | Segment number within the SEG — join to `segmentations.SegmentNumber` |
314| `sourceSegmentedSeriesUID` | STRING | Source image series — join to `dicom_all.SeriesInstanceUID` |
316**Discover available measurement types:**
318```sql
319SELECT
320 Quantity.CodeMeaning AS measurement,
321 Units.CodeMeaning AS units,
322 COUNT(*) AS measurement_count,
323 COUNT(DISTINCT SeriesInstanceUID) AS sr_series_count
324FROM `bigquery-public-data.idc_current.quantitative_measurements`
325GROUP BY 1, 2
326ORDER BY measurement_count DESC
327LIMIT 20
328```
330**Query measurements for a specific structure (e.g., liver volume across collections):**
332```sql
333SELECT
334 qm.PatientID,
335 ROUND(CAST(qm.Value AS FLOAT64) / 1000, 1) AS volume_cm3,
336 img.collection_id,
337 qm.segmentationSeriesUID
338FROM `bigquery-public-data.idc_current.quantitative_measurements` qm
339JOIN (SELECT DISTINCT SeriesInstanceUID, collection_id, PatientID, Modality
340 FROM `bigquery-public-data.idc_current.dicom_all`) img
341 ON qm.sourceSegmentedSeriesUID = img.SeriesInstanceUID
342WHERE qm.Quantity.CodeMeaning = 'Volume from Voxel Summation'
343 AND qm.findingSite.CodeMeaning = 'Liver'
344 AND qm.Units.CodingSchemeDesignator = 'UCUM'
345 AND qm.Units.CodeValue = 'mm3'
346ORDER BY volume_cm3 DESC
347LIMIT 20
348```
350**Retrieve all measurements for a specific patient and finding:**
352```sql
353SELECT
354 qm.measurementGroup_number,
355 qm.finding.CodeMeaning AS finding,
356 qm.findingSite.CodeMeaning AS finding_site,
357 qm.lateralityModifier.CodeMeaning AS laterality,
358 qm.Quantity.CodeMeaning AS feature,
359 ROUND(CAST(qm.Value AS FLOAT64), 3) AS value,
360 qm.Units.CodeMeaning AS units
361FROM `bigquery-public-data.idc_current.quantitative_measurements` qm
362WHERE qm.PatientID = 'LIDC-IDRI-0001'
363 AND qm.finding.CodeMeaning = 'Nodule'
364ORDER BY qm.measurementGroup_number, qm.Quantity.CodeMeaning
365```
367---

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 compact idc-index equivalent. Available in BigQuery and its public Parquet export.

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 (SELECT DISTINCT SeriesInstanceUID, collection_id, PatientID, Modality
      FROM `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'
  AND qm.Units.CodingSchemeDesignator = 'UCUM'
  AND qm.Units.CodeValue = 'mm3'
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

Raw lines 287 to 368
369### qualitative_measurements
371One 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)").
373**No compact idc-index equivalent.** Available in BigQuery and its public Parquet export.
375**Key columns:**
377| Column | Type | Description |
378|--------|------|-------------|
379| `SOPInstanceUID` | STRING | SR instance UID |
380| `SeriesInstanceUID` | STRING | SR series UID — join to `dicom_all` for collection/modality |
381| `PatientID` | STRING | Patient identifier |
382| `measurementGroup_number` | INTEGER | Group index within the SR — join key with `quantitative_measurements` |
383| `Quantity` | RECORD | What was assessed — `CodeMeaning` (e.g., "Malignancy", "Calcification", "Texture") |
384| `Value` | RECORD | The coded answer — `CodeMeaning` (e.g., "4 out of 5 (Moderately Suspicious for Cancer)") |
385| `finding` | RECORD | What finding was assessed — `CodeMeaning` (e.g., "Nodule") |
386| `findingSite` | RECORD | Anatomic site — `CodeMeaning` (e.g., "Lung") |
387| `trackingIdentifier` | STRING | Human-readable tracking label |
388| `segmentationInstanceUID` | STRING | SOPInstanceUID of the referenced SEG object |
389| `segmentationSeriesUID` | STRING | SeriesInstanceUID of the referenced SEG object |
390| `segmentationSegmentNumber` | INTEGER | Segment number within the referenced SEG |
391| `sourceSegmentedSeriesUID` | STRING | Source image series — join to `dicom_all.SeriesInstanceUID` |
393**Discover available qualitative features and their values:**
395```sql
396SELECT
397 Quantity.CodeMeaning AS feature,
398 Value.CodeMeaning AS assessed_value,
399 finding.CodeMeaning AS finding,
400 COUNT(*) AS count
401FROM `bigquery-public-data.idc_current.qualitative_measurements`
402GROUP BY 1, 2, 3
403ORDER BY count DESC
404LIMIT 20
405```
407**Find all nodules with a specific malignancy rating:**
409```sql
410SELECT
411 qm.PatientID,
412 qm.trackingIdentifier AS nodule_id,
413 qm.Value.CodeMeaning AS malignancy_rating,
414 img.collection_id
415FROM `bigquery-public-data.idc_current.qualitative_measurements` qm
416JOIN (SELECT DISTINCT SeriesInstanceUID, collection_id, PatientID, Modality
417 FROM `bigquery-public-data.idc_current.dicom_all`) img
418 ON qm.SeriesInstanceUID = img.SeriesInstanceUID
419WHERE qm.Quantity.CodeMeaning = 'Malignancy'
420 AND qm.Value.CodeMeaning LIKE '%Suspicious%'
421ORDER BY qm.PatientID
422LIMIT 20
423```
425---

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 compact idc-index equivalent. Available in BigQuery and its public Parquet export.

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
segmentationSegmentNumberINTEGERSegment number within the referenced SEG
sourceSegmentedSeriesUIDSTRINGSource image series — join to dicom_all.SeriesInstanceUID

Discover available qualitative features and their values:

SELECT
  Quantity.CodeMeaning AS feature,
  Value.CodeMeaning AS assessed_value,
  finding.CodeMeaning AS finding,
  COUNT(*) AS count
FROM `bigquery-public-data.idc_current.qualitative_measurements`
GROUP BY 1, 2, 3
ORDER BY count DESC
LIMIT 20

Find all nodules with a specific malignancy rating:

SELECT
  qm.PatientID,
  qm.trackingIdentifier AS nodule_id,
  qm.Value.CodeMeaning AS malignancy_rating,
  img.collection_id
FROM `bigquery-public-data.idc_current.qualitative_measurements` qm
JOIN (SELECT DISTINCT SeriesInstanceUID, collection_id, PatientID, Modality
      FROM `bigquery-public-data.idc_current.dicom_all`) img
  ON qm.SeriesInstanceUID = img.SeriesInstanceUID
WHERE qm.Quantity.CodeMeaning = 'Malignancy'
  AND qm.Value.CodeMeaning LIKE '%Suspicious%'
ORDER BY qm.PatientID
LIMIT 20

Raw lines 369 to 426
427### measurement_groups
429The parent table for TID1500 measurement groups. Each row represents one measurement group within an SR, with references to the segmentation and source image but without the individual measurement values. Use this table when you need to enumerate groups or check what was tracked, without pulling all measurement values.
431**Key columns:** `SOPInstanceUID`, `SeriesInstanceUID`, `PatientID`, `measurementGroup_number`, `trackingIdentifier`, `trackingUniqueIdentifier`, `finding`, `findingSite`, `segmentationInstanceUID`, `segmentationSeriesUID`, `segmentationSegmentNumber`, `sourceSegmentedSeriesUID`, `contentSequence` (raw SR content sequence).
433In most workflows, join `quantitative_measurements` and `qualitative_measurements` directly using `SOPInstanceUID` + `measurementGroup_number` rather than going through `measurement_groups`.
435---

measurement_groups

The parent table for TID1500 measurement groups. Each row represents one measurement group within an SR, with references to the segmentation and source image but without the individual measurement values. Use this table when you need to enumerate groups or check what was tracked, without pulling all measurement values.

Key columns: SOPInstanceUID, SeriesInstanceUID, PatientID, measurementGroup_number, trackingIdentifier, trackingUniqueIdentifier, finding, findingSite, segmentationInstanceUID, segmentationSeriesUID, segmentationSegmentNumber, sourceSegmentedSeriesUID, contentSequence (raw SR content sequence).

In most workflows, join quantitative_measurements and qualitative_measurements directly using SOPInstanceUID + measurementGroup_number rather than going through measurement_groups.


Raw lines 427 to 436
437### Combining quantitative and qualitative measurements
439The primary use case requiring both tables: correlate numeric features (volume, diameter) with coded assessments (malignancy, texture) for the same finding. Join on `SOPInstanceUID` + `measurementGroup_number`.
441**Example: LIDC-IDRI lung nodule analysis — malignancy rating with volume and diameter:**
443```sql
444SELECT
445 qual.PatientID,
446 qual.trackingIdentifier AS nodule_id,
447 qual.Value.CodeMeaning AS malignancy_rating,
448 ROUND(CAST(vol.Value AS FLOAT64), 1) AS volume_mm3,
449 ROUND(CAST(diam.Value AS FLOAT64), 1) AS diameter_mm
450FROM `bigquery-public-data.idc_current.qualitative_measurements` qual
451JOIN `bigquery-public-data.idc_current.quantitative_measurements` vol
452 ON qual.SOPInstanceUID = vol.SOPInstanceUID
453 AND qual.measurementGroup_number = vol.measurementGroup_number
454JOIN `bigquery-public-data.idc_current.quantitative_measurements` diam
455 ON qual.SOPInstanceUID = diam.SOPInstanceUID
456 AND qual.measurementGroup_number = diam.measurementGroup_number
457WHERE qual.Quantity.CodeMeaning = 'Malignancy'
458 AND vol.Quantity.CodeMeaning = 'Volume'
459 AND diam.Quantity.CodeMeaning = 'Diameter'
460ORDER BY qual.PatientID, qual.trackingIdentifier
461LIMIT 20
462```
464**Joining all three derived tables to get full segment context:**
466```sql
467SELECT
468 seg.SegmentedPropertyType.CodeMeaning AS structure,
469 qual.Quantity.CodeMeaning AS qualitative_feature,
470 qual.Value.CodeMeaning AS qualitative_value,
471 qm.Quantity.CodeMeaning AS quantitative_feature,
472 ROUND(CAST(qm.Value AS FLOAT64), 3) AS numeric_value,
473 qm.Units.CodeMeaning AS units,
474 img.collection_id
475FROM `bigquery-public-data.idc_current.segmentations` seg
476JOIN `bigquery-public-data.idc_current.qualitative_measurements` qual
477 ON seg.SOPInstanceUID = qual.segmentationInstanceUID
478 AND seg.SegmentNumber = qual.segmentationSegmentNumber
479JOIN `bigquery-public-data.idc_current.quantitative_measurements` qm
480 ON qual.SOPInstanceUID = qm.SOPInstanceUID
481 AND qual.measurementGroup_number = qm.measurementGroup_number
482JOIN (SELECT DISTINCT SeriesInstanceUID, collection_id, PatientID, Modality
483 FROM `bigquery-public-data.idc_current.dicom_all`) img
484 ON seg.segmented_SeriesInstanceUID = img.SeriesInstanceUID
485WHERE seg.SegmentedPropertyType.CodeMeaning = 'Neoplasm'
486LIMIT 10
487```

Combining quantitative and qualitative measurements

The primary use case requiring both tables: correlate numeric features (volume, diameter) with coded assessments (malignancy, texture) for the same finding. Join on SOPInstanceUID + measurementGroup_number.

Example: LIDC-IDRI lung nodule analysis — malignancy rating with volume and diameter:

SELECT
  qual.PatientID,
  qual.trackingIdentifier AS nodule_id,
  qual.Value.CodeMeaning AS malignancy_rating,
  ROUND(CAST(vol.Value AS FLOAT64), 1) AS volume_mm3,
  ROUND(CAST(diam.Value AS FLOAT64), 1) AS diameter_mm
FROM `bigquery-public-data.idc_current.qualitative_measurements` qual
JOIN `bigquery-public-data.idc_current.quantitative_measurements` vol
  ON qual.SOPInstanceUID = vol.SOPInstanceUID
  AND qual.measurementGroup_number = vol.measurementGroup_number
JOIN `bigquery-public-data.idc_current.quantitative_measurements` diam
  ON qual.SOPInstanceUID = diam.SOPInstanceUID
  AND qual.measurementGroup_number = diam.measurementGroup_number
WHERE qual.Quantity.CodeMeaning = 'Malignancy'
  AND vol.Quantity.CodeMeaning = 'Volume'
  AND diam.Quantity.CodeMeaning = 'Diameter'
ORDER BY qual.PatientID, qual.trackingIdentifier
LIMIT 20

Joining all three derived tables to get full segment context:

SELECT
  seg.SegmentedPropertyType.CodeMeaning AS structure,
  qual.Quantity.CodeMeaning AS qualitative_feature,
  qual.Value.CodeMeaning AS qualitative_value,
  qm.Quantity.CodeMeaning AS quantitative_feature,
  ROUND(CAST(qm.Value AS FLOAT64), 3) AS numeric_value,
  qm.Units.CodeMeaning AS units,
  img.collection_id
FROM `bigquery-public-data.idc_current.segmentations` seg
JOIN `bigquery-public-data.idc_current.qualitative_measurements` qual
  ON seg.SOPInstanceUID = qual.segmentationInstanceUID
  AND seg.SegmentNumber = qual.segmentationSegmentNumber
JOIN `bigquery-public-data.idc_current.quantitative_measurements` qm
  ON qual.SOPInstanceUID = qm.SOPInstanceUID
  AND qual.measurementGroup_number = qm.measurementGroup_number
JOIN (SELECT DISTINCT SeriesInstanceUID, collection_id, PatientID, Modality
      FROM `bigquery-public-data.idc_current.dicom_all`) img
  ON seg.segmented_SeriesInstanceUID = img.SeriesInstanceUID
WHERE seg.SegmentedPropertyType.CodeMeaning = 'Neoplasm'
LIMIT 10
Raw lines 437 to 488
489## Private DICOM Elements
491Private DICOM elements are vendor-specific attributes not defined in the DICOM standard. They often contain essential acquisition parameters (like diffusion b-values, gradient directions, or scanner-specific settings) that are critical for image interpretation and analysis.

Private DICOM Elements

Private DICOM elements are vendor-specific attributes not defined in the DICOM standard. They often contain essential acquisition parameters (like diffusion b-values, gradient directions, or scanner-specific settings) that are critical for image interpretation and analysis.

Raw lines 489 to 492
493### Understanding Private Elements
495**How private elements work:**
496- Private elements use odd-numbered group numbers (e.g., 0019, 0043, 2001)
497- Each vendor reserves blocks of 256 elements using Private Creator identifiers at positions (gggg,0010-00FF)
498- For example, GE uses Private Creator "GEMS_PARM_01" at (0043,0010) to reserve elements (0043,1000-10FF)
500**Standard vs. private tags:** Some parameters exist in both forms:
501| Parameter | Standard Tag | GE | Siemens | Philips |
502|-----------|--------------|-----|---------|---------|
503| Diffusion b-value | (0018,9087) | (0043,1039) | (0019,100C) | (2001,1003) |
504| Private Creator | - | Verify block reservation in the object | Verify block reservation in the object | Verify block reservation in the object |
506Older scanners typically populate only private tags; newer scanners may use standard tags. Always check both.
508**Challenges with private elements:**
509- Require manufacturer DICOM Conformance Statements to interpret
510- Tag meanings can change between software versions
511- May be removed during de-identification for HIPAA compliance
512- Value encoding varies (string vs. numeric, different units)

Understanding Private Elements

How private elements work:

  • Private elements use odd-numbered group numbers (e.g., 0019, 0043, 2001)
  • Each vendor reserves blocks of 256 elements using Private Creator identifiers at positions (gggg,0010-00FF)
  • For example, GE uses Private Creator "GEMS_PARM_01" at (0043,0010) to reserve elements (0043,1000-10FF)

Standard vs. private tags: Some parameters exist in both forms:

ParameterStandard TagGESiemensPhilips
Diffusion b-value(0018,9087)(0043,1039)(0019,100C)(2001,1003)
Private Creator-Verify block reservation in the objectVerify block reservation in the objectVerify block reservation in the object

Older scanners typically populate only private tags; newer scanners may use standard tags. Always check both.

Challenges with private elements:

  • Require manufacturer DICOM Conformance Statements to interpret
  • Tag meanings can change between software versions
  • May be removed during de-identification for HIPAA compliance
  • Value encoding varies (string vs. numeric, different units)
Raw lines 493 to 513
514### Accessing Private Elements in BigQuery
516Private elements are stored in the `OtherElements` column of `dicom_all` as an array of structs with `Tag` and `Data` fields.
518**Tag notation:** DICOM notation (0043,1039) becomes BigQuery format `Tag_00431039`.

Accessing Private Elements in BigQuery

Private elements are stored in the OtherElements column of dicom_all as an array of structs with Tag and Data fields.

Tag notation: DICOM notation (0043,1039) becomes BigQuery format Tag_00431039.

Raw lines 514 to 519
520### Private Element Query Patterns
522#### Discover Available Private Tags
524List all non-empty private tags for a collection:
526```sql
527SELECT
528 other_elements.Tag,
529 COUNT(*) AS instance_count,
530 ARRAY_AGG(DISTINCT other_elements.Data[SAFE_OFFSET(0)] IGNORE NULLS LIMIT 5) AS sample_values
531FROM `bigquery-public-data.idc_current.dicom_all`,
532 UNNEST(OtherElements) AS other_elements
533WHERE collection_id = 'qin_prostate_repeatability'
534 AND Modality = 'MR'
535 AND ARRAY_LENGTH(other_elements.Data) > 0
536 AND other_elements.Data[SAFE_OFFSET(0)] IS NOT NULL
537 AND other_elements.Data[SAFE_OFFSET(0)] != ''
538GROUP BY other_elements.Tag
539ORDER BY instance_count DESC
540```
542For a specific series:
544```sql
545SELECT
546 other_elements.Tag,
547 ARRAY_AGG(DISTINCT other_elements.Data[SAFE_OFFSET(0)] IGNORE NULLS) AS values
548FROM `bigquery-public-data.idc_current.dicom_all`,
549 UNNEST(OtherElements) AS other_elements
550WHERE SeriesInstanceUID = '1.3.6.1.4.1.14519.5.2.1.7311.5101.206828891270520544417996275680'
551 AND ARRAY_LENGTH(other_elements.Data) > 0
552 AND other_elements.Data[SAFE_OFFSET(0)] IS NOT NULL
553 AND other_elements.Data[SAFE_OFFSET(0)] != ''
554GROUP BY other_elements.Tag
555```
557To identify the Private Creator for a tag, look for the reservation element in the same group. For example, if you find `Tag_00431039`, the Private Creator is at `Tag_00430010` (the tag that reserves block 10xx in group 0043).
559#### Identify Equipment Manufacturer
561Determine what equipment produced the data to find the correct DICOM Conformance Statement:
563```sql
564SELECT DISTINCT Manufacturer, ManufacturerModelName
565FROM `bigquery-public-data.idc_current.dicom_all`
566WHERE collection_id = 'qin_prostate_repeatability'
567 AND Modality = 'MR'
568```
570#### Access Private Element Values
572Use `UNNEST` to access individual private elements:
574```sql
575SELECT
576 SeriesInstanceUID,
577 SeriesDescription,
578 other_elements.Data[SAFE_OFFSET(0)] AS b_value
579FROM `bigquery-public-data.idc_current.dicom_all`,
580 UNNEST(OtherElements) AS other_elements
581WHERE collection_id = 'qin_prostate_repeatability'
582 AND other_elements.Tag = 'Tag_00431039'
583LIMIT 10
584```
586#### Aggregate Values by Series
588Collect all unique values across slices in a series:
590```sql
591SELECT
592 SeriesInstanceUID,
593 ANY_VALUE(SeriesDescription) AS SeriesDescription,
594 ARRAY_AGG(DISTINCT other_elements.Data[SAFE_OFFSET(0)]) AS b_values
595FROM `bigquery-public-data.idc_current.dicom_all`,
596 UNNEST(OtherElements) AS other_elements
597WHERE collection_id = 'qin_prostate_repeatability'
598 AND other_elements.Tag = 'Tag_00431039'
599GROUP BY SeriesInstanceUID
600```
602#### Combine Standard and Private Filters
604Filter using both standard DICOM attributes and private element values:
606```sql
607SELECT
608 PatientID,
609 SeriesInstanceUID,
610 ANY_VALUE(SeriesDescription) AS SeriesDescription,
611 ARRAY_AGG(DISTINCT other_elements.Data[SAFE_OFFSET(0)]) AS b_values,
612 COUNT(DISTINCT SOPInstanceUID) AS n_slices
613FROM `bigquery-public-data.idc_current.dicom_all`,
614 UNNEST(OtherElements) AS other_elements
615WHERE collection_id = 'qin_prostate_repeatability'
616 AND Modality = 'MR'
617 AND other_elements.Tag = 'Tag_00431039'
618 AND ImageType[SAFE_OFFSET(0)] = 'ORIGINAL'
619 AND other_elements.Data[SAFE_OFFSET(0)] = '1400'
620GROUP BY PatientID, SeriesInstanceUID
621ORDER BY PatientID
622```
624#### Cross-Collection Analysis
626Survey usage of a private tag across all IDC collections:
628```sql
629SELECT
630 collection_id,
631 ARRAY_TO_STRING(ARRAY_AGG(DISTINCT other_elements.Data[SAFE_OFFSET(0)] IGNORE NULLS), ', ') AS values_found,
632 ARRAY_AGG(DISTINCT Manufacturer IGNORE NULLS) AS manufacturers
633FROM `bigquery-public-data.idc_current.dicom_all`,
634 UNNEST(OtherElements) AS other_elements
635WHERE other_elements.Tag = 'Tag_00431039'
636 AND other_elements.Data[SAFE_OFFSET(0)] IS NOT NULL
637 AND other_elements.Data[SAFE_OFFSET(0)] != ''
638GROUP BY collection_id
639ORDER BY collection_id
640```

Private Element Query Patterns

Discover Available Private Tags

List all non-empty private tags for a collection:

SELECT
  other_elements.Tag,
  COUNT(*) AS instance_count,
  ARRAY_AGG(DISTINCT other_elements.Data[SAFE_OFFSET(0)] IGNORE NULLS LIMIT 5) AS sample_values
FROM `bigquery-public-data.idc_current.dicom_all`,
  UNNEST(OtherElements) AS other_elements
WHERE collection_id = 'qin_prostate_repeatability'
  AND Modality = 'MR'
  AND ARRAY_LENGTH(other_elements.Data) > 0
  AND other_elements.Data[SAFE_OFFSET(0)] IS NOT NULL
  AND other_elements.Data[SAFE_OFFSET(0)] != ''
GROUP BY other_elements.Tag
ORDER BY instance_count DESC

For a specific series:

SELECT
  other_elements.Tag,
  ARRAY_AGG(DISTINCT other_elements.Data[SAFE_OFFSET(0)] IGNORE NULLS) AS values
FROM `bigquery-public-data.idc_current.dicom_all`,
  UNNEST(OtherElements) AS other_elements
WHERE SeriesInstanceUID = '1.3.6.1.4.1.14519.5.2.1.7311.5101.206828891270520544417996275680'
  AND ARRAY_LENGTH(other_elements.Data) > 0
  AND other_elements.Data[SAFE_OFFSET(0)] IS NOT NULL
  AND other_elements.Data[SAFE_OFFSET(0)] != ''
GROUP BY other_elements.Tag

To identify the Private Creator for a tag, look for the reservation element in the same group. For example, if you find Tag_00431039, the Private Creator is at Tag_00430010 (the tag that reserves block 10xx in group 0043).

Identify Equipment Manufacturer

Determine what equipment produced the data to find the correct DICOM Conformance Statement:

SELECT DISTINCT Manufacturer, ManufacturerModelName
FROM `bigquery-public-data.idc_current.dicom_all`
WHERE collection_id = 'qin_prostate_repeatability'
  AND Modality = 'MR'

Access Private Element Values

Use UNNEST to access individual private elements:

SELECT
  SeriesInstanceUID,
  SeriesDescription,
  other_elements.Data[SAFE_OFFSET(0)] AS b_value
FROM `bigquery-public-data.idc_current.dicom_all`,
  UNNEST(OtherElements) AS other_elements
WHERE collection_id = 'qin_prostate_repeatability'
  AND other_elements.Tag = 'Tag_00431039'
LIMIT 10

Aggregate Values by Series

Collect all unique values across slices in a series:

SELECT
  SeriesInstanceUID,
  ANY_VALUE(SeriesDescription) AS SeriesDescription,
  ARRAY_AGG(DISTINCT other_elements.Data[SAFE_OFFSET(0)]) AS b_values
FROM `bigquery-public-data.idc_current.dicom_all`,
  UNNEST(OtherElements) AS other_elements
WHERE collection_id = 'qin_prostate_repeatability'
  AND other_elements.Tag = 'Tag_00431039'
GROUP BY SeriesInstanceUID

Combine Standard and Private Filters

Filter using both standard DICOM attributes and private element values:

SELECT
  PatientID,
  SeriesInstanceUID,
  ANY_VALUE(SeriesDescription) AS SeriesDescription,
  ARRAY_AGG(DISTINCT other_elements.Data[SAFE_OFFSET(0)]) AS b_values,
  COUNT(DISTINCT SOPInstanceUID) AS n_slices
FROM `bigquery-public-data.idc_current.dicom_all`,
  UNNEST(OtherElements) AS other_elements
WHERE collection_id = 'qin_prostate_repeatability'
  AND Modality = 'MR'
  AND other_elements.Tag = 'Tag_00431039'
  AND ImageType[SAFE_OFFSET(0)] = 'ORIGINAL'
  AND other_elements.Data[SAFE_OFFSET(0)] = '1400'
GROUP BY PatientID, SeriesInstanceUID
ORDER BY PatientID

Cross-Collection Analysis

Survey usage of a private tag across all IDC collections:

SELECT
  collection_id,
  ARRAY_TO_STRING(ARRAY_AGG(DISTINCT other_elements.Data[SAFE_OFFSET(0)] IGNORE NULLS), ', ') AS values_found,
  ARRAY_AGG(DISTINCT Manufacturer IGNORE NULLS) AS manufacturers
FROM `bigquery-public-data.idc_current.dicom_all`,
  UNNEST(OtherElements) AS other_elements
WHERE other_elements.Tag = 'Tag_00431039'
  AND other_elements.Data[SAFE_OFFSET(0)] IS NOT NULL
  AND other_elements.Data[SAFE_OFFSET(0)] != ''
GROUP BY collection_id
ORDER BY collection_id
Raw lines 520 to 641
642### Workflow: Finding and Using Private Tags
6441. **Discover available private tags** in your collection using the discovery query above
6452. **Identify the manufacturer** to know which conformance statement to consult
6463. **Find the DICOM Conformance Statement** from the manufacturer's website (see Resources below)
6474. **Search the conformance statement** for the parameter you need (e.g., "b_value", "gradient") to understand what each tag contains
6485. **Convert tag to BigQuery format:** (gggg,eeee) → `Tag_ggggeeee`
6496. **Query and verify** results visually in the IDC Viewer

Workflow: Finding and Using Private Tags

  1. Discover available private tags in your collection using the discovery query above
  2. Identify the manufacturer to know which conformance statement to consult
  3. Find the DICOM Conformance Statement from the manufacturer's website (see Resources below)
  4. Search the conformance statement for the parameter you need (e.g., "b_value", "gradient") to understand what each tag contains
  5. Convert tag to BigQuery format: (gggg,eeee) → Tag_ggggeeee
  6. Query and verify results visually in the IDC Viewer
Raw lines 642 to 650
651### Data Quality Notes
653- Some private tags encode packed values (e.g., GE diffusion fields); values such as "1000000600" are not directly interpretable as b-values without the vendor convention
654- IDC data is de-identified; private tags containing PHI may have been removed or modified
655- The same tag may have different meanings across software versions
656- Inspect source headers and vendor documentation to validate private-tag interpretation; the [IDC Viewer](https://viewer.imaging.datacommons.cancer.gov/) provides complementary image QA

Data Quality Notes

  • Some private tags encode packed values (e.g., GE diffusion fields); values such as "1000000600" are not directly interpretable as b-values without the vendor convention
  • IDC data is de-identified; private tags containing PHI may have been removed or modified
  • The same tag may have different meanings across software versions
  • Inspect source headers and vendor documentation to validate private-tag interpretation; the IDC Viewer provides complementary image QA
Raw lines 651 to 657
658### Private Element Resources
660**Manufacturer DICOM Conformance Statements:**
661- [GE Healthcare MR](https://www.gehealthcare.com/products/interoperability/dicom/magnetic-resonance-imaging-dicom-conformance-statements)
662- [Siemens MR](https://www.siemens-healthineers.com/services/it-standards/dicom-conformance-statements-magnetic-resonance)
663- [Siemens CT](https://www.siemens-healthineers.com/services/it-standards/dicom-conformance-statements-computed-tomography)
665**DICOM Standard:**
666- [Part 5 Section 7.8 - Private Data Elements](https://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_7.8.html)
667- [Part 15 Appendix E - De-identification Profiles](https://dicom.nema.org/medical/dicom/current/output/chtml/part15/chapter_e.html)
669**Community Resources:**
670- [NAMIC Wiki: DWI/DTI DICOM](https://web.archive.org/web/20260520044207/https://www.na-mic.org/wiki/NAMIC_Wiki:DTI:DICOM_for_DWI_and_DTI) - comprehensive vendor comparison for diffusion imaging (archived; original NA-MIC wiki retired)
671- [StandardizeBValue](https://github.com/nslay/StandardizeBValue) - tool to extract vendor b-values to standard tags

Private Element Resources

Manufacturer DICOM Conformance Statements:

DICOM Standard:

Community Resources:

Raw lines 658 to 672
673## Using Query Results with idc-index
675Combine BigQuery for complex queries with idc-index for downloads (no GCP auth needed for downloads):
677```python
678from google.cloud import bigquery
679from idc_index import IDCClient
681# Initialize BigQuery client
682# Requires: the Python google-cloud-bigquery[pandas] package
683# Auth: gcloud auth application-default login
684# Project: executes the query and supplies its quota/billing context
685bq_client = bigquery.Client(project="your-gcp-project-id")
687# Query for series with specific criteria
688query = """
689SELECT DISTINCT SeriesInstanceUID
690FROM `bigquery-public-data.idc_current.dicom_all`
691WHERE collection_id = 'tcga_luad'
692 AND Modality = 'CT'
693 AND Manufacturer = 'GE MEDICAL SYSTEMS'
694LIMIT 100
695"""
697df = bq_client.query(query).to_dataframe()
698print(f"Found {len(df)} GE CT series")
700# Download with idc-index (no GCP auth required)
701idc_client = IDCClient()
702idc_client.download_from_selection(
703 seriesInstanceUID=list(df['SeriesInstanceUID'].values),
704 downloadDir="./tcga_luad_thin_ct"
706```

Using Query Results with idc-index

Combine BigQuery for complex queries with idc-index for downloads (no GCP auth needed for downloads):

from google.cloud import bigquery
from idc_index import IDCClient

# Initialize BigQuery client
# Requires: the Python google-cloud-bigquery[pandas] package
# Auth: gcloud auth application-default login
# Project: executes the query and supplies its quota/billing context
bq_client = bigquery.Client(project="your-gcp-project-id")

# Query for series with specific criteria
query = """
SELECT DISTINCT SeriesInstanceUID
FROM `bigquery-public-data.idc_current.dicom_all`
WHERE collection_id = 'tcga_luad'
  AND Modality = 'CT'
  AND Manufacturer = 'GE MEDICAL SYSTEMS'
LIMIT 100
"""

df = bq_client.query(query).to_dataframe()
print(f"Found {len(df)} GE CT series")

# Download with idc-index (no GCP auth required)
idc_client = IDCClient()
idc_client.download_from_selection(
    seriesInstanceUID=list(df['SeriesInstanceUID'].values),
    downloadDir="./tcga_luad_thin_ct"
)
Raw lines 673 to 707
708## Cost and Optimization
710**Pricing:** On-demand analysis is priced per TiB scanned; the reviewed US rate is $6.25/TiB
711with the first 1 TiB/month free. Verify the region and current
712[BigQuery pricing](https://cloud.google.com/bigquery/pricing) before estimating a job.
714**Minimize data scanned:**
715- Select only needed columns (not `SELECT *`)
716- Use partition/cluster filters when the table layout supports them
717- Use `LIMIT` to bound returned rows; it generally does not bound scanned bytes
718- Do not assume `dicom_all` is smaller than `dicom_metadata`; compare dry-run estimates
719- Preview queries in BQ console (free, shows bytes to scan)
721**Check cost before running:**
722```python
723query_job = bq_client.query(
724 query, job_config=bigquery.QueryJobConfig(dry_run=True, use_query_cache=False)
726print(f"Query will scan {query_job.total_bytes_processed / 1e9:.2f} GB")
727```
729For execution, set `maximum_bytes_billed` in `QueryJobConfig` to your budget in bytes;
730BigQuery refuses a job estimated to exceed it. See
731[estimate and control costs](https://docs.cloud.google.com/bigquery/docs/best-practices-costs).
733**Use materialized tables:** IDC provides both views (`table_name_view`) and materialized tables (`table_name`). Always use the materialized tables (faster, lower cost).

Cost and Optimization

Pricing: On-demand analysis is priced per TiB scanned; the reviewed US rate is $6.25/TiB with the first 1 TiB/month free. Verify the region and current BigQuery pricing before estimating a job.

Minimize data scanned:

  • Select only needed columns (not SELECT *)
  • Use partition/cluster filters when the table layout supports them
  • Use LIMIT to bound returned rows; it generally does not bound scanned bytes
  • Do not assume dicom_all is smaller than dicom_metadata; compare dry-run estimates
  • Preview queries in BQ console (free, shows bytes to scan)

Check cost before running:

query_job = bq_client.query(
    query, job_config=bigquery.QueryJobConfig(dry_run=True, use_query_cache=False)
)
print(f"Query will scan {query_job.total_bytes_processed / 1e9:.2f} GB")

For execution, set maximum_bytes_billed in QueryJobConfig to your budget in bytes; BigQuery refuses a job estimated to exceed it. See estimate and control costs.

Use materialized tables: IDC provides both views (table_name_view) and materialized tables (table_name). Always use the materialized tables (faster, lower cost).

Raw lines 708 to 734
735## Clinical Data
737Clinical data is in separate datasets with collection-specific tables. All clinical data available via `idc-index` is also available in BigQuery, with the same content and structure. Use BigQuery when you need complex cross-collection queries or joins that aren't possible with the local `idc-index` tables.
739**Datasets:**
740- `bigquery-public-data.idc_current_clinical` - current release (for exploration)
741- `bigquery-public-data.idc_v{version}_clinical` - versioned datasets (for reproducibility)
743Discover the current clinical table inventory rather than relying on a fixed count. Not all collections have clinical data (started in IDC v11).

Clinical Data

Clinical data is in separate datasets with collection-specific tables. All clinical data available via idc-index is also available in BigQuery, with the same content and structure. Use BigQuery when you need complex cross-collection queries or joins that aren't possible with the local idc-index tables.

Datasets:

  • bigquery-public-data.idc_current_clinical - current release (for exploration)
  • bigquery-public-data.idc_v{version}_clinical - versioned datasets (for reproducibility)

Discover the current clinical table inventory rather than relying on a fixed count. Not all collections have clinical data (started in IDC v11).

Raw lines 735 to 744
745### Clinical Table Naming
747Most collections use a single table: `<collection_id>_clinical`
749**Exception:** ACRIN collections use multiple tables for different data types (e.g., `acrin_6698_A0`, `acrin_6698_A1`, etc.).

Clinical Table Naming

Most collections use a single table: <collection_id>_clinical

Exception: ACRIN collections use multiple tables for different data types (e.g., acrin_6698_A0, acrin_6698_A1, etc.).

Raw lines 745 to 750
751### Metadata Tables
753Two metadata tables help navigate clinical data:
755**table_metadata** - Collection-level information:
756```sql
757SELECT
758 collection_id,
759 table_name,
760 table_description
761FROM `bigquery-public-data.idc_current_clinical.table_metadata`
762WHERE collection_id = 'nlst'
763```
765**column_metadata** - Attribute-level details with value mappings:
766```sql
767SELECT
768 collection_id,
769 table_name,
770 column,
771 column_label,
772 data_type,
773 values
774FROM `bigquery-public-data.idc_current_clinical.column_metadata`
775WHERE collection_id = 'nlst'
776 AND column_label LIKE '%stage%'
777```
779The `values` field contains observed attribute values with their descriptions (same as in `idc-index` clinical_index).

Metadata Tables

Two metadata tables help navigate clinical data:

table_metadata - Collection-level information:

SELECT
  collection_id,
  table_name,
  table_description
FROM `bigquery-public-data.idc_current_clinical.table_metadata`
WHERE collection_id = 'nlst'

column_metadata - Attribute-level details with value mappings:

SELECT
  collection_id,
  table_name,
  column,
  column_label,
  data_type,
  values
FROM `bigquery-public-data.idc_current_clinical.column_metadata`
WHERE collection_id = 'nlst'
  AND column_label LIKE '%stage%'

The values field contains observed attribute values with their descriptions (same as in idc-index clinical_index).

Raw lines 751 to 780
781### Common Clinical Queries
783**List available clinical tables:**
784```sql
785SELECT table_name
786FROM `bigquery-public-data.idc_current_clinical.INFORMATION_SCHEMA.TABLES`
787WHERE table_name NOT IN ('table_metadata', 'column_metadata')
788```
790**Find collections with specific clinical attributes:**
791```sql
792SELECT DISTINCT collection_id, table_name, column, column_label
793FROM `bigquery-public-data.idc_current_clinical.column_metadata`
794WHERE LOWER(column_label) LIKE '%chemotherapy%'
795```
797**Query clinical data for a collection:**
798```sql
799-- Example: NLST cancer staging data
800SELECT
801 dicom_patient_id,
802 clinical_stag,
803 path_stag,
804 de_stag
805FROM `bigquery-public-data.idc_current_clinical.nlst_canc`
806WHERE clinical_stag IS NOT NULL
807LIMIT 10
808```
810**Join clinical with imaging data:**
811```sql
812SELECT
813 d.PatientID,
814 d.StudyInstanceUID,
815 d.Modality,
816 c.clinical_stag,
817 c.path_stag
818FROM (SELECT DISTINCT collection_id, PatientID, StudyInstanceUID, Modality
819 FROM `bigquery-public-data.idc_current.dicom_all`) d
820JOIN `bigquery-public-data.idc_current_clinical.nlst_canc` c
821 ON d.PatientID = c.dicom_patient_id
822WHERE d.collection_id = 'nlst'
823 AND d.Modality = 'CT'
824 AND c.clinical_stag = '400' -- Stage IV
825LIMIT 20
826```
828**Cross-collection clinical search:**
829```sql
830-- Find all collections with staging information
831SELECT
832 cm.collection_id,
833 cm.table_name,
834 cm.column,
835 cm.column_label
836FROM `bigquery-public-data.idc_current_clinical.column_metadata` cm
837WHERE LOWER(cm.column_label) LIKE '%stage%'
838ORDER BY cm.collection_id
839```

Common Clinical Queries

List available clinical tables:

SELECT table_name
FROM `bigquery-public-data.idc_current_clinical.INFORMATION_SCHEMA.TABLES`
WHERE table_name NOT IN ('table_metadata', 'column_metadata')

Find collections with specific clinical attributes:

SELECT DISTINCT collection_id, table_name, column, column_label
FROM `bigquery-public-data.idc_current_clinical.column_metadata`
WHERE LOWER(column_label) LIKE '%chemotherapy%'

Query clinical data for a collection:

-- Example: NLST cancer staging data
SELECT
  dicom_patient_id,
  clinical_stag,
  path_stag,
  de_stag
FROM `bigquery-public-data.idc_current_clinical.nlst_canc`
WHERE clinical_stag IS NOT NULL
LIMIT 10

Join clinical with imaging data:

SELECT
  d.PatientID,
  d.StudyInstanceUID,
  d.Modality,
  c.clinical_stag,
  c.path_stag
FROM (SELECT DISTINCT collection_id, PatientID, StudyInstanceUID, Modality
      FROM `bigquery-public-data.idc_current.dicom_all`) d
JOIN `bigquery-public-data.idc_current_clinical.nlst_canc` c
  ON d.PatientID = c.dicom_patient_id
WHERE d.collection_id = 'nlst'
  AND d.Modality = 'CT'
  AND c.clinical_stag = '400'  -- Stage IV
LIMIT 20

Cross-collection clinical search:

-- Find all collections with staging information
SELECT
  cm.collection_id,
  cm.table_name,
  cm.column,
  cm.column_label
FROM `bigquery-public-data.idc_current_clinical.column_metadata` cm
WHERE LOWER(cm.column_label) LIKE '%stage%'
ORDER BY cm.collection_id
Raw lines 781 to 840
841### Key Column: dicom_patient_id
843Every clinical table includes `dicom_patient_id`, which matches the DICOM `PatientID` attribute in imaging tables. This is the join key between clinical and imaging data.
845**Note:** Clinical table schemas vary significantly by collection. Always check available columns first:
846```sql
847SELECT column_name, data_type
848FROM `bigquery-public-data.idc_current_clinical.INFORMATION_SCHEMA.COLUMNS`
849WHERE table_name = 'nlst_canc'
850```
852See `references/clinical_data_guide.md` for detailed workflows using `idc-index`, which provides the same clinical data without requiring BigQuery authentication.

Key Column: dicom_patient_id

Every clinical table includes dicom_patient_id, which matches the DICOM PatientID attribute in imaging tables. This is the join key between clinical and imaging data.

Note: Clinical table schemas vary significantly by collection. Always check available columns first:

SELECT column_name, data_type
FROM `bigquery-public-data.idc_current_clinical.INFORMATION_SCHEMA.COLUMNS`
WHERE table_name = 'nlst_canc'

See references/clinical_data_guide.md for detailed workflows using idc-index, which provides the same clinical data without requiring BigQuery authentication.

Raw lines 841 to 853
854## Important Notes
856- Tables are read-only (public dataset)
857- Schema changes between IDC versions
858- Use versioned datasets for reproducibility
859- Some DICOM sequences >15 levels deep are not extracted
860- Very large sequences (>1MB) may be truncated
861- Always check data license before use

Important Notes

  • Tables are read-only (public dataset)
  • Schema changes between IDC versions
  • Use versioned datasets for reproducibility
  • Some DICOM sequences >15 levels deep are not extracted
  • Very large sequences (>1MB) may be truncated
  • Always check data license before use
Raw lines 854 to 862
863## Common Errors
865**Issue: Billing must be enabled**
866- Cause: The requested operation exceeds sandbox capabilities or needs billing configuration
867- Solution: Check sandbox limits and project configuration, enable billing when needed, or use idc-index/public Parquet exports
869**Issue: Query exceeds resource limits**
870- Cause: Query scans too much data or is too complex
871- Solution: Inspect dry-run bytes and the plan, use applicable partition/cluster filters, and break into smaller queries; LIMIT alone is not a scan-cost control
873**Issue: Column not found**
874- Cause: Field name typo or not in selected table
875- Solution: Check table schema first with `INFORMATION_SCHEMA.COLUMNS`
877**Issue: Permission denied**
878- Cause: Not authenticated to Google Cloud
879- Solution: Run `gcloud auth application-default login` or set GOOGLE_APPLICATION_CREDENTIALS

Common Errors

Issue: Billing must be enabled

  • Cause: The requested operation exceeds sandbox capabilities or needs billing configuration
  • Solution: Check sandbox limits and project configuration, enable billing when needed, or use idc-index/public Parquet exports

Issue: Query exceeds resource limits

  • Cause: Query scans too much data or is too complex
  • Solution: Inspect dry-run bytes and the plan, use applicable partition/cluster filters, and break into smaller queries; LIMIT alone is not a scan-cost control

Issue: Column not found

  • Cause: Field name typo or not in selected table
  • Solution: Check table schema first with INFORMATION_SCHEMA.COLUMNS

Issue: Permission denied

  • Cause: Not authenticated to Google Cloud
  • Solution: Run gcloud auth application-default login or set GOOGLE_APPLICATION_CREDENTIALS
Raw lines 863 to 880
881## Resources
883- [Understanding the BigQuery DICOM schema](https://docs.cloud.google.com/healthcare-api/docs/how-tos/dicom-bigquery-schema)
884- [BigQuery Query Syntax](https://docs.cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax)
885- [Kaggle Intro to SQL](https://www.kaggle.com/learn/intro-to-sql)
886- [Sample BigQuery queries of IDC data](https://github.com/ImagingDataCommons/idc-bigquery-cookbook)