@ottolab/bio-age 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/kdm.d.ts +59 -0
- package/dist/kdm.d.ts.map +1 -0
- package/dist/kdm.js +80 -0
- package/dist/kdm.js.map +1 -0
- package/dist/pheno-age.d.ts +116 -0
- package/dist/pheno-age.d.ts.map +1 -0
- package/dist/pheno-age.js +210 -0
- package/dist/pheno-age.js.map +1 -0
- package/dist/utils.d.ts +9 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +13 -0
- package/dist/utils.js.map +1 -0
- package/package.json +8 -2
- package/__tests__/kdm.test.ts +0 -187
- package/__tests__/pheno-age.test.ts +0 -371
- package/__tests__/utils.test.ts +0 -67
- package/src/index.ts +0 -21
- package/src/kdm.ts +0 -129
- package/src/pheno-age.ts +0 -284
- package/src/utils.ts +0 -13
- package/tsconfig.json +0 -10
- package/tsconfig.tsbuildinfo +0 -1
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { calculatePhenoAge, calculateMetabolicProxy, computeLinearPredictor, computeMortalityScore, invertToPhenoAge, convertToPhenoAgeUnits, PHENO_AGE_COEFFICIENTS, GAMMA, } from './pheno-age.js';
|
|
2
|
+
export type { PhenoAgeInput, PhenoAgeResult, PhenoAgeDriver, MetabolicProxyInput, } from './pheno-age.js';
|
|
3
|
+
export { calculateKDM, KDM_REGRESSIONS, AGE_VARIANCE } from './kdm.js';
|
|
4
|
+
export type { KDMInput, KDMResult } from './kdm.js';
|
|
5
|
+
export { clamp, safeLn } from './utils.js';
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,KAAK,GACN,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,aAAa,EACb,cAAc,EACd,cAAc,EACd,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACvE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEpD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { calculatePhenoAge, calculateMetabolicProxy, computeLinearPredictor, computeMortalityScore, invertToPhenoAge, convertToPhenoAgeUnits, PHENO_AGE_COEFFICIENTS, GAMMA, } from './pheno-age.js';
|
|
2
|
+
export { calculateKDM, KDM_REGRESSIONS, AGE_VARIANCE } from './kdm.js';
|
|
3
|
+
export { clamp, safeLn } from './utils.js';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,KAAK,GACN,MAAM,gBAAgB,CAAC;AAQxB,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGvE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/kdm.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Klemera-Doubal Method (KDM) Biological Age.
|
|
3
|
+
*
|
|
4
|
+
* Based on: Klemera & Doubal (2006) "A new approach to the concept and
|
|
5
|
+
* computation of biological age". Implemented with biomarker regressions
|
|
6
|
+
* from NHANES III data following the approach in Levine (2013).
|
|
7
|
+
*
|
|
8
|
+
* KDM fits each biomarker as a linear function of chronological age,
|
|
9
|
+
* then combines all biomarkers into a single BA estimate that minimizes
|
|
10
|
+
* the sum of squared deviations weighted by residual variance.
|
|
11
|
+
*/
|
|
12
|
+
export interface KDMInput {
|
|
13
|
+
chronologicalAge: number;
|
|
14
|
+
albumin?: number;
|
|
15
|
+
creatinine?: number;
|
|
16
|
+
glucose?: number;
|
|
17
|
+
lnCRP?: number;
|
|
18
|
+
lymphocytePercent?: number;
|
|
19
|
+
mcv?: number;
|
|
20
|
+
rdw?: number;
|
|
21
|
+
alp?: number;
|
|
22
|
+
wbc?: number;
|
|
23
|
+
systolicBP?: number;
|
|
24
|
+
bun?: number;
|
|
25
|
+
hba1c?: number;
|
|
26
|
+
totalCholesterol?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface KDMResult {
|
|
29
|
+
kdmAge: number;
|
|
30
|
+
delta: number;
|
|
31
|
+
markersUsed: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Biomarker regression parameters: each marker regressed on chronological age.
|
|
35
|
+
* slope (k), intercept (q), residual SD (s) from NHANES III reference.
|
|
36
|
+
*
|
|
37
|
+
* Model: biomarker_i = q_i + k_i * age + error_i, Var(error_i) = s_i^2
|
|
38
|
+
*/
|
|
39
|
+
interface BiomarkerRegression {
|
|
40
|
+
k: number;
|
|
41
|
+
q: number;
|
|
42
|
+
s: number;
|
|
43
|
+
}
|
|
44
|
+
declare const KDM_REGRESSIONS: Record<string, BiomarkerRegression>;
|
|
45
|
+
declare const AGE_VARIANCE = 250;
|
|
46
|
+
/**
|
|
47
|
+
* Calculate KDM biological age.
|
|
48
|
+
*
|
|
49
|
+
* The KDM formula:
|
|
50
|
+
* BA = [ sum_i( (x_i - q_i) * k_i / s_i^2 ) + CA / s_BA^2 ]
|
|
51
|
+
* / [ sum_i( k_i^2 / s_i^2 ) + 1 / s_BA^2 ]
|
|
52
|
+
*
|
|
53
|
+
* where s_BA^2 is estimated from the age variance in the reference population.
|
|
54
|
+
*
|
|
55
|
+
* Requires at least 3 markers for a meaningful estimate.
|
|
56
|
+
*/
|
|
57
|
+
export declare function calculateKDM(input: KDMInput): KDMResult;
|
|
58
|
+
export { KDM_REGRESSIONS, AGE_VARIANCE };
|
|
59
|
+
//# sourceMappingURL=kdm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kdm.d.ts","sourceRoot":"","sources":["../src/kdm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,QAAQ;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,UAAU,mBAAmB;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,QAAA,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAcxD,CAAC;AAGF,QAAA,MAAM,YAAY,MAAQ,CAAC;AAE3B;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS,CA8BvD;AAqBD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC"}
|
package/dist/kdm.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Klemera-Doubal Method (KDM) Biological Age.
|
|
3
|
+
*
|
|
4
|
+
* Based on: Klemera & Doubal (2006) "A new approach to the concept and
|
|
5
|
+
* computation of biological age". Implemented with biomarker regressions
|
|
6
|
+
* from NHANES III data following the approach in Levine (2013).
|
|
7
|
+
*
|
|
8
|
+
* KDM fits each biomarker as a linear function of chronological age,
|
|
9
|
+
* then combines all biomarkers into a single BA estimate that minimizes
|
|
10
|
+
* the sum of squared deviations weighted by residual variance.
|
|
11
|
+
*/
|
|
12
|
+
const KDM_REGRESSIONS = {
|
|
13
|
+
albumin: { k: -0.0172, q: 4.703, s: 0.3262 },
|
|
14
|
+
creatinine: { k: 0.0033, q: 0.842, s: 0.2136 },
|
|
15
|
+
glucose: { k: 0.27, q: 83.56, s: 22.24 },
|
|
16
|
+
lnCRP: { k: 0.0205, q: -1.794, s: 1.126 },
|
|
17
|
+
lymphocytePercent: { k: -0.0522, q: 33.55, s: 8.47 },
|
|
18
|
+
mcv: { k: 0.052, q: 87.08, s: 5.51 },
|
|
19
|
+
rdw: { k: 0.0211, q: 12.36, s: 1.18 },
|
|
20
|
+
alp: { k: 0.347, q: 58.83, s: 24.1 },
|
|
21
|
+
wbc: { k: -0.0072, q: 7.4, s: 2.12 },
|
|
22
|
+
systolicBP: { k: 0.527, q: 101.8, s: 17.64 },
|
|
23
|
+
bun: { k: 0.101, q: 10.89, s: 4.63 },
|
|
24
|
+
hba1c: { k: 0.0131, q: 4.926, s: 0.607 },
|
|
25
|
+
totalCholesterol: { k: 0.252, q: 190.2, s: 40.41 },
|
|
26
|
+
};
|
|
27
|
+
// Variance of chronological age in reference population (NHANES III, adults 20-85)
|
|
28
|
+
const AGE_VARIANCE = 250.0; // ~SD of 15.8 years
|
|
29
|
+
/**
|
|
30
|
+
* Calculate KDM biological age.
|
|
31
|
+
*
|
|
32
|
+
* The KDM formula:
|
|
33
|
+
* BA = [ sum_i( (x_i - q_i) * k_i / s_i^2 ) + CA / s_BA^2 ]
|
|
34
|
+
* / [ sum_i( k_i^2 / s_i^2 ) + 1 / s_BA^2 ]
|
|
35
|
+
*
|
|
36
|
+
* where s_BA^2 is estimated from the age variance in the reference population.
|
|
37
|
+
*
|
|
38
|
+
* Requires at least 3 markers for a meaningful estimate.
|
|
39
|
+
*/
|
|
40
|
+
export function calculateKDM(input) {
|
|
41
|
+
const markers = getAvailableMarkers(input);
|
|
42
|
+
if (markers.length < 3) {
|
|
43
|
+
throw new Error(`KDM requires at least 3 biomarkers, got ${markers.length}`);
|
|
44
|
+
}
|
|
45
|
+
let numerator = 0;
|
|
46
|
+
let denominator = 0;
|
|
47
|
+
for (const { value, regression } of markers) {
|
|
48
|
+
const { k, q, s } = regression;
|
|
49
|
+
const s2 = s * s;
|
|
50
|
+
numerator += ((value - q) * k) / s2;
|
|
51
|
+
denominator += (k * k) / s2;
|
|
52
|
+
}
|
|
53
|
+
// Add chronological age term (acts as a prior)
|
|
54
|
+
const sBA2 = AGE_VARIANCE;
|
|
55
|
+
numerator += input.chronologicalAge / sBA2;
|
|
56
|
+
denominator += 1 / sBA2;
|
|
57
|
+
const kdmAge = numerator / denominator;
|
|
58
|
+
const delta = kdmAge - input.chronologicalAge;
|
|
59
|
+
return {
|
|
60
|
+
kdmAge: Math.round(kdmAge * 100) / 100,
|
|
61
|
+
delta: Math.round(delta * 100) / 100,
|
|
62
|
+
markersUsed: markers.length,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Extract available markers from input, matching to their regression parameters.
|
|
67
|
+
*/
|
|
68
|
+
function getAvailableMarkers(input) {
|
|
69
|
+
const result = [];
|
|
70
|
+
for (const [name, regression] of Object.entries(KDM_REGRESSIONS)) {
|
|
71
|
+
const value = input[name];
|
|
72
|
+
if (typeof value === 'number') {
|
|
73
|
+
result.push({ name, value, regression });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
// Export regressions for testing
|
|
79
|
+
export { KDM_REGRESSIONS, AGE_VARIANCE };
|
|
80
|
+
//# sourceMappingURL=kdm.js.map
|
package/dist/kdm.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kdm.js","sourceRoot":"","sources":["../src/kdm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Input for PhenoAge calculation.
|
|
3
|
+
* Units follow the Levine 2018 model convention:
|
|
4
|
+
* albumin g/dL, creatinine mg/dL, glucose mmol/L, CRP mg/dL (log-transformed),
|
|
5
|
+
* lymphocyte %, MCV fL, RDW %, ALP U/L, WBC 10^3/uL.
|
|
6
|
+
*/
|
|
7
|
+
export interface PhenoAgeInput {
|
|
8
|
+
chronologicalAge: number;
|
|
9
|
+
albumin: number;
|
|
10
|
+
creatinine: number;
|
|
11
|
+
glucose: number;
|
|
12
|
+
lnCRP: number;
|
|
13
|
+
lymphocytePercent: number;
|
|
14
|
+
mcv: number;
|
|
15
|
+
rdw: number;
|
|
16
|
+
alp: number;
|
|
17
|
+
wbc: number;
|
|
18
|
+
}
|
|
19
|
+
export interface PhenoAgeResult {
|
|
20
|
+
phenoAge: number;
|
|
21
|
+
delta: number;
|
|
22
|
+
mortalityScore: number;
|
|
23
|
+
isProxy: boolean;
|
|
24
|
+
drivers?: PhenoAgeDriver[];
|
|
25
|
+
}
|
|
26
|
+
export interface PhenoAgeDriver {
|
|
27
|
+
marker: string;
|
|
28
|
+
contribution: number;
|
|
29
|
+
direction: 'aging' | 'protective';
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Input for the metabolic proxy fallback when full CBC is unavailable.
|
|
33
|
+
* All values in conventional US units.
|
|
34
|
+
*/
|
|
35
|
+
export interface MetabolicProxyInput {
|
|
36
|
+
chronologicalAge: number;
|
|
37
|
+
glucose?: number;
|
|
38
|
+
hba1c?: number;
|
|
39
|
+
hsCrp?: number;
|
|
40
|
+
triglycerides?: number;
|
|
41
|
+
hdl?: number;
|
|
42
|
+
ldlC?: number;
|
|
43
|
+
fastingInsulin?: number;
|
|
44
|
+
uricAcid?: number;
|
|
45
|
+
}
|
|
46
|
+
export declare const PHENO_AGE_COEFFICIENTS: {
|
|
47
|
+
readonly intercept: -19.9067;
|
|
48
|
+
readonly albumin: -0.0336;
|
|
49
|
+
readonly creatinine: 0.0095;
|
|
50
|
+
readonly glucose: 0.1953;
|
|
51
|
+
readonly lnCRP: 0.0954;
|
|
52
|
+
readonly lymphocytePercent: -0.012;
|
|
53
|
+
readonly mcv: 0.0268;
|
|
54
|
+
readonly rdw: 0.3306;
|
|
55
|
+
readonly alp: 0.00188;
|
|
56
|
+
readonly wbc: 0.0554;
|
|
57
|
+
readonly age: 0.0804;
|
|
58
|
+
};
|
|
59
|
+
export declare const GAMMA = 0.0076927;
|
|
60
|
+
/**
|
|
61
|
+
* Compute the linear predictor (xb) from PhenoAge model.
|
|
62
|
+
*/
|
|
63
|
+
export declare function computeLinearPredictor(input: PhenoAgeInput): number;
|
|
64
|
+
/**
|
|
65
|
+
* Compute cumulative mortality probability from linear predictor via Gompertz model.
|
|
66
|
+
*
|
|
67
|
+
* M(xb) = 1 - exp(-exp(xb) * (exp(gamma * T) - 1) / gamma)
|
|
68
|
+
* where T = MAX_AGE (120 years)
|
|
69
|
+
*/
|
|
70
|
+
export declare function computeMortalityScore(xb: number): number;
|
|
71
|
+
/**
|
|
72
|
+
* Invert mortality score back to PhenoAge.
|
|
73
|
+
*
|
|
74
|
+
* PhenoAge = intercept + ln(lambda * ln(1 - M)) / slope
|
|
75
|
+
*/
|
|
76
|
+
export declare function invertToPhenoAge(mortalityScore: number): number;
|
|
77
|
+
/**
|
|
78
|
+
* Calculate PhenoAge biological age using the Levine 2018 algorithm.
|
|
79
|
+
*
|
|
80
|
+
* Algorithm:
|
|
81
|
+
* 1. Linear predictor: xb = intercept + sum(coeff_i * marker_i)
|
|
82
|
+
* 2. Gompertz mortality: M = 1 - exp(-exp(xb) * (exp(gamma*120) - 1) / gamma)
|
|
83
|
+
* 3. Invert: PhenoAge = 141.50225 + ln(-0.00553 * ln(1-M)) / 0.090165
|
|
84
|
+
*
|
|
85
|
+
* All inputs must be in model-native units (g/dL, mg/dL, etc.).
|
|
86
|
+
* Use `convertToPhenoAgeUnits()` if you have SI units.
|
|
87
|
+
*/
|
|
88
|
+
export declare function calculatePhenoAge(input: PhenoAgeInput): PhenoAgeResult;
|
|
89
|
+
/**
|
|
90
|
+
* Metabolic proxy for biological age when full CBC panel is unavailable.
|
|
91
|
+
*
|
|
92
|
+
* Uses z-score deviation from population means across available metabolic
|
|
93
|
+
* markers. Each weighted SD of deviation approximates YEARS_PER_SD years
|
|
94
|
+
* of biological age shift. Delta is capped at [-10, +15] years.
|
|
95
|
+
*/
|
|
96
|
+
export declare function calculateMetabolicProxy(input: MetabolicProxyInput): PhenoAgeResult;
|
|
97
|
+
/**
|
|
98
|
+
* Convert common lab units to PhenoAge model units.
|
|
99
|
+
*
|
|
100
|
+
* Accepts either SI or US units and converts to model-native:
|
|
101
|
+
* albumin g/L → g/dL, creatinine umol/L → mg/dL, glucose mg/dL → mmol/L,
|
|
102
|
+
* CRP mg/L → ln(mg/dL).
|
|
103
|
+
*/
|
|
104
|
+
export declare function convertToPhenoAgeUnits(raw: {
|
|
105
|
+
albumin_gL?: number;
|
|
106
|
+
creatinine_umolL?: number;
|
|
107
|
+
glucose_mgDL?: number;
|
|
108
|
+
glucose_mmolL?: number;
|
|
109
|
+
crp_mgL?: number;
|
|
110
|
+
lymphocytePercent?: number;
|
|
111
|
+
mcv?: number;
|
|
112
|
+
rdw?: number;
|
|
113
|
+
alp?: number;
|
|
114
|
+
wbc?: number;
|
|
115
|
+
}): Partial<Omit<PhenoAgeInput, 'chronologicalAge'>>;
|
|
116
|
+
//# sourceMappingURL=pheno-age.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pheno-age.d.ts","sourceRoot":"","sources":["../src/pheno-age.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,EAAE,MAAM,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,OAAO,GAAG,YAAY,CAAC;CACnC;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,gBAAgB,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAGD,eAAO,MAAM,sBAAsB;;;;;;;;;;;;CAYzB,CAAC;AAGX,eAAO,MAAM,KAAK,YAAY,CAAC;AAwC/B;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAenE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAI/D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,CActE;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,mBAAmB,GAAG,cAAc,CAiClF;AAiCD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE;IAC1C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,IAAI,CAAC,aAAa,EAAE,kBAAkB,CAAC,CAAC,CAenD"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { clamp } from './utils.js';
|
|
2
|
+
// Published coefficients (Levine 2018, Table S6)
|
|
3
|
+
export const PHENO_AGE_COEFFICIENTS = {
|
|
4
|
+
intercept: -19.9067,
|
|
5
|
+
albumin: -0.0336,
|
|
6
|
+
creatinine: 0.0095,
|
|
7
|
+
glucose: 0.1953,
|
|
8
|
+
lnCRP: 0.0954,
|
|
9
|
+
lymphocytePercent: -0.012,
|
|
10
|
+
mcv: 0.0268,
|
|
11
|
+
rdw: 0.3306,
|
|
12
|
+
alp: 0.00188,
|
|
13
|
+
wbc: 0.0554,
|
|
14
|
+
age: 0.0804,
|
|
15
|
+
};
|
|
16
|
+
// Gompertz proportional hazard gamma
|
|
17
|
+
export const GAMMA = 0.0076927;
|
|
18
|
+
// Max age horizon for Gompertz integration
|
|
19
|
+
const MAX_AGE = 120;
|
|
20
|
+
// PhenoAge inversion constants (derived from Gompertz model)
|
|
21
|
+
const PHENO_INVERSE = {
|
|
22
|
+
intercept: 141.50225,
|
|
23
|
+
lambda: -0.00553,
|
|
24
|
+
slope: 0.090165,
|
|
25
|
+
};
|
|
26
|
+
// Population means for driver analysis (NHANES III reference)
|
|
27
|
+
const POPULATION_MEANS = {
|
|
28
|
+
albumin: 4.0,
|
|
29
|
+
creatinine: 0.96,
|
|
30
|
+
glucose: 5.42, // 97.7 mg/dL → mmol/L
|
|
31
|
+
lnCRP: -0.94,
|
|
32
|
+
lymphocytePercent: 30.3,
|
|
33
|
+
mcv: 89.5,
|
|
34
|
+
rdw: 13.3,
|
|
35
|
+
alp: 78.5,
|
|
36
|
+
wbc: 7.1,
|
|
37
|
+
};
|
|
38
|
+
// Population means and SDs for metabolic proxy (NHANES reference)
|
|
39
|
+
const METABOLIC_PROXY_MARKERS = {
|
|
40
|
+
glucose: { mean: 97.7, sd: 22, weight: 1.0 },
|
|
41
|
+
hba1c: { mean: 5.5, sd: 0.5, weight: 1.2 },
|
|
42
|
+
hsCrp: { mean: 2.0, sd: 3.0, weight: 0.8 },
|
|
43
|
+
triglycerides: { mean: 130, sd: 75, weight: 0.6 },
|
|
44
|
+
hdl: { mean: 53, sd: 15, weight: -0.7 }, // negative: higher is better
|
|
45
|
+
ldlC: { mean: 120, sd: 35, weight: 0.5 },
|
|
46
|
+
fastingInsulin: { mean: 9.0, sd: 6.0, weight: 0.9 },
|
|
47
|
+
uricAcid: { mean: 5.4, sd: 1.4, weight: 0.6 },
|
|
48
|
+
};
|
|
49
|
+
// Years of biological age per 1 SD deviation
|
|
50
|
+
const YEARS_PER_SD = 2.5;
|
|
51
|
+
/**
|
|
52
|
+
* Compute the linear predictor (xb) from PhenoAge model.
|
|
53
|
+
*/
|
|
54
|
+
export function computeLinearPredictor(input) {
|
|
55
|
+
const c = PHENO_AGE_COEFFICIENTS;
|
|
56
|
+
return (c.intercept +
|
|
57
|
+
c.albumin * input.albumin +
|
|
58
|
+
c.creatinine * input.creatinine +
|
|
59
|
+
c.glucose * input.glucose +
|
|
60
|
+
c.lnCRP * input.lnCRP +
|
|
61
|
+
c.lymphocytePercent * input.lymphocytePercent +
|
|
62
|
+
c.mcv * input.mcv +
|
|
63
|
+
c.rdw * input.rdw +
|
|
64
|
+
c.alp * input.alp +
|
|
65
|
+
c.wbc * input.wbc +
|
|
66
|
+
c.age * input.chronologicalAge);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Compute cumulative mortality probability from linear predictor via Gompertz model.
|
|
70
|
+
*
|
|
71
|
+
* M(xb) = 1 - exp(-exp(xb) * (exp(gamma * T) - 1) / gamma)
|
|
72
|
+
* where T = MAX_AGE (120 years)
|
|
73
|
+
*/
|
|
74
|
+
export function computeMortalityScore(xb) {
|
|
75
|
+
const hazard = Math.exp(xb);
|
|
76
|
+
const cumHazard = (hazard * (Math.exp(GAMMA * MAX_AGE) - 1)) / GAMMA;
|
|
77
|
+
return 1 - Math.exp(-cumHazard);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Invert mortality score back to PhenoAge.
|
|
81
|
+
*
|
|
82
|
+
* PhenoAge = intercept + ln(lambda * ln(1 - M)) / slope
|
|
83
|
+
*/
|
|
84
|
+
export function invertToPhenoAge(mortalityScore) {
|
|
85
|
+
const clamped = clamp(mortalityScore, 1e-10, 1 - 1e-10);
|
|
86
|
+
const inner = PHENO_INVERSE.lambda * Math.log(1 - clamped);
|
|
87
|
+
return PHENO_INVERSE.intercept + Math.log(inner) / PHENO_INVERSE.slope;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Calculate PhenoAge biological age using the Levine 2018 algorithm.
|
|
91
|
+
*
|
|
92
|
+
* Algorithm:
|
|
93
|
+
* 1. Linear predictor: xb = intercept + sum(coeff_i * marker_i)
|
|
94
|
+
* 2. Gompertz mortality: M = 1 - exp(-exp(xb) * (exp(gamma*120) - 1) / gamma)
|
|
95
|
+
* 3. Invert: PhenoAge = 141.50225 + ln(-0.00553 * ln(1-M)) / 0.090165
|
|
96
|
+
*
|
|
97
|
+
* All inputs must be in model-native units (g/dL, mg/dL, etc.).
|
|
98
|
+
* Use `convertToPhenoAgeUnits()` if you have SI units.
|
|
99
|
+
*/
|
|
100
|
+
export function calculatePhenoAge(input) {
|
|
101
|
+
const xb = computeLinearPredictor(input);
|
|
102
|
+
const mortalityScore = computeMortalityScore(xb);
|
|
103
|
+
const phenoAge = invertToPhenoAge(mortalityScore);
|
|
104
|
+
const delta = phenoAge - input.chronologicalAge;
|
|
105
|
+
const drivers = computeDrivers(input);
|
|
106
|
+
return {
|
|
107
|
+
phenoAge: Math.round(phenoAge * 100) / 100,
|
|
108
|
+
delta: Math.round(delta * 100) / 100,
|
|
109
|
+
mortalityScore: Math.round(mortalityScore * 10000) / 10000,
|
|
110
|
+
isProxy: false,
|
|
111
|
+
drivers,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Metabolic proxy for biological age when full CBC panel is unavailable.
|
|
116
|
+
*
|
|
117
|
+
* Uses z-score deviation from population means across available metabolic
|
|
118
|
+
* markers. Each weighted SD of deviation approximates YEARS_PER_SD years
|
|
119
|
+
* of biological age shift. Delta is capped at [-10, +15] years.
|
|
120
|
+
*/
|
|
121
|
+
export function calculateMetabolicProxy(input) {
|
|
122
|
+
let weightedZSum = 0;
|
|
123
|
+
let totalWeight = 0;
|
|
124
|
+
for (const [key, config] of Object.entries(METABOLIC_PROXY_MARKERS)) {
|
|
125
|
+
const value = input[key];
|
|
126
|
+
if (value === undefined)
|
|
127
|
+
continue;
|
|
128
|
+
const z = (value - config.mean) / config.sd;
|
|
129
|
+
weightedZSum += z * config.weight;
|
|
130
|
+
totalWeight += Math.abs(config.weight);
|
|
131
|
+
}
|
|
132
|
+
if (totalWeight === 0) {
|
|
133
|
+
return {
|
|
134
|
+
phenoAge: input.chronologicalAge,
|
|
135
|
+
delta: 0,
|
|
136
|
+
mortalityScore: 0,
|
|
137
|
+
isProxy: true,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const normalizedZ = weightedZSum / totalWeight;
|
|
141
|
+
const rawDelta = normalizedZ * YEARS_PER_SD;
|
|
142
|
+
const delta = clamp(rawDelta, -10, 15);
|
|
143
|
+
const phenoAge = input.chronologicalAge + delta;
|
|
144
|
+
return {
|
|
145
|
+
phenoAge: Math.round(phenoAge * 100) / 100,
|
|
146
|
+
delta: Math.round(delta * 100) / 100,
|
|
147
|
+
mortalityScore: 0,
|
|
148
|
+
isProxy: true,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Identify which biomarkers drive the PhenoAge deviation most.
|
|
153
|
+
* Computes contribution = coefficient * (actual - population_mean) for each marker.
|
|
154
|
+
*/
|
|
155
|
+
function computeDrivers(input) {
|
|
156
|
+
const c = PHENO_AGE_COEFFICIENTS;
|
|
157
|
+
const markerCoeffs = [
|
|
158
|
+
['albumin', c.albumin, input.albumin],
|
|
159
|
+
['creatinine', c.creatinine, input.creatinine],
|
|
160
|
+
['glucose', c.glucose, input.glucose],
|
|
161
|
+
['lnCRP', c.lnCRP, input.lnCRP],
|
|
162
|
+
['lymphocytePercent', c.lymphocytePercent, input.lymphocytePercent],
|
|
163
|
+
['mcv', c.mcv, input.mcv],
|
|
164
|
+
['rdw', c.rdw, input.rdw],
|
|
165
|
+
['alp', c.alp, input.alp],
|
|
166
|
+
['wbc', c.wbc, input.wbc],
|
|
167
|
+
];
|
|
168
|
+
const drivers = markerCoeffs.map(([marker, coeff, actual]) => {
|
|
169
|
+
const mean = POPULATION_MEANS[marker] ?? 0;
|
|
170
|
+
const contribution = coeff * (actual - mean);
|
|
171
|
+
return {
|
|
172
|
+
marker,
|
|
173
|
+
contribution: Math.round(contribution * 10000) / 10000,
|
|
174
|
+
direction: contribution > 0 ? 'aging' : 'protective',
|
|
175
|
+
};
|
|
176
|
+
});
|
|
177
|
+
return drivers.sort((a, b) => Math.abs(b.contribution) - Math.abs(a.contribution));
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Convert common lab units to PhenoAge model units.
|
|
181
|
+
*
|
|
182
|
+
* Accepts either SI or US units and converts to model-native:
|
|
183
|
+
* albumin g/L → g/dL, creatinine umol/L → mg/dL, glucose mg/dL → mmol/L,
|
|
184
|
+
* CRP mg/L → ln(mg/dL).
|
|
185
|
+
*/
|
|
186
|
+
export function convertToPhenoAgeUnits(raw) {
|
|
187
|
+
const result = {};
|
|
188
|
+
if (raw.albumin_gL !== undefined)
|
|
189
|
+
result.albumin = raw.albumin_gL * 0.1; // g/L → g/dL
|
|
190
|
+
if (raw.creatinine_umolL !== undefined)
|
|
191
|
+
result.creatinine = raw.creatinine_umolL / 88.4; // umol/L → mg/dL
|
|
192
|
+
if (raw.glucose_mgDL !== undefined)
|
|
193
|
+
result.glucose = raw.glucose_mgDL / 18.0182; // mg/dL → mmol/L
|
|
194
|
+
if (raw.glucose_mmolL !== undefined)
|
|
195
|
+
result.glucose = raw.glucose_mmolL; // already mmol/L
|
|
196
|
+
if (raw.crp_mgL !== undefined)
|
|
197
|
+
result.lnCRP = Math.log(Math.max(raw.crp_mgL * 0.1, 0.001)); // mg/L → mg/dL → ln
|
|
198
|
+
if (raw.lymphocytePercent !== undefined)
|
|
199
|
+
result.lymphocytePercent = raw.lymphocytePercent;
|
|
200
|
+
if (raw.mcv !== undefined)
|
|
201
|
+
result.mcv = raw.mcv;
|
|
202
|
+
if (raw.rdw !== undefined)
|
|
203
|
+
result.rdw = raw.rdw;
|
|
204
|
+
if (raw.alp !== undefined)
|
|
205
|
+
result.alp = raw.alp;
|
|
206
|
+
if (raw.wbc !== undefined)
|
|
207
|
+
result.wbc = raw.wbc;
|
|
208
|
+
return result;
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=pheno-age.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pheno-age.js","sourceRoot":"","sources":["../src/pheno-age.ts"],"names":[],"mappings":"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"}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clamp a value to a [min, max] range.
|
|
3
|
+
*/
|
|
4
|
+
export declare function clamp(value: number, min: number, max: number): number;
|
|
5
|
+
/**
|
|
6
|
+
* Natural log with safety floor to avoid -Infinity.
|
|
7
|
+
*/
|
|
8
|
+
export declare function safeLn(value: number, floor?: number): number;
|
|
9
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAErE;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAQ,GAAG,MAAM,CAE3D"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clamp a value to a [min, max] range.
|
|
3
|
+
*/
|
|
4
|
+
export function clamp(value, min, max) {
|
|
5
|
+
return Math.min(Math.max(value, min), max);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Natural log with safety floor to avoid -Infinity.
|
|
9
|
+
*/
|
|
10
|
+
export function safeLn(value, floor = 0.001) {
|
|
11
|
+
return Math.log(Math.max(value, floor));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,KAAK,CAAC,KAAa,EAAE,GAAW,EAAE,GAAW;IAC3D,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,MAAM,CAAC,KAAa,EAAE,KAAK,GAAG,KAAK;IACjD,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;AAC1C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ottolab/bio-age",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": "https://github.com/hokev/Otto",
|
|
6
|
-
"publishConfig": {
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
7
9
|
"type": "module",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
8
13
|
"exports": {
|
|
9
14
|
".": {
|
|
10
15
|
"import": {
|
|
@@ -16,6 +21,7 @@
|
|
|
16
21
|
},
|
|
17
22
|
"scripts": {
|
|
18
23
|
"build": "tsc --build",
|
|
24
|
+
"prepublishOnly": "npm run build",
|
|
19
25
|
"lint": "eslint src/",
|
|
20
26
|
"test": "vitest run"
|
|
21
27
|
},
|