Case Reports
Structured Case Reports / Case Related Data

Input documents containing case narratives, investigation reports, and case-related data as PDFs.

Layer 1
Ingestion
Text Extraction & Normalization
# Extract text from PDF
text = extract_pdf_text("case_report.pdf")
# Normalize format
normalized = normalize_text(text)
# Returns: Clean, structured text ready for processing
  • PDF text extraction using pdfplumber
  • Organization detection from filenames
  • Batch processing support
  • Input validation and error handling
Layer 2
Processing
Feature Extraction & Case Schema

How it's done: Hybrid approach using regex patterns for structured data (demographics, platforms, evidence, prosecution) and pattern-based matching for semantic features (severity indicators, case topics, severity phrases). ML/NER extraction supplements with law enforcement agencies, ages, dates, and locations. Text is cleaned (URL removal, artifact normalization), cases are batched by temporal patterns, and unique case IDs are generated.

# 1. Clean URLs and artifacts
cleaned_text = clean_urls_from_text(raw_text)

# 2. Batch cases by month patterns
cases = case_batching(cleaned_text, org_name="azicac")

# 3. Extract features (regex + patterns + NER)
features = extract_features(case)
# Regex: Demographics, platforms, evidence, prosecution
# Patterns: Severity indicators, case topics, phrases
# NER: Law enforcement agencies, ages, dates, locations
Demographics
Victim age, victim_gender, count
Perpetrator age, perpetrator_gender, RSO status
Platforms
Social media, online methods, communication channels
Severity
Infant, very young, rape, production indicators
Topics
Hands-on, possession, online-only, family, stranger
Prosecution
Charges, booking status, outcomes
Evidence
Images, videos, storage volume, messages
Layer 3
Storage
Case store, cache, and graph artifacts
# Cases: PostgreSQL in production (Railway); SQLite locally (caselinker.db)
storage = CaseStorage() # DATABASE_URL → Postgres, else SQLite
storage.store_case(case)

# Optional Redis (REDIS_URL): /api/cases, facet-tree, cluster-groups, automated-analysis
# Ontology artifacts on disk: ontology/graph_output/*.ttl|.jsonld · ontology/PACER/
# RDF store: Oxigraph (backend only) behind OXIGRAPH_URL → public GET|POST /sparql
  • Deployed on Railway with PostgreSQL; SQLite for local development
  • Normalized columns plus raw_data / extracted_features JSON
  • Optional Redis shared cache for quicker API responses
  • CASE/UCO/CAC graphs on disk; Oxigraph is the SPARQL backend
Layer 4
Analysis
Filtering, facets, clustering, triage, agents, and CASE/UCO/CAC graphs

How it's done: Deterministic mapping turns CaseLinker features into CAC entities (no custom predicates). Per-case Turtle + JSON-LD land in ontology/graph_output/, pass SHACL, and load into Oxigraph (SPARQL backend). The analyst UI is Ontology & Graphs at /patterns. PACER investigations are separate CASE-UCO SDK graphs under ontology/PACER/.

# Tag intersection · facet tree · five cluster families + Jaccard
cases = return_tagged_cases(all_cases, tags)
# HTTP: /api/facet-tree, /api/cluster-groups, /api/automated-analysis

triaged = triage_cases(cases) # rules + sklearn bundle
# /api/triage-model-corpus · /api/triage-live (paste-in)

# Agents: MCP at /mcp (SSE) and /mcp-http/ — corpus, facets, triage, case2cac graphs

# features → CAC mapping → RDF (TTL / JSON-LD) → SHACL → Oxigraph
python ontology/features_to_cac.py <case_id>
GET|POST /sparql
# Explorer APIs: /api/ontology/cases · /lookup · /pacer · /merged
# Live store: 10,282 press-release graphs · ~297 PACER KG graphs
  • Tag intersection, navigable facet tree, and cohort APIs over the live DB
  • Clustering + automated analysis; rule-based and ML triage
  • MCP tool surface for agents (same FastAPI app; SPARQL via /sparql or CASE/UCO SDK)
  • Vocabulary: CASE / UCO / CAC (Project VIC on the Cyber Domain Ontology stack)
  • Oxigraph stores RDF; users browse and compare via /patterns + query via /sparql
  • PACER court-record KGs and Q1–Q3 evidence pages under /patterns/questions/
Layer 5
Visualization
Analyst UI: HTML tabs + JSON / SPARQL APIs
# FastAPI serves visualization/*.html; browser fetches /api/* and /sparql.

# Tabs: Visualization · Analysis · Clusters · Stats · Search · Lifecycle
# Query · Triage · Case Studies · Tech Landscape · LLM · Sources
# Audit · Ontology & Graphs (/patterns) · Look Under the Hood

# Graph explorer pools: Compare 200 · Universe ~2k · Big Bang · Analysis
  • Same nav across pages; Redis-backed caches where they help
  • Ontology & Graphs: CAC lookup, press-release + PACER corpora, compare/single canvas
  • Modular: new views sit on the same storage, APIs, and SPARQL store

Open source on GitHub

Crash course View on GitHub