spb/cancerindex
Public
1/**2 * Metric catalog (CLAUDE.md §250-252, §352). Every derived number shown on the site references3 * one of these definitions by slug; the formula text and version are displayed on /methodology.4 *5 * Composite scores (CI-IMPACT etc.) are intentionally absent from Phase 1 (§353).6 */7export interface MetricSeed {8 slug: string;9 name: string;10 description: string;11 formula: string;12 formulaVersion: string;13 unit: string;14 higherIsWorse: boolean | null;15 aggregation: string | null;16 validDimensions: string[];17 sourceSlugs: string[];18 category: string;19 eligibility: Record<string, unknown>;20 experimental: boolean;21}2223export const METRIC_CATALOG: MetricSeed[] = [24 // --- Burden (epidemiology observations) ---25 {26 slug: 'incidence_count',27 name: 'Annual new cases',28 description: 'Number of new cases diagnosed in the reference year for the population scope. Registry counts are observed; national/global figures may be estimates and are labeled as such.',29 formula: 'epidemiology_observations.value WHERE metric = incidence_count',30 formulaVersion: 'ci-incidence-count-v1',31 unit: 'count',32 higherIsWorse: true,33 aggregation: 'none',34 validDimensions: ['geography', 'sex', 'age_group', 'year'],35 sourceSlugs: ['cdc-wonder', 'seer', 'iarc-globocan'],36 category: 'burden',37 eligibility: { requires: ['incidence_count'], entityLevel: 'top' },38 experimental: false,39 },40 {41 slug: 'mortality_count',42 name: 'Annual deaths',43 description: 'Number of deaths with this cancer as underlying cause in the reference year for the population scope.',44 formula: 'epidemiology_observations.value WHERE metric = mortality_count',45 formulaVersion: 'ci-mortality-count-v1',46 unit: 'count',47 higherIsWorse: true,48 aggregation: 'none',49 validDimensions: ['geography', 'sex', 'age_group', 'year'],50 sourceSlugs: ['cdc-wonder', 'seer', 'iarc-globocan'],51 category: 'burden',52 eligibility: { requires: ['mortality_count'], entityLevel: 'top' },53 experimental: false,54 },55 {56 slug: 'as_incidence_rate',57 name: 'Age-standardized incidence rate',58 description: 'Incidence per 100,000 person-years, age-standardized to the standard population declared by the source. Rates standardized to different standard populations are never compared in one ranking.',59 formula: 'epidemiology_observations.value WHERE metric = as_incidence_rate (standard_population fixed per scope)',60 formulaVersion: 'ci-asir-v1',61 unit: 'per_100k',62 higherIsWorse: true,63 aggregation: 'none',64 validDimensions: ['geography', 'sex', 'year'],65 sourceSlugs: ['cdc-wonder', 'seer', 'iarc-globocan'],66 category: 'burden',67 eligibility: { requires: ['as_incidence_rate'], entityLevel: 'top' },68 experimental: false,69 },70 {71 slug: 'as_mortality_rate',72 name: 'Age-standardized mortality rate',73 description: 'Deaths per 100,000 person-years, age-standardized to the standard population declared by the source.',74 formula: 'epidemiology_observations.value WHERE metric = as_mortality_rate (standard_population fixed per scope)',75 formulaVersion: 'ci-asmr-v1',76 unit: 'per_100k',77 higherIsWorse: true,78 aggregation: 'none',79 validDimensions: ['geography', 'sex', 'year'],80 sourceSlugs: ['cdc-wonder', 'seer', 'iarc-globocan'],81 category: 'burden',82 eligibility: { requires: ['as_mortality_rate'], entityLevel: 'top' },83 experimental: false,84 },85 // --- Lethality ---86 {87 slug: 'mortality_incidence_ratio',88 name: 'Mortality-to-incidence ratio',89 description: 'Deaths divided by new cases in the same population, year and sex. A crude proxy of lethality; it is not a survival probability and is affected by incidence trends and registration completeness.',90 formula: 'mortality_count / incidence_count (same geography, year, sex, source family)',91 formulaVersion: 'ci-mir-v1',92 unit: 'ratio',93 higherIsWorse: true,94 aggregation: 'none',95 validDimensions: ['geography', 'sex', 'year'],96 sourceSlugs: ['cdc-wonder', 'seer', 'iarc-globocan'],97 category: 'lethality',98 eligibility: { requires: ['incidence_count', 'mortality_count'], minIncidence: 100, entityLevel: 'top' },99 experimental: false,100 },101 {102 slug: 'five_year_survival',103 name: '5-year relative survival',104 description: '5-year relative survival for the diagnosis period and population declared by the source. Population survival statistics do not predict an individual outcome.',105 formula: 'survival_observations.probability WHERE survival_type = relative AND duration_months = 60 AND stage IS NULL',106 formulaVersion: 'ci-5ys-v1',107 unit: 'probability',108 higherIsWorse: false,109 aggregation: 'none',110 validDimensions: ['geography', 'sex', 'diagnosis_period'],111 sourceSlugs: ['seer'],112 category: 'lethality',113 eligibility: { requires: ['five_year_relative_survival'], minCohort: 50, entityLevel: 'top' },114 experimental: false,115 },116 // --- Clinical research (ClinicalTrials.gov) ---117 {118 slug: 'active_trials',119 name: 'Active clinical trials',120 description: 'Interventional studies registered on ClinicalTrials.gov whose overall status is RECRUITING, NOT_YET_RECRUITING, ENROLLING_BY_INVITATION or ACTIVE_NOT_RECRUITING and whose conditions map to this cancer or one of its descendants in the NCIt hierarchy.',121 formula: 'COUNT(DISTINCT trial) FROM trial_conditions JOIN clinical_trials WHERE cancer_id IN descendants(cancer) AND study_type = INTERVENTIONAL AND overall_status IN (RECRUITING, NOT_YET_RECRUITING, ENROLLING_BY_INVITATION, ACTIVE_NOT_RECRUITING)',122 formulaVersion: 'ci-active-trials-v1',123 unit: 'count',124 higherIsWorse: false,125 aggregation: 'descendants',126 validDimensions: ['entity_level'],127 sourceSlugs: ['clinicaltrials'],128 category: 'trials',129 eligibility: { entityLevel: 'any' },130 experimental: false,131 },132 {133 slug: 'recruiting_trials',134 name: 'Recruiting clinical trials',135 description: 'Interventional studies currently RECRUITING whose conditions map to this cancer or its descendants.',136 formula: 'COUNT(DISTINCT trial) … overall_status = RECRUITING AND study_type = INTERVENTIONAL',137 formulaVersion: 'ci-recruiting-trials-v1',138 unit: 'count',139 higherIsWorse: false,140 aggregation: 'descendants',141 validDimensions: ['entity_level'],142 sourceSlugs: ['clinicaltrials'],143 category: 'trials',144 eligibility: { entityLevel: 'any' },145 experimental: false,146 },147 {148 slug: 'phase3_trials',149 name: 'Active Phase III trials',150 description: 'Active interventional studies with PHASE3 among their phases, mapped to this cancer or its descendants.',151 formula: 'COUNT(DISTINCT trial) … active statuses AND PHASE3 = ANY(phases)',152 formulaVersion: 'ci-phase3-trials-v1',153 unit: 'count',154 higherIsWorse: false,155 aggregation: 'descendants',156 validDimensions: ['entity_level'],157 sourceSlugs: ['clinicaltrials'],158 category: 'trials',159 eligibility: { entityLevel: 'any' },160 experimental: false,161 },162 // --- Research activity (PubMed) ---163 {164 slug: 'publications_5y',165 name: 'Publications, last 5 years',166 description: 'PubMed records matching the cancer’s MeSH-anchored query (stored verbatim with the count) with a publication date in the last 5 full years plus the current year.',167 formula: 'literature_counts.count WHERE window_key = 5y (query stored per row)',168 formulaVersion: 'ci-pubs-5y-v1',169 unit: 'count',170 higherIsWorse: false,171 aggregation: 'none',172 validDimensions: ['entity_level'],173 sourceSlugs: ['pubmed'],174 category: 'research',175 eligibility: { entityLevel: 'any', requiresQuery: true },176 experimental: false,177 },178 {179 slug: 'publications_12m',180 name: 'Publications, last 12 months',181 description: 'PubMed records matching the cancer’s query with a publication date in the last 12 months.',182 formula: 'literature_counts.count WHERE window_key = 12m',183 formulaVersion: 'ci-pubs-12m-v1',184 unit: 'count',185 higherIsWorse: false,186 aggregation: 'none',187 validDimensions: ['entity_level'],188 sourceSlugs: ['pubmed'],189 category: 'research',190 eligibility: { entityLevel: 'any', requiresQuery: true },191 experimental: false,192 },193 {194 slug: 'publication_growth',195 name: 'Publication growth',196 description: 'Ratio of publications in the last 12 months to the average annual publications over the preceding 5-year window. Values above 1 indicate accelerating literature.',197 formula: 'publications_12m / (publications_5y_prior / 5)',198 formulaVersion: 'ci-pub-growth-v1',199 unit: 'ratio',200 higherIsWorse: null,201 aggregation: 'none',202 validDimensions: ['entity_level'],203 sourceSlugs: ['pubmed'],204 category: 'trend',205 eligibility: { entityLevel: 'any', minPublications5y: 50 },206 experimental: false,207 },208 // --- Molecular knowledge ---209 {210 slug: 'curated_evidence_items',211 name: 'Curated clinical evidence items',212 description: 'Accepted CIViC evidence items whose disease maps to this cancer or its descendants.',213 formula: 'COUNT(civic_evidence_items) WHERE status = ACCEPTED AND cancer_id IN descendants(cancer)',214 formulaVersion: 'ci-civic-evidence-v1',215 unit: 'count',216 higherIsWorse: false,217 aggregation: 'descendants',218 validDimensions: ['entity_level'],219 sourceSlugs: ['civic'],220 category: 'molecular',221 eligibility: { entityLevel: 'any' },222 experimental: false,223 },224 {225 slug: 'associated_genes',226 name: 'Genes with curated or cohort evidence',227 description: 'Distinct genes linked to this cancer (or descendants) by an accepted CIViC evidence item or by a GDC cohort frequency of at least 5% with ≥ 20 affected cases.',228 formula: 'COUNT(DISTINCT gene) FROM (civic accepted evidence ∪ gdc frequency ≥ 0.05 AND cases_affected ≥ 20)',229 formulaVersion: 'ci-genes-v1',230 unit: 'count',231 higherIsWorse: false,232 aggregation: 'descendants',233 validDimensions: ['entity_level'],234 sourceSlugs: ['civic', 'gdc'],235 category: 'molecular',236 eligibility: { entityLevel: 'any' },237 experimental: false,238 },239 {240 slug: 'genomic_cohorts',241 name: 'Public genomic cohorts',242 description: 'Open-access genomic studies (GDC projects) whose disease maps to this cancer or its descendants.',243 formula: 'COUNT(genomic_cohorts) WHERE cancer_id IN descendants(cancer)',244 formulaVersion: 'ci-cohorts-v1',245 unit: 'count',246 higherIsWorse: false,247 aggregation: 'descendants',248 validDimensions: ['entity_level'],249 sourceSlugs: ['gdc'],250 category: 'molecular',251 eligibility: { entityLevel: 'any' },252 experimental: false,253 },254 // --- Gap indexes (derived; require burden) ---255 {256 slug: 'trial_gap',257 name: 'Trial Gap Index',258 description: 'Burden percentile minus active-trial percentile within the same scope. Positive values flag cancers with high mortality burden but comparatively few active trials. A quantitative signal, not an accusation (CLAUDE.md §324).',259 formula: 'percentile(mortality_count) − percentile(active_trials)',260 formulaVersion: 'ci-trial-gap-v1',261 unit: 'percentile_points',262 higherIsWorse: true,263 aggregation: 'none',264 validDimensions: ['geography', 'year'],265 sourceSlugs: ['clinicaltrials', 'cdc-wonder', 'seer', 'iarc-globocan'],266 category: 'unmet_need',267 eligibility: { requires: ['mortality_count', 'active_trials'], entityLevel: 'top' },268 experimental: false,269 },270 {271 slug: 'research_gap',272 name: 'Research Gap Index',273 description: 'Burden percentile minus research-activity percentile (publications, last 5 years) within the same scope. Positive values flag cancers with high mortality burden but comparatively little literature.',274 formula: 'percentile(mortality_count) − percentile(publications_5y)',275 formulaVersion: 'ci-research-gap-v1',276 unit: 'percentile_points',277 higherIsWorse: true,278 aggregation: 'none',279 validDimensions: ['geography', 'year'],280 sourceSlugs: ['pubmed', 'cdc-wonder', 'seer', 'iarc-globocan'],281 category: 'unmet_need',282 eligibility: { requires: ['mortality_count', 'publications_5y'], entityLevel: 'top' },283 experimental: false,284 },285];286