The Day QC Hands Back Table 14.1.2
The Day QC Hands Back Table 14.1.2
Quality Control (QC) Pass 2 finding
Demographic TLF (Tables, Listings, Figures)
Program counted exposure · shell = safety set
Mock shell = contract — QC flags violations
SHIPPING PATH — FOUR-PASS QC
ODS = Output Delivery System · RTF = Rich Text Format
READ MOCK
SHELL
PROGRAM
PLAN
PROC REPORT
RTF + ODS
FOUR-PASS
QC CHECK
Open with a real work situation: a demographics table comes back from QC with a Pass 2 denominator finding. Frame the lesson as the full shipping path from mock shell to RTF under four-pass QC.
Speaker notes
Table 14.1.2 just came back from Quality Control, or QC, with a pass two finding: the column denominator doesn't match the population statement on the mock shell. Our program counted subjects with study exposure, but the shell was written against the safety population. Both numbers can be defensible, yet only one is the deliverable. That is the whole game of Tables, Listings, and Figures, or TLF, outputs: the mock shell is a contract, and most late-stage QC findings are contract violations, not math errors. Map the shipping path: read the mock shell, write the program plan, build the table with PROC REPORT and the Output Delivery System, or ODS, to Rich Text Format, or RTF, then run the four-pass QC with discrepancy records. This lesson uses simulated teaching data, and every row shown traces to the subject-level analysis dataset extract.
The Mock Shell Is a Contract
The Mock Shell Is a Contract
| Shell element | Commitment QC can check |
|---|---|
| Output ID | Filing location; SAP (Statistical Analysis Plan) traceability |
| Title block | Exact wording; named population |
| Denominators (N=) | Which N feeds each percentage; header N wrong → every percentage beneath inherits the defect |
| Footnotes | Methods; dictionary versions; SAP section references; wrong dictionary version = wrong-% severity |
| Page conventions | Repeated headers; (Continued) markers on later pages |
Most late-stage QC findings are contract violations,
not arithmetic errors — audit the output against the shell.
Teach the anatomy of a mock shell and why every element in it is a checkable commitment that QC can be run against.
Speaker notes
A mock shell is not decoration; it is a contract you can be checked against. It fixes the title block, column headers, a sample row or two, and the footnotes. The output identifier ties the shell to its filing location and the Statistical Analysis Plan (SAP) traceability. The title block commits you to exact wording and a named population. Each denominator N tells quality control (QC) which N feeds every percentage, and if the header N is wrong, every percentage beneath it inherits that defect. Footnotes carry methods, dictionary versions, and SAP section references, and a wrong dictionary version is the same severity as a wrong percentage. Most late-stage QC findings are contract violations, not arithmetic errors.
Read the Shell Into a Program Plan
Read the Shell Into a Program Plan
1 · Population flag — ADSL (subject-level)
2 · Data source
3 · Row structure
4 · Column blocks & denominators
5 · Statistics & formats
6 · Footnotes & pagination
Step 1 = highest-risk decision
Population flag → ADSL · SAF / ITT / completers
Record the population statement verbatim.
Skipping it → denominator-class defect
Denominators: ADSL under flag — never event data.
Decimal precision is a shell property
Set it at shell read — not at output formatting.
Show the fixed sequence of decisions a programmer must make from the shell before writing any code, with the population step as the most failure-prone one.
Speaker notes
Before you write any code, read the shell as a program plan with six decisions in a fixed order. Step one is the population flag in the ADSL, the Subject-Level Analysis Dataset, choosing between the Safety Analysis Set, or SAF, the Intention-to-Treat, or ITT, population, or completers, and you record the population statement verbatim. This is the highest-risk decision because skipping it produces the classic denominator-class defect, the most common serious discrepancy on a first Quality Control, or QC, cycle. Denominators always come from ADSL under that flag, never from the event dataset, because an event-dataset count silently means subjects with events. Then fix row structure, column blocks, statistics, formats, footnotes, and pagination in that order. Remember, decimal precision is a shell property, not a programmer preference, so set it when reading the shell, not when formatting the output.
Checkpoint: Shell Contract Basics
1 When you review a reporting shell for a table, listing, or figure (TLF), which shell element is the contract for the output file location and traceability back to the Statistical Analysis Plan (SAP)?
2 For study 043-18101, a safety-population table counts subjects with adverse events from the adverse-event analysis dataset (ADAE). For each treatment column, the column percent is n (%) subjects with the event. What is the correct source of the denominator for each column percentage?
3 When you read a TLF shell into a program plan before writing code, which decisions are correct to make at that stage? Select all that apply. (select all that apply, then Check)
Speaker notes
Let's check your understanding of the shell contract for tables, listings, or figures, or TLF. First, when you review a TLF shell, which element is the contract for the output file location and traceability back to the Statistical Analysis Plan, or SAP? The correct answer is B, the Output ID, because the Output ID carries the filing location and points back to the SAP item; titles, footnotes, and row labels define content or formatting, not the file-name or location contract. Second, for the safety-population table in the demo, event counts come from the adverse-event analysis dataset, or ADAE, and each column percent is n (%) subjects with the event. The correct denominator source is B: subject-level analysis dataset, or ADSL, records with the safety population, or SAF, flag, SAFFL='Y', grouped by the same treatment variable used in each column, because safety-population percentages must not be derived from event rows or from all randomized subjects regardless of the population flag. Third, when you read a TLF shell into a program plan before writing code, the correct choices are A, B, and D: confirm the ADSL population flag such as SAFFL='Y' before subsetting event records; decide whether zero-count or missing row categories must still be displayed as part of the shell contract; and translate the shell's row order and column layout into the sort keys and column mapping for PROC REPORT. Choosing a SAS version or an Output Delivery System, or ODS, Rich Text Format, or RTF, bookmark style is an environment or formatting decision, not a first-read shell-contract decision.
Walkthrough: Five ADSL Rows Become a Table
Walkthrough: Five ADSL Rows Become a Table
| ADSL (Subject-Level Analysis Dataset) extract · study 043-18101 · site 74001 | ||||
|---|---|---|---|---|
| USUBJID | SAFFL | TRT01PN | SEX | AGEGR1 |
| 043-18101-74001-001 | Y | 1.0 | M | ≥65 |
| 043-18101-74001-002 | Y | 1.0 | M | <65 |
| 043-18101-74001-003 | Y | 1.0 | M | ≥65 |
| 043-18101-74001-004 | Y | 2.0 | F | <65 |
| 043-18101-74001-005 | Y | 3.0 | F | <65 |
• Safety set: SAFFL = Y on 5/5 rows → N = 5
• TRT01PN column Ns → 3 / 1 / 1 (not pooled)
• Counts read from rows: SEX M/F 3/2; AGEGR1 ≥65/<65 2/3
• Trap: DLTEVLFL=Y filter keeps only 004 and 005
• Kept N=2 is DLT-evaluable, not the safety deliverable
Real-data walkthrough: step through the five ADSL extract rows from study 043-18101, tracing population flags, treatment denominators, and simple demographic counts directly to each row.
Speaker notes
Five rows from the ADSL, the Subject-Level Analysis Dataset, become this table header. SAFFL, the safety population flag, is Y on all five rows, so the safety analysis set denominator is N equals 5. Treatment column denominators come from TRT01PN: subjects 001 through 003 give N equals 3, subject 004 gives one, subject 005 gives one, so three, one, one, not a pooled number. Read straight from the rows, SEX M counts three and SEX F counts two; AGEGR1 greater than or equal to 65 counts two, below 65 counts three. Now the trap: filtering DLTEVLFL equals Y, the dose-limiting toxicity evaluable flag, keeps only subjects 004 and 005, so N equals 2, which is defensible for a DLT-evaluable population but not the safety deliverable your shell names.
Table Pattern: PROC REPORT With Pre-Built Cells
PROC REPORT With Pre-Built Cells
1 · Analysis blocks
2 · Pre-built cell strings
3 · Render — ODS RTF
• SQL: N per arm & level + denom
• MEANS: mean, SD, median, min, max
• Canonical macro: AGE / HEIGHT / WEIGHT
• Extract walkthrough: AGE
• Cell: n (pct%)
• pct = count over arm denom
• ADSL is the denominator source
• Never another dataset
• One PROC REPORT on stacked blocks
• Layout: (block trt01a, col_stat)
• Render under ODS RTF
• QC reads the shipped string
/* macro title shell contract — inside the ODS RTF destination */
title1 "Protocol 043-18101 (simulated teaching data)";
title2 "Table 14.1.2 Summary of Demographics";
TLF = Tables, Listings, and Figures · ADSL = Subject-Level Analysis Dataset
ODS = Output Delivery System · RTF = Rich Text Format · QC = Quality Control
Teach the demographics-table pattern using canonical snippet 08: analysis cells are built into display strings before PROC REPORT renders them under ODS RTF, so what QC checks is what ships.
Speaker notes
This scene shows the table pattern: PROC REPORT with pre-built cells. Analysis blocks are stacked, then one PROC REPORT lays them out by block, treatment arm, and column stat. For categorical variables, SQL builds the N per arm and level plus the denominator from the Subject-Level Analysis Dataset, ADSL; the cell is always a count over that treatment denominator, never another dataset. For continuous variables, PROC MEANS per arm writes mean, SD, median, min, max; the canonical macro loops AGE, HEIGHT, WEIGHT, but our extract has only AGE and SEX. Because numbers ship as pre-built strings, what Quality Control, QC, reads in the Rich Text Format, RTF, is exactly what the program wrote — no surprises. The title block inside the Output Delivery System, ODS, is the shell contract in code, including the simulated teaching data note and the table title.
Listings and Figures: Shape and Failure Modes
Listings and Figures — Shape and Failure Modes
TLF = Tables, Listings, and Figures · ADSL = Subject-Level Analysis Dataset · SAF = Safety Analysis Set
ODS = Output Delivery System · RTF = Rich Text Format · QC = Quality Control
Listings — Shell Shape
Figures — Shell Shape
QC Failure Modes
• Rows, not summaries
• One record per row
• Sort order per the shell
• Page breaks from the program
• (Continued) header repeats
• Join analysis to ADSL
• Population flag gates axes
• SAF subjects only
• N in the title or legend
• Placement per the shell
• Wrong SAF population
• N counts missing
• Groups unlabelled
• Order overrides the shell
• “Looks reasonable” fails
Scope: ADSL-only extract — no AE or lab rows. Listing/figure patterns are taught as rules (no fabricated patient rows).
Teach the structural rules for listings and figures and their characteristic QC failure modes. Because the teaching extract contains ADSL rows only, this coverage is conceptual, not a data walkthrough.
Speaker notes
Listings and figures are part of the Tables, Listings, and Figures (TLF) deliverable. A listing shows records, not summaries: one record per row, sort order exactly as the shell specifies, and page breaks controlled by the program. Repeated headers on continued pages are expected; reviewers look for the exact (Continued) convention from the shell. For figures, join the analysis data to the Subject-Level Analysis Dataset (ADSL) under the population flag, so only Safety Analysis Set (SAF) subjects reach an axis; place per-group N in the title or legend as the shell directs. Figures often fail Quality Control (QC) on boring details: wrong population, missing N counts, unlabelled groups, or category order that looks reasonable instead of following the shell. Remember, our extract has no adverse event or lab rows, so we teach these patterns as rules without fabricating patient rows.
ODS RTF Delivery Details
ODS RTF Delivery Details
1. Titles/footnotes in ODS RTF block
2. styles.learn_tlf — fonts/margins once
3. ODS escape + PAGEOF footnote → Page x of y
4. Precision per shell — QC Pass 4 verifies
5. Path/version footnote gives traceability
ODS = Output Delivery System · RTF = Rich Text Format
TLF = Tables, Listings & Figures
source: study 043-18101 · snippets 08-tlf-rtf-proc-report / 09-qc-proc-compare
Teach the delivery conventions that separate a submitted TLF from a draft: titles and footnotes inside the ODS block, a reusable style template, reliable page numbering, and traceability.
Speaker notes
We deliver through the Output Delivery System, or ODS, into Rich Text Format, or RTF. Titles and footnotes live in the ODS RTF block using title and footnote statements, so they repeat per page as specified. One style template, styles.learn_tlf based on styles.rtf, sets fonts and margins once for every Tables, Listings and Figures, or TLF, output: Courier New 8 point data, Arial 9 point titles. For Page x of y, use an ODS escape character and the PAGEOF construct in a footnote — reliable and safer than counting pages yourself. Precision follows the shell, so a one-decimal mean next to an integer count is a shell property, not a preference — Pass 4 of Quality Control, or QC, verifies that. A footnote with the program path or version makes each RTF traceable to its program and data cut.
The Four-Pass QC Order and the Discrepancy Record
The Four-Pass QC Order
and the Discrepancy Record
| QC pass | Focus | Gate / why this order |
|---|---|---|
| 1 · Format | Titles, headers, footnotes, pagination | Cheapest — failure stops later passes |
| 2 · Data definitions | Population flag, denominators, visit windows per SAP | Rules must be stable before a re-run |
| 3 · Numbers | Independent recomputation; one row per block or separate QC program | Only pass needing real independent work |
| 4 · Consistency | Same N everywhere; same terminology, decimals | 09-qc-proc-compare: absolute 1e-9; issue count 0 |
• Four passes, cheapest first; each pass gates the next.
• 09-qc-proc-compare: method=absolute, criterion=1e-9; issue count 0 — log is evidence.
• Record before fix: output ID, shell ref, observed vs expected, disposition; no silent fix.
• Agent: require 3 rejected mismatches; verified 2026-08-30 (time-sensitive).
Teach the cheapest-first QC pass order, how each pass gates the next, and the absolute discipline of recording discrepancies before resolving them.
Speaker notes
The four-pass quality control (QC) order goes cheapest first: format, covering titles, headers, footnotes, and pagination, then data definitions: population flag, denominators, and visit windows per the statistical analysis plan. Each pass gates the next, so never recompute an output that would fail an earlier check. Pass three is the only pass needing real independent work: recompute one row per block, or write a separate QC program. Pass four checks consistency: same N, same terminology, same decimals. Snippet 09-qc-proc-compare sets the release gate: method equals absolute, criterion 1e-9, issue count zero; any nonzero count blocks release, and the log itself is evidence. Record before fixing: output ID, shell reference, observed versus expected, and a named disposition with approver; for agents, require the three closest mismatches they rejected; this was verified 2026-08-30, so treat it as time-sensitive.
Hands-On: Sort the Findings Into QC Passes
Hands-on interactive — if it does not load, open the paired article and try the exercise there.
Speaker notes
This last exercise is hands-on, on the website at jaimeyan.com/learn, so you can pause the video and work through it yourself. You will practice the core industrial judgment of quality control, or QC: given a defect in an output compared with the shell, pick the cheapest QC pass that would actually catch it, whether that pass is format, data definitions, numbers, or consistency. Try it right after the video, and check your reasoning against the pass logic we just walked through.
Final Check: Ship the Deliverable
1 During quality control (QC) review of a tables, listings, and figures (TLF) output produced through the Output Delivery System (ODS) to rich-text format (RTF), page 2 repeats the column heading instead of showing a '(Continued)' marker. Which QC pass should catch this issue?
2 For a safety-analysis-set (SAF) percentage by treatment group, what is the correct denominator source?
3 In the fixed QC order, Pass 2 checks the output's data definitions against the statistical analysis plan (SAP). Which of the following are checked in Pass 2? Select all that apply. (select all that apply, then Check)
4 Before a TLF output is shipped, the fixed QC workflow must finish. In your own words: (a) list the four QC passes in cheapest-first order and explain why that order is fixed. (b) Suppose a table shell and the output code disagree—for example, the shell calls for a safety-population denominator but the code uses an event dataset. What written record must be created before you edit the code, and what four items must that record contain? (reflect, then reveal)
Reveal analysis
Speaker notes
This is the final check: ship the deliverable. During quality control (QC) review of a tables, listings, and figures (TLF) output made with the Output Delivery System (ODS) in rich-text format (RTF), page 2 repeats the column heading instead of showing a '(Continued)' marker. The answer is A, Pass 1, the format and visual review done before any numeric recomputation, because this is a layout defect, not a data-definition or numeric defect. For a safety-analysis-set (SAF) percentage by treatment group, the correct denominator source is option C: subjects in the subject-level analysis dataset (ADSL) where the safety flag SAFFL = 'Y' in that treatment group. The SAF is a subject-level population, so denominators must count safety-evaluable subjects from ADSL, not events or exposures. In the fixed QC order, Pass 2 checks the output's data definitions against the statistical analysis plan (SAP). The answers are A, B, and C: the SAP population flag such as SAFFL = 'Y' for the SAF, column denominators from the correct ADSL safety population rather than an event dataset, and visit windows and analysis-visit assignments per the SAP. Pass 2 is the data-definition pass; formatting and page breaks belong to Pass 1, and numeric recomputation is later. Before shipping, the fixed quality-control workflow is Pass 1, format and visual review against the shell; Pass 2, data-definition check of population flags, denominators, and visit windows against the SAP; Pass 3, independent numeric recomputation; and Pass 4, final comparison, for example with PROC COMPARE; this order is fixed cheapest-first because you catch cheap format and definition defects before paying for recomputation, and if the shell and code disagree you must first create a discrepancy record containing observed, expected, disposition, and approver.
Summary: Ship the Contract, Never the Defensible Number
Ship the Contract, Never the Defensible Number
1 · Shell = contract — check output ID, titles, column blocks, denominators, footnotes, and population statement.
2 · Pull denominators from ADSL under the population flag — never the event dataset; render precision per shell incl. n(100).
3 · Tables ship on PROC REPORT cells + column Ns; listings on sort, page breaks, repeated headers; figures on join + stated group n.
4 · QC runs cheapest-first: format → definitions → numbers → consistency — each gate precedes the next; never recompute a failed output.
5 · Every discrepancy gets a record: shell reference, observed, expected, disposition, approver — never fix silently.
6 · Practice with “From Mock Shell to RTF” + the TLF QC checklist; this lesson used real ADSL rows — listing/figure walks were conceptual.
Close the lesson by restating the durable takeaways, naming the data gap honestly, and linking back to the paired article and QC skill for continued practice.
Speaker notes
The mock shell is a contract, so check output ID, titles, column blocks, denominators, footnotes, and the population statement. Pull denominators from the Subject-Level Analysis Dataset, or ADSL, under the population flag, never the event dataset, and honor the shell's precision, including the n (100) convention. Tables ship on pre-formatted PROC REPORT cells; listings on sort, page breaks, repeated headers, and (Continued); figures on the population join and group n. Quality Control, or QC, runs cheapest-first: format, definitions, numbers, consistency; each pass gates the next, never recompute a failed output. Every discrepancy gets a record with shell reference, observed, expected, disposition, and approver; never fix silently. Continue with the paired article From Mock Shell to Rich Text Format (RTF) and its Table, Listing, and Figure (TLF) QC checklist; this lesson used real ADSL-only rows, so listing and figure walks were conceptual.