Skip to main content
PVgenix logo
Guide

Signal Detection: From First Principles to a Validated Signal

One course, three depths. Climb from first principles to disproportionality statistics and Bayesian methods, learn exactly how to build and optimise the detection pipeline, and get the cross-testing angles that prove every number is correct — with a live calculator and an animated end-to-end flow.

PVgenix24 min read
🎓

Foundations

Start at zero. Every term defined, then built up to disproportionality and Bayesian methods — with a worked example you can follow.

</>

Build track

How the data flows, the schema, the engine pseudocode, the workflow state machine, performance and the pitfalls to avoid.

🔬

QC & review

How to test the system from every angle — positive/negative controls, hand-calc cross-checks, data integrity, edge cases — so no detail is wrong.

Module 01

What signal detection is

Finding a new safety concern about a medicine — earlier and more reliably than reading cases one by one ever could.

The definition

A signal is information suggesting a new potentially causal association — or a new aspect of a known one — between a medicine and an event, serious enough to warrant verification. The key word is suggests: a signal is a hypothesis, never a proven fact.

Why it exists

A trial has a few thousand patients. After launch, millions use the drug in combinations, doses and conditions no trial covered. Rare and delayed harms surface only there. Signal detection watches that real-world population continuously.

🎓For the newcomer · start here

Think of it like antivirus for a medicine. Antivirus doesn't wait for one expert to inspect every file — it scans everything and raises alerts on suspicious patterns. Signal detection scans every drug–event combination and raises alerts (SDRs) on statistically suspicious ones. A human then confirms or dismisses each alert.

The one line to remember

Signal detection generates hypotheses. It never, by itself, proves a drug caused harm — proof comes later, in validation and assessment.

Module 02 · Foundations

PV vocabulary & the anatomy of a case

Before any maths, you must speak the language. These are the words every PV person uses daily — and every developer must model correctly in the database.

TermPlain meaningWhy it matters for detection
AE (Adverse Event)Any bad medical happening during treatment — cause not yet known.Raw input; not yet linked to the drug.
ADR (Adverse Drug Reaction)An AE where a causal link to the drug is at least suspected.The thing detection is ultimately about.
ICSRIndividual Case Safety Report — one patient's full report.The unit that gets counted.
PT / MedDRAThe standard coded term for the event (Preferred Term).Disproportionality is computed on Drug × PT.
SeriousnessDeath, life-threatening, hospitalisation, disability, congenital anomaly, or an IME.Serious cases get priority & expedited reporting.
ExpectednessIs the event already in the drug's label?Unexpected + serious = highest signal interest.
CausalityHow likely the drug caused it (WHO-UMC / Naranjo scales).Central to validating a signal.

The MedDRA hierarchy foundational

Events are coded into a 5-level tree. Detection usually runs at PT level, but you can roll up to spot broader patterns.

SOC — System Organ Class
broadest — e.g. “Hepatobiliary disorders”
HLGT — High Level Group Term
“Hepatic and hepatobiliary disorders”
HLT — High Level Term
“Hepatocellular damage”
PT — Preferred Term ★
the detection unit — “Hepatotoxicity”
LLT — Lowest Level Term
verbatim — “liver got damaged”
</>For the developer · data model note

Store the LLT (what the reporter actually wrote) and the mapped PT — never overwrite the verbatim. Detection queries group by PT; audits and re-coding need the original LLT. Model the hierarchy as a versioned lookup (MedDRA updates ~twice a year), so historical cases keep the coding valid at their time.

Causality scales intermediate

WHO-UMC

A categorical ladder a reviewer assigns: Certain → Probable → Possible → Unlikely → Conditional → Unassessable. Uses time relationship, dechallenge, rechallenge, plausibility, and alternative causes.

Naranjo

A 10-question scored questionnaire → total maps to Definite (≥9) / Probable (5–8) / Possible (1–4) / Doubtful (≤0). More reproducible because it's numeric.

Module 03

Where it sits: the lifecycle

This settles the most common confusion. Quantitative detection runs after case processing — because it needs coded, de-duplicated, locked data to count.

Case ReceiptICSR arrivesCase Processingdedup · code · lockSafety Databaselocked casesSignal Detectionquant + qualValidate → Assess→ PSUR / RMP

1 · Coding needed

PRR/ROR use Drug × PT pairs. No MedDRA coding → no pair → no maths.

2 · De-duplication

A case counted twice inflates n → false signal. Dedup is a processing job.

3 · Locked data

Run on half-finished cases and the result can't be defended.

Exception — remember

A single case can be a signal (e.g. agranulocytosis with positive rechallenge). But even it must be processed and coded first — so processing always precedes detection. Here detection is qualitative, not counting.

Module 04

Data — where to take it, and why

Two families of data feed detection. They answer different questions — so both are needed, not alternatives.

OWN ICSR CASES

Your own processed cases

Answers: “how many / how often?” — the numbers.

  • Where: your safety database — locked, coded ICSRs.
  • Why: your own denominator lets you compute disproportionality reliably.
  • Benefit: statistical proof a regulator can re-check line by line.
EXTERNAL SOURCES

The world outside your DB

Answers: “is it real? why? did anyone see it first?”

  • Where: FAERS, WHO VigiBase, PubMed, regulatory sites, social media.
  • Why: early warning + causal evidence your counts can't give.
  • Benefit: confirmation & context — defensible from two directions.
Refinement most people miss

External is not all qualitative. FAERS & VigiBase are external quantitative confirmation (they run disproportionality too). Literature, mechanism and social listening are the qualitative layer.

Module 05 · Core method

Quantitative methods — with a live calculator

Every disproportionality method starts from one small table. Understand it once, and the rest is just different ways of dividing it.

The 2×2 contingency table foundational

This event
Other events
This drug
a
b
Other drugs
c
d

a = reports of this drug with this event — the cell we care about. b, c, d from the rest of the database.

The four core measures

# Proportional Reporting Ratio
PRR = [a/(a+b)] / [c/(c+d)]
# Reporting Odds Ratio
ROR = ad / bc
# chi-square (screen with PRR)
χ² = N(ad−bc)² / [(a+b)(c+d)(a+c)(b+d)]
# Information Component (Bayesian)
IC = log₂( a·N / [(a+b)(a+c)] )

Worked example — follow every step intermediate

Scenario: Drug X, event “hepatotoxicity”. Database has 100,000 reports. Drug X appears in 500 reports; 25 of them mention hepatotoxicity. Across all other drugs, 300 reports mention hepatotoxicity.

Fill the table: a=25, b=475, c=300, d=99200 (N = 100,000)
PRR numerator: a/(a+b) = 25/500 = 0.050
PRR denominator: c/(c+d) = 300/99500 = 0.00302
PRR = 0.050 / 0.00302 ≈ 16.6 → well above 2 ✓
ROR = ad/bc = (25×99200)/(475×300) ≈ 17.4
Checks: a=25 ≥ 3 ✓ · PRR ≥ 2 ✓ · χ² ≫ 4 ✓this is an SDR
Do not stop here

16.6 looks dramatic, but it's still only a statistical alert. Maybe those 25 cases are duplicates, or all from one hospital, or the drug is genuinely hepatotoxic. Validation decides — not the ratio.

Live calculator — try your own numbers

Change a, b, c, d and watch every measure and every signal flag update. Newcomers build intuition; reviewers use it to hand-verify the platform's output.

PRR16.58
ROR17.40
χ² (chi-square)339.03
IC (log₂)3.94
a ≥ 3 PRR ≥ 2 χ² ≥ 4
⚑ SDR — investigate (not yet a confirmed signal)
MethodFamilyTypical signal thresholdBest when…
PRRFrequentistPRR ≥ 2, χ² ≥ 4, a ≥ 3first-line screening
RORFrequentistlower 95% CI > 1adjusting for confounders
IC / BCPNNBayesianIC025 > 0rare events (shrinkage)
EBGM (MGPS)BayesianEB05 > 2large DBs, many pairs

Advanced caveats every reviewer checks advanced

Masking / competition bias

A very frequent drug–event pair can hide (mask) a real signal for another pair by inflating the background. Re-run with the dominant pair removed.

Small-count instability

At a=3–5, PRR swings wildly. Bayesian shrinkage (IC/EBGM) pulls weak estimates toward the null — fewer false alarms.

Confounding & stratification

Age, sex, indication can drive a spike. Stratify (compute within subgroups) before believing the headline ratio.

Module 06

Qualitative & single-case detection

Not every signal is a number. Some of the most important are caught by a trained eye on a single well-documented case.

Designated Medical Events (DME/IME)

A short watch-list so serious and so drug-specific that one credible case opens a signal — no waiting for counts.

  • Agranulocytosis
  • Stevens–Johnson syndrome / TEN
  • Anaphylaxis
  • Rhabdomyolysis
  • PML
  • Acute liver failure, torsades de pointes…

What makes one case a signal

Clinical judgement, not arithmetic. A reviewer weighs:

  • Positive rechallenge — event returned on restart.
  • Dechallenge — resolved when stopped.
  • Biological plausibility — a known mechanism fits.
  • No confounders — nothing else explains it.
  • Temporal link — timing fits exposure.
Teaching point

This is why detection is quantitative AND qualitative. The platform surfaces the maths; a PV reviewer catches rare, high-value single-case signals the maths misses because n is too small.

Module 07

External sources & the routing rule

The same source — PubMed or social media — plays two roles. Fetch once, route twice. This is the design decision that keeps the platform clean.

Same source, two purposes

In intake, PubMed answers “is there a reportable case here?” In the signal app, it answers “what evidence supports or detects this drug–event signal?” Same source, different purpose — not a duplicate.

Social media listening

Most posts aren't valid ICSRs. But a sudden spike of one symptom for one drug is an emerging-issue hint — an aggregate signal, not a case. It feeds the emerging-issue tracker, not the case queue.

The rule that prevents duplication

Intake creates cases. The Signal app only reads, links and assesses. If the Signal app finds a new reportable case, one button sends it to intake — it never creates the case itself.

</>For the developer · one ingestion, one router

Build a single ingestion worker that fetches & de-duplicates once, writing to a raw documents store. A separate classifier/router reads each doc and emits two independent events: case.candidate → intake and evidence.linked → signal. Never let the signal service write to the case table — enforce it with DB permissions, not just code review.

Module 08 · The critical refinement

SDR → validated signal

The single most important idea in this course: a statistical spike is not a confirmed signal. It is an SDR — an alert to investigate.

SDRstatistical alertValidationreal? dedup? known?Assessmentcausality · evidenceDecisionaction / no actionValidatedSignal
STEP 1 · VALIDATE

Is it real?

Check underlying cases: duplicates removed? coding right? already labelled? confounder? Many SDRs die here — correctly.

STEP 2 · ASSESS

What does it mean?

Full causality review — Bradford Hill, mechanism, external data, benefit-risk. This is where literature earns its place.

STEP 3 · ACT

What do we do?

Label update, PSUR/PBRER entry, RMP change, or documented “no action”. Every step auditable.

Never say this to a regulator

“PRR spiked, so the drug causes X.” Wrong. Correct: “A statistical SDR was raised; on validation and assessment it was [confirmed / refuted / already known].” The word SDR keeps you honest and defensible.

Module 09 · Signature

The complete flow — animated

Everything above in one moving picture. Two feeder lanes merge into detection; a spike becomes an amber SDR; validation turns it green.

OWN ICSR CASES · QUANTITATIVESourcesreports · lit · HCPIntake +ProcessingSafety DBlocked · codedEXTERNAL SOURCES · CONFIRM + EVIDENCEFAERS · VigiBasequant confirmationLiterature · Socialevidence · spikeSignal DetectionPRR·ROR·IC·EBGM+ clinical reviewSDRstat. alertValidatereal? known?AssesscausalityDecisionPSUR·RMPlabel
Own cases (quantitative)External + SDR alertValidated → decision
Module 10 · Developer deep track

How to build it — the engineering

The same flow as a technical pipeline. This section is written for the developer who must design, build and optimise it.

1

Data layer — analysis-ready store

Locked ICSRs materialised into an aggregate table keyed by drug × PT × period. Multi-tenant, partitioned by tenant, so each client's counts stay isolated.

PostgreSQL · LIST partition by tenant_id · materialised views
2

Disproportionality engine

On each data-lock it rebuilds the 2×2 for every drug–event pair and computes PRR, ROR, IC/BCPNN, EBGM with CIs and the a ≥ 3 guard.

FastAPI service · vectorised NumPy/Pandas · scheduled per data-lock
3

Qualitative & AI layer

DME/IME watch-list auto-flags single serious cases. AI assists triage — clustering narratives, summarising, drafting the assessment — but a qualified reviewer always decides.

LLM triage · narrative clustering · human-in-the-loop
4

External connectors

Shared ingestion pulls FAERS/VigiBase, PubMed and social once; the router splits case-worthy content to intake, evidence/trend to the Signal Evidence Explorer.

ingestion workers · dedup · dual-router (intake vs evidence)
5

Workflow & audit

SDR → validation → assessment → decision is a state machine. Every transition is e-signed and time-stamped for 21 CFR Part 11 / EU Annex 11.

state machine · e-signature · immutable audit trail

The aggregate schema intermediate

-- one row per drug × PT × period × tenant; rebuilt at each data-lock
CREATE TABLE signal_counts (
  tenant_id   uuid       NOT NULL,   -- partition key, tenant isolation
  data_lock   date       NOT NULL,   -- the cut-off this snapshot belongs to
  drug_id     bigint     NOT NULL,
  pt_code     int        NOT NULL,   -- MedDRA Preferred Term
  a int, b int, c int, d int,          -- the 2x2 cells
  prr numeric, ror numeric, chi2 numeric,
  ic025 numeric, eb05 numeric,         -- lower bounds drive the flag
  is_sdr boolean,                       -- a>=3 AND prr>=2 AND chi2>=4
  PRIMARY KEY (tenant_id, data_lock, drug_id, pt_code)
) PARTITION BY LIST (tenant_id);

The engine, in pseudocode intermediate

def run_disproportionality(tenant, data_lock):
    df = load_locked_cases(tenant, data_lock)      # coded, de-duplicated only
    N  = len(df)
    for (drug, pt) in distinct_pairs(df):
        a = count(df, drug=drug, pt=pt)
        b = count(df, drug=drug) - a
        c = count(df, pt=pt) - a
        d = N - a - b - c
        if a < 3:                              # stability guard — skip / flag low
            store(drug, pt, a,b,c,d, is_sdr=False); continue
        prr  = (a/(a+b)) / (c/(c+d))
        ror  = (a*d) / (b*c)
        chi2 = N*(a*d-b*c)**2 / ((a+b)*(c+d)*(a+c)*(b+d))
        ic   = log2( a*N / ((a+b)*(a+c)) )         # Bayesian variants add shrinkage
        is_sdr = (prr >= 2) and (chi2 >= 4) and (a >= 3)
        store(drug, pt, a,b,c,d, prr, ror, chi2, ic, is_sdr)
</>Best practices & pitfalls
  • Precompute at data-lock, don't compute on read. Dashboards read a snapshot table; never recalculate 2×2s on every page load.
  • Guard divide-by-zero. Zero cells (a=0 or b=0) break ROR. Use continuity corrections or skip with a clear flag.
  • Numeric precision. Use decimal/float64 carefully; huge d values × tiny ratios lose precision if you multiply in the wrong order.
  • Store the 2×2, not just the ratio. An auditor must reproduce your number from a, b, c, d — keep them.
  • Never mutate a locked snapshot. A new data-lock = a new row set. History stays immutable for audit.

The workflow state machine advanced

# every transition writes an immutable, e-signed audit row
DETECTED ▶ SDR_RAISED ▶ UNDER_VALIDATION ─┬▶ REFUTED         (closed, reason logged)
                                               ├▶ ALREADY_KNOWN   (closed, ref to label)
                                               └▶ VALIDATED ▶ UNDER_ASSESSMENT
                                                                    ├▶ NO_ACTION   (documented)
                                                                    └▶ ACTION ▶ LABEL / PSUR / RMP
Module 11 · PV expert deep track

How to test it — cross-check from every angle

This section is for the reviewer who must prove the system is correct before anyone trusts a signal from it. Test from six independent angles — if all pass, no single detail is wrong.

🔬The testing philosophy

You are not testing whether the drug is dangerous — you are testing whether the tool computes and records correctly. That's computer system validation (OQ/PQ): feed known inputs, compare to a known-correct expected output, and prove reproducibility. If the maths is right on controlled data, you can trust it on real data.

The six cross-testing angles

AngleQuestion it answersHow to test
1 · Math correctnessDoes PRR/ROR/IC match a hand calculation?Feed the worked example (a=25…); expect PRR≈16.6, ROR≈17.4.
2 · Positive controlDoes a known true signal fire?Inject a well-established drug–ADR pair; it must raise an SDR.
3 · Negative controlDoes noise stay quiet?Inject a random, implausible pair; it must NOT raise an SDR.
4 · Edge casesa<3, zero cells, single case?Confirm a<3 is not flagged; zero cell doesn't crash; DME single case still flags qualitatively.
5 · Data integrityAre duplicates & coding clean?Seed known duplicates; confirm counts don't inflate. Check PT roll-up.
6 · Reproducibility & auditSame input → same output, fully traced?Re-run the same data-lock; numbers identical; audit trail shows who/when/what.

A sample OQ test script

#Test stepInputExpected resultPass?
1Compute PRR on known 2×225,475,300,99200PRR 16.5–16.7
2Low-count guarda=2Not flagged as SDR
3Zero-cell handlingb=0Graceful (no crash / correction)
4Positive control firesknown ADR pairis_sdr = true
5Negative control silentrandom pairis_sdr = false
6Re-run reproducibilitysame data-lock ×2identical outputs
🔬ALCOA+ — the data-integrity backbone

Every number the system produces must be Attributable, Legible, Contemporaneous, Original, Accurate — plus Complete, Consistent, Enduring, Available. Concretely: who ran the analysis and when, the exact input snapshot, the original verbatim preserved, the calculation reproducible, nothing silently overwritten. If any of these fails, the signal isn't defensible no matter how correct the maths.

Common errors to catch in review

Denominator uses total reports vs total drug exposures (be consistent) · duplicates not removed before counting · threshold applied without the a≥3 guard · masking not checked on high-volume pairs · a confirmed signal stated as causal without assessment · audit trail missing the “no action” decisions.

Module 12

Golden rules — recap

If a new joiner remembers only these, they can already read a signal the correct way.

  • Processing first, detection after — quantitative maths needs coded, de-duplicated, locked cases.
  • A spike is an SDR, not a signal — an alert to investigate, never a conclusion.
  • Detection is quantitative AND qualitative — one strong DME case can be a signal at n = 1.
  • Own cases measure; external confirms — FAERS/VigiBase confirm quantitatively, literature/social give evidence.
  • Statistics needs enough n — for rare events, lean on qualitative + external early warning.
  • Fetch once, route twice — the Signal app reads and links; only intake creates cases.
  • Prove it before you trust it — positive/negative controls, hand-calc cross-check, reproducibility, ALCOA+.
  • Everything is audit-trailed — if it isn't recorded and e-signed, to a regulator it didn't happen.

Frequently asked questions

Common questions