Appearance
Methodology
Data sources, data quality assessment, analysis approach, and query transparency. Every claim in this report is traceable to public data, and every limitation is stated explicitly.
Data Quality Assessment
Critical Context
The data underlying this report has significant gaps. All claims are made within these constraints. Improving data quality is the #1 priority for making stronger claims in future reports.
Current State
| Dimension | Status | Value | Impact on Report |
|---|---|---|---|
| Total MAUDE events | Good | 2.48M | Full history available |
| Device linkage | Critical gap | 18.9% linked | 81% of events can't be analyzed by brand |
| LLM extraction | Declining | 4-33% (recent months at 4%) | Root cause and failure mode data is sparse |
| Embedding coverage | Good | 87-91% | Vector search mostly works |
| BD Power line linked events | Small | ~150 events | Enough for pattern detection, not statistical power |
| Extracted BD events | Small | ~90 events | Failure mode data from a fraction of total |
What Each Gap Means
Device linkage at 18.9%: We can only analyze events that are linked to specific device brands. The 150 BD Power line events we analyze are from the 18.9% that are linked -- the remaining 81% of events may include more BD events we can't see. This means our event counts are underestimates, but our rate calculations (injury rate per event, failure mode distribution) are valid for the linked sample.
LLM extraction declining (4-33%): The structured fields we rely on (recall_risk, root_cause, failure_mode, user_error_blamed) come from LLM extraction of event narratives. With extraction coverage dropping to 4% in recent months, we have diminishing data for pattern analysis. The n=90 and n=38 samples cited in this report draw from the full extraction history, not just recent data.
Embedding coverage at 87-91%: Good enough for vector similarity search and clustering. The 9-13% gap mainly affects the most recent events.
Data Quality Gates
What you need before making specific types of claims:
Data Sources
FDA MAUDE Database
Source: FDA Manufacturer and User Facility Device Experience
Coverage: Medical device adverse event reports from 1992-present
Our dataset: 2.48M events (data through February 2026)
Access: Public data via openFDA API and bulk downloads
URL: https://www.accessdata.fda.gov/scripts/cdrh/cfdocs/cfmaude/search.cfm
CMS Provider Utilization
Source: Centers for Medicare & Medicaid Services (public files)
Coverage: Medicare Part B procedures by provider
Dataset used: 727K procedures, 299K providers (2022 data)
Note: This data comes from publicly available CMS files. It is not stored in our ClickHouse database. We reference it for market sizing only.
HCPCS codes used:
- 36568: PICC insertion (without imaging)
- 36569: PICC insertion (with imaging)
- 36572: CVC insertion (without imaging)
- 36573: CVC insertion (with imaging)
INFO
Medicare represents ~30% of total procedures. Actual market volume is 3-4x larger.
FDA Enforcement Data
Sources: Recall database, warning letters, enforcement actions
Our dataset: 57K enforcement actions in ClickHouse
Analysis Pipeline
openFDA API → ClickHouse (analytics engine)Process:
- Daily date ranges to avoid API 26K pagination limit
- Deduplication by MDR report key
- Device and manufacturer linking via brand name matching
- Geographic extraction from event narratives
- LLM extraction for structured fields (recall risk, root cause, failure mode)
- Vector embeddings for similarity search
Refresh: Weekly automated pipeline
LLM Extraction
Model: Gemini 2.0 Flash via Vertex AI Batch
Cost: ~$0.05 per 1M tokens (~$45 for 700K events)
Fields extracted:
| Field | Type | Purpose |
|---|---|---|
| recall_risk | high/medium/low | Recall prediction |
| root_cause | enum | Failure attribution |
| failure_mode | enum | Technical classification |
| user_error_blamed | boolean | Blame detection |
| user_error_justified | boolean | Blame validation |
| affects_other_units | boolean | Batch risk indicator |
| facility_name | text | Geographic intelligence |
| facility_state | text | Territory mapping |
Coverage: 30% of total events extracted (743K of 2.48M). Recent months at 4%.
Vector Embeddings
Model: Voyage-3 (1024-dimensional)
Use cases: Similar event clustering, failure pattern discovery, semantic search across narratives
Coverage: 87-91% of events embedded
Key Queries
BD Power Line Events
sql
SELECT d.brand_name, COUNT(*) as events,
countIf(resulted_in_injury) as injuries,
round(countIf(resulted_in_injury) * 100.0 / COUNT(*), 1) as injury_rate
FROM scanpath.events e
JOIN scanpath.devices d ON e.device_id = d.id
WHERE lower(d.brand_name) LIKE '%power%picc%'
OR lower(d.brand_name) LIKE '%power%glide%'
OR lower(d.brand_name) LIKE '%power%midline%'
GROUP BY d.brand_name
ORDER BY events DESCPowerGlide Timeline
sql
SELECT toYYYYMM(event_date) as month,
COUNT(*) as events,
countIf(resulted_in_injury) as injuries
FROM scanpath.events e
JOIN scanpath.devices d ON e.device_id = d.id
WHERE lower(d.brand_name) LIKE '%power%glide%'
AND event_date >= '2024-11-01'
GROUP BY month
ORDER BY monthFailure Mode Distribution
sql
SELECT failure_mode, COUNT(*) as n,
round(COUNT()*100.0/SUM(COUNT(*)) OVER(), 1) as pct
FROM scanpath.events e
JOIN scanpath.devices d ON e.device_id = d.id
WHERE llm_extracted = 1
AND (lower(d.brand_name) LIKE '%power%glide%'
OR lower(d.brand_name) LIKE '%power%picc%'
OR lower(d.brand_name) LIKE '%power%midline%')
GROUP BY failure_mode
ORDER BY n DESCRoot Cause Distribution
sql
SELECT root_cause, COUNT(*) as n,
round(COUNT()*100.0/SUM(COUNT(*)) OVER(), 1) as pct
FROM scanpath.events e
JOIN scanpath.devices d ON e.device_id = d.id
WHERE llm_extracted = 1
AND (lower(d.brand_name) LIKE '%power%glide%'
OR lower(d.brand_name) LIKE '%power%picc%'
OR lower(d.brand_name) LIKE '%power%midline%')
GROUP BY root_cause
ORDER BY n DESCUsing the ScanPath API
ScanPath provides a ClickHouse endpoint for live data queries. This report is a snapshot; the API gives you real-time access.
Connection
bash
# Basic query
curl -s "https://scanpath-clickhouse.fly.dev/?user=default&password=scanpath2025secure" \
--data "SELECT count() FROM scanpath.events"
# Query with format
curl -s "https://scanpath-clickhouse.fly.dev/?user=default&password=scanpath2025secure" \
--data "SELECT brand_name, count() as n FROM scanpath.events e
JOIN scanpath.devices d ON e.device_id = d.id
WHERE lower(d.brand_name) LIKE '%power%glide%'
GROUP BY brand_name FORMAT Pretty"Example: Monitor a Device Category
sql
-- Monthly event trend for any device
SELECT toYYYYMM(event_date) as month,
COUNT(*) as events,
countIf(resulted_in_injury) as injuries,
round(countIf(resulted_in_injury) * 100.0 / COUNT(*), 1) as injury_rate
FROM scanpath.events e
JOIN scanpath.devices d ON e.device_id = d.id
WHERE lower(d.brand_name) LIKE '%your_device%'
AND event_date >= today() - 365
GROUP BY month
ORDER BY monthExample: Find Emerging Signals
sql
-- Devices with accelerating event velocity (last 6 months vs prior 6 months)
SELECT d.brand_name,
countIf(event_date >= today() - 180) as recent_6mo,
countIf(event_date >= today() - 365 AND event_date < today() - 180) as prior_6mo,
round(countIf(event_date >= today() - 180) * 1.0 /
nullIf(countIf(event_date >= today() - 365 AND event_date < today() - 180), 0), 2) as velocity_ratio
FROM scanpath.events e
JOIN scanpath.devices d ON e.device_id = d.id
WHERE event_date >= today() - 365
GROUP BY d.brand_name
HAVING recent_6mo >= 10
ORDER BY velocity_ratio DESC
LIMIT 20Data Improvement Roadmap
In priority order:
| Priority | Gap | Current | Target | Impact |
|---|---|---|---|---|
| 1 | Device linkage | 18.9% | 95% | Unlock brand-level analysis for 81% more events |
| 2 | LLM extraction (recent) | 4% | 80%+ | Restore structured field coverage for new events |
| 3 | LLM extraction (backfill) | 30% overall | 80%+ | Larger samples for root cause and failure mode analysis |
| 4 | CMS data integration | Not in DB | In ClickHouse | Enable volume normalization and market sizing |
How to Run Improvements
bash
# Check current status
python -m clickhouse.pipeline.run_pipeline --status
# Run full pipeline (ingest + extract + embed)
python -m clickhouse.pipeline.run_pipeline --days 14
# Run extraction only (improve LLM coverage)
python -m clickhouse.pipeline.run_pipeline --extract-only --extract-limit 5000
# Run embeddings only
python -m clickhouse.pipeline.run_pipeline --embed-only --embed-limit 10000October 2025 PowerGlide Spike
The Pattern
| Month | Events | Injuries | Notes |
|---|---|---|---|
| Nov 2024 - Sep 2025 | 1-2/month | <2/month | Baseline |
| October 2025 | 40 | 30 | 40x baseline |
| November 2025 | 1 | 0 | Return to baseline |
Investigation
- 30 of 40 events reported on single day (October 22, 2025)
- LLM extraction on 4 sampled events: 2 explicitly mention "clinical trial" or "clinical study"
- November 2025: 1 event (baseline restored)
- Pattern matches published PowerGlide clinical study (ClinicalTrials.gov, 2019-2021 enrollment)
Conclusion
Clinical trial batch reporting, NOT sudden quality crisis. FDA requires all clinical trial adverse events be reported to MAUDE. Trials often batch-submit at study completion. Single-day spikes indicate batch submission, not field failures.
This spike is not used as competitive evidence in this report.
Limitations
Reporting Bias
Voluntary facility reports (except deaths) lead to underreporting. Estimates suggest 1-10% of actual events get reported to MAUDE. Facilities may not report if manufacturer convinces them it's "user error."
Attribution Uncertainty
Manufacturer investigations are self-interested (not independent). "Use-related" conclusions are not verified by FDA. Root cause fields reflect manufacturer claim, not verified fact.
Market Share Confound
This is the biggest limitation. Raw event counts are not comparable between manufacturers with different market share. BD's ~40% share means many more devices in the field than Stiletto's <5%. We mitigate this by using rates (injury rate per event) and patterns (failure mode distribution) rather than raw counts.
Device Linkage Gap
At 18.9% device linkage, 81% of events cannot be analyzed by brand. Our BD Power line sample (~150 linked events) may not represent the full population of BD events in MAUDE.
LLM Extraction Reliability
Structured fields (root cause, failure mode, user error) are extracted by an LLM from narrative text. These are interpretations, not verified facts. We cite sample sizes to make the extraction basis clear.
Injury Severity
Outcome detail varies by report quality. "Injury" is binary (yes/no), not scaled by severity. A minor bruise and a surgical retrieval both count as "injury."
Interpretation Guidelines
- Event counts are proxies -- Higher counts may indicate market success (more devices in field), not just safety issues
- Patterns matter more than absolutes -- Same failure mode across multiple facilities signals design issue, not user error
- User error claims need scrutiny -- Manufacturer investigations are self-interested; look for pattern evidence
- Absence of evidence is not evidence of absence -- Low event counts may reflect low market share, underreporting, or newness
- Temporal spikes require investigation -- Distinguish clinical trial batches from actual field failure increases
- Sample sizes determine confidence -- n=26 gives directional signal; n=500 gives statistical confidence
Reproducibility
All queries can be run against the ScanPath ClickHouse instance:
bash
curl -s "https://scanpath-clickhouse.fly.dev/?user=default&password=scanpath2025secure" \
--data "SELECT count() FROM scanpath.events"Database Statistics (February 2026)
| Table | Row Count | Coverage |
|---|---|---|
| events | 2,480,000+ | 1992-2026 |
| devices | 45,000+ | Brand names |
| manufacturers | 8,000+ | Company names |
| enforcement_actions | 57,000+ | Recalls, warnings |
| LLM extractions | 743,000 | 30% of events |
| Embeddings | 2,250,000 | 87-91% of events |
Transparency Commitment
All claims in this report are traceable to:
- FDA MAUDE database (public)
- CMS Medicare data (public)
- FDA 510(k) clearances (public)
- Clinical trial registry (ClinicalTrials.gov, public)
Independent verification: Any claim can be verified by searching MAUDE directly. All SQL queries are provided for reproducibility. Raw data access available via ClickHouse endpoint.
What this report does:
- Uses rates and patterns, not raw counts
- Includes sample sizes with every claim
- States limitations prominently
- Separates what the data shows from what it doesn't
What this report does NOT do:
- Compare raw event counts between products with different market share
- Use clinical trial spikes as field failure evidence
- Claim Stiletto is "proven safer" (insufficient field data)
- Hide data gaps or limitations
Last updated: February 2026