heor-agent-mcp 1.9.0 → 1.10.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/README.md +2 -2
- package/dist/icf/jargon.d.ts.map +1 -1
- package/dist/icf/jargon.js +5 -4
- package/dist/icf/jargon.js.map +1 -1
- package/dist/icf/syllables.d.ts.map +1 -1
- package/dist/icf/syllables.js +31 -10
- package/dist/icf/syllables.js.map +1 -1
- package/dist/icf/types.d.ts +7 -3
- package/dist/icf/types.d.ts.map +1 -1
- package/dist/icf/types.js.map +1 -1
- package/dist/models/evppi.d.ts +8 -1
- package/dist/models/evppi.d.ts.map +1 -1
- package/dist/models/evppi.js +21 -8
- package/dist/models/evppi.js.map +1 -1
- package/dist/models/survivalFitting.d.ts.map +1 -1
- package/dist/models/survivalFitting.js +99 -29
- package/dist/models/survivalFitting.js.map +1 -1
- package/dist/providers/regulatory/ageRangeParser.d.ts +13 -0
- package/dist/providers/regulatory/ageRangeParser.d.ts.map +1 -0
- package/dist/providers/regulatory/ageRangeParser.js +78 -0
- package/dist/providers/regulatory/ageRangeParser.js.map +1 -0
- package/dist/providers/regulatory/autoCheck.d.ts +31 -0
- package/dist/providers/regulatory/autoCheck.d.ts.map +1 -0
- package/dist/providers/regulatory/autoCheck.js +93 -0
- package/dist/providers/regulatory/autoCheck.js.map +1 -0
- package/dist/providers/regulatory/cache.d.ts +37 -0
- package/dist/providers/regulatory/cache.d.ts.map +1 -0
- package/dist/providers/regulatory/cache.js +51 -0
- package/dist/providers/regulatory/cache.js.map +1 -0
- package/dist/providers/regulatory/dailymed.d.ts +34 -0
- package/dist/providers/regulatory/dailymed.d.ts.map +1 -0
- package/dist/providers/regulatory/dailymed.js +60 -0
- package/dist/providers/regulatory/dailymed.js.map +1 -0
- package/dist/providers/regulatory/drugNameNormaliser.d.ts +29 -0
- package/dist/providers/regulatory/drugNameNormaliser.d.ts.map +1 -0
- package/dist/providers/regulatory/drugNameNormaliser.js +186 -0
- package/dist/providers/regulatory/drugNameNormaliser.js.map +1 -0
- package/dist/providers/regulatory/emaEpi.d.ts +58 -0
- package/dist/providers/regulatory/emaEpi.d.ts.map +1 -0
- package/dist/providers/regulatory/emaEpi.js +105 -0
- package/dist/providers/regulatory/emaEpi.js.map +1 -0
- package/dist/providers/regulatory/index.d.ts +12 -0
- package/dist/providers/regulatory/index.d.ts.map +1 -0
- package/dist/providers/regulatory/index.js +12 -0
- package/dist/providers/regulatory/index.js.map +1 -0
- package/dist/providers/regulatory/openfda.d.ts +54 -0
- package/dist/providers/regulatory/openfda.d.ts.map +1 -0
- package/dist/providers/regulatory/openfda.js +216 -0
- package/dist/providers/regulatory/openfda.js.map +1 -0
- package/dist/providers/regulatory/types.d.ts +65 -0
- package/dist/providers/regulatory/types.d.ts.map +1 -0
- package/dist/providers/regulatory/types.js +8 -0
- package/dist/providers/regulatory/types.js.map +1 -0
- package/dist/providers/types.d.ts +2 -0
- package/dist/providers/types.d.ts.map +1 -1
- package/dist/server.js +16 -0
- package/dist/server.js.map +1 -1
- package/dist/tools/costEffectivenessModel.d.ts +30 -0
- package/dist/tools/costEffectivenessModel.d.ts.map +1 -1
- package/dist/tools/costEffectivenessModel.js +43 -1
- package/dist/tools/costEffectivenessModel.js.map +1 -1
- package/dist/tools/evidenceUnmetNeed.d.ts +40 -2
- package/dist/tools/evidenceUnmetNeed.d.ts.map +1 -1
- package/dist/tools/evidenceUnmetNeed.js +186 -12
- package/dist/tools/evidenceUnmetNeed.js.map +1 -1
- package/dist/tools/htaDossierPrep.d.ts.map +1 -1
- package/dist/tools/htaDossierPrep.js +97 -0
- package/dist/tools/htaDossierPrep.js.map +1 -1
- package/dist/tools/htaWorkflow.d.ts +44 -0
- package/dist/tools/htaWorkflow.d.ts.map +1 -1
- package/dist/tools/htaWorkflow.js +113 -1
- package/dist/tools/htaWorkflow.js.map +1 -1
- package/dist/tools/icfReadabilityCheck.d.ts.map +1 -1
- package/dist/tools/icfReadabilityCheck.js +19 -15
- package/dist/tools/icfReadabilityCheck.js.map +1 -1
- package/dist/tools/regulatoryStatusCheck.d.ts +60 -0
- package/dist/tools/regulatoryStatusCheck.d.ts.map +1 -0
- package/dist/tools/regulatoryStatusCheck.js +418 -0
- package/dist/tools/regulatoryStatusCheck.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,7 +45,7 @@ curl -s http://localhost:8080/health
|
|
|
45
45
|
Expected output:
|
|
46
46
|
|
|
47
47
|
```json
|
|
48
|
-
{"status":"ok","server":"heor-agent-mcp","version":"1.9.
|
|
48
|
+
{"status":"ok","server":"heor-agent-mcp","version":"1.9.2"}
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
✅ If you see the JSON above, the npm package works on your machine. Any further issues are in your MCP client config (Claude Desktop / Cursor / Continue), not the server.
|
|
@@ -126,7 +126,7 @@ The first prompt exercises `literature_search` + `validate_links` (free, no API
|
|
|
126
126
|
|
|
127
127
|
## What's new
|
|
128
128
|
|
|
129
|
-
See [CHANGELOG.md](./CHANGELOG.md) for full version history. Current: **v1.9.
|
|
129
|
+
See [CHANGELOG.md](./CHANGELOG.md) for full version history. Current: **v1.9.2** (27 tools, 44 data sources).
|
|
130
130
|
|
|
131
131
|
### v1.0.4 highlights (still in v1.6.3)
|
|
132
132
|
|
package/dist/icf/jargon.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jargon.d.ts","sourceRoot":"","sources":["../../src/icf/jargon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,iBAAiB,EAAE,aAAa,CAAC,WAAW,
|
|
1
|
+
{"version":3,"file":"jargon.d.ts","sourceRoot":"","sources":["../../src/icf/jargon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,iBAAiB,EAAE,aAAa,CAAC,WAAW,CAsLxD,CAAC;AASF;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,CAgCpD"}
|
package/dist/icf/jargon.js
CHANGED
|
@@ -129,10 +129,11 @@ export const JARGON_DICTIONARY = [
|
|
|
129
129
|
term: "efficacy",
|
|
130
130
|
plain_language: "how well the treatment works under controlled conditions",
|
|
131
131
|
},
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
132
|
+
// v1.9.1 fix: removed an "effectiveness" entry here. NIH Plain Language
|
|
133
|
+
// ICF guidance and FDA Communicating Risks and Benefits recommend
|
|
134
|
+
// "effectiveness" AS the plain-language replacement for "efficacy" —
|
|
135
|
+
// flagging it as jargon contradicts the cited authority and would tell
|
|
136
|
+
// investigators who did the right thing to undo it.
|
|
136
137
|
{ term: "incidence", plain_language: "how often new cases occur" },
|
|
137
138
|
{
|
|
138
139
|
term: "prevalence",
|
package/dist/icf/jargon.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jargon.js","sourceRoot":"","sources":["../../src/icf/jargon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAUH,MAAM,CAAC,MAAM,iBAAiB,GAA+B;IAC3D,2BAA2B;IAC3B,EAAE,IAAI,EAAE,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE;IAC5D,EAAE,IAAI,EAAE,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE;IAC5D;QACE,IAAI,EAAE,cAAc;QACpB,cAAc,EACZ,oEAAoE;KACvE;IACD;QACE,IAAI,EAAE,cAAc;QACpB,cAAc,EAAE,0CAA0C;KAC3D;IACD;QACE,IAAI,EAAE,SAAS;QACf,cAAc,EAAE,8CAA8C;KAC/D;IACD;QACE,IAAI,EAAE,YAAY;QAClB,cAAc,EACZ,uEAAuE;KAC1E;IACD;QACE,IAAI,EAAE,WAAW;QACjB,cAAc,EACZ,iEAAiE;KACpE;IACD,EAAE,IAAI,EAAE,YAAY,EAAE,cAAc,EAAE,oCAAoC,EAAE;IAC5E,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,8BAA8B,EAAE;IAClE,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE;IAClD,EAAE,IAAI,EAAE,cAAc,EAAE,cAAc,EAAE,6BAA6B,EAAE;IACvE,EAAE,IAAI,EAAE,YAAY,EAAE,cAAc,EAAE,8BAA8B,EAAE;IAEtE,0BAA0B;IAC1B;QACE,IAAI,EAAE,eAAe;QACrB,cAAc,EAAE,wCAAwC;KACzD;IACD,EAAE,IAAI,EAAE,kBAAkB,EAAE,cAAc,EAAE,aAAa,EAAE;IAC3D;QACE,IAAI,EAAE,uBAAuB;QAC7B,cAAc,EACZ,oGAAoG;KACvG;IACD,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE;IACtD;QACE,IAAI,EAAE,OAAO;QACb,cAAc,EACZ,yEAAyE;KAC5E;IACD,EAAE,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,wBAAwB,EAAE;IAE9D,eAAe;IACf;QACE,IAAI,EAAE,kBAAkB;QACxB,cAAc,EAAE,0CAA0C;KAC3D;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,cAAc,EAAE,qCAAqC;KACtD;IACD;QACE,IAAI,EAAE,iBAAiB;QACvB,cAAc,EAAE,4CAA4C;KAC7D;IACD;QACE,IAAI,EAAE,WAAW;QACjB,cAAc,EAAE,0CAA0C;KAC3D;IACD;QACE,IAAI,EAAE,YAAY;QAClB,cAAc,EAAE,+CAA+C;KAChE;IACD;QACE,IAAI,EAAE,YAAY;QAClB,cAAc,EAAE,wCAAwC;KACzD;IAED,qBAAqB;IACrB,EAAE,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE;IAC7C,EAAE,IAAI,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE;IAC9C,EAAE,IAAI,EAAE,WAAW,EAAE,cAAc,EAAE,8BAA8B,EAAE;IACrE;QACE,IAAI,EAAE,aAAa;QACnB,cAAc,EAAE,mCAAmC;KACpD;IACD,EAAE,IAAI,EAAE,eAAe,EAAE,cAAc,EAAE,yBAAyB,EAAE;IACpE,EAAE,IAAI,EAAE,aAAa,EAAE,cAAc,EAAE,kBAAkB,EAAE;IAC3D,EAAE,IAAI,EAAE,cAAc,EAAE,cAAc,EAAE,uBAAuB,EAAE;IACjE,EAAE,IAAI,EAAE,WAAW,EAAE,cAAc,EAAE,8BAA8B,EAAE;IACrE;QACE,IAAI,EAAE,YAAY;QAClB,cAAc,EAAE,sCAAsC;KACvD;IACD,EAAE,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,EAAE;IAC7C,EAAE,IAAI,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE;IAClD,EAAE,IAAI,EAAE,QAAQ,EAAE,cAAc,EAAE,eAAe,EAAE;IACnD;QACE,IAAI,EAAE,YAAY;QAClB,cAAc,EAAE,mDAAmD;KACpE;IACD,EAAE,IAAI,EAAE,YAAY,EAAE,cAAc,EAAE,wBAAwB,EAAE;IAChE;QACE,IAAI,EAAE,SAAS;QACf,cAAc,EAAE,uCAAuC;KACxD;IAED,4BAA4B;IAC5B;QACE,IAAI,EAAE,WAAW;QACjB,cAAc,EAAE,oDAAoD;KACrE;IACD,EAAE,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,0BAA0B,EAAE;IAChE;QACE,IAAI,EAAE,kBAAkB;QACxB,cAAc,EAAE,mCAAmC;KACpD;IACD;QACE,IAAI,EAAE,oBAAoB;QAC1B,cAAc,EAAE,qCAAqC;KACtD;IACD;QACE,IAAI,EAAE,UAAU;QAChB,cAAc,EAAE,0DAA0D;KAC3E;IACD;
|
|
1
|
+
{"version":3,"file":"jargon.js","sourceRoot":"","sources":["../../src/icf/jargon.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syllables.d.ts","sourceRoot":"","sources":["../../src/icf/syllables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAwCtD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"syllables.d.ts","sourceRoot":"","sources":["../../src/icf/syllables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAwCtD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAkCtD"}
|
package/dist/icf/syllables.js
CHANGED
|
@@ -61,19 +61,40 @@ export function countSyllables(rawWord) {
|
|
|
61
61
|
export function countComplexWord(word) {
|
|
62
62
|
// Gunning's "complex" = 3+ syllables, excluding proper nouns,
|
|
63
63
|
// compound words, and common suffix-only inflections (-es, -ed,
|
|
64
|
-
// -ing). Approximated here by stripping common
|
|
65
|
-
// syllable
|
|
64
|
+
// -ing). Approximated here by stripping common inflectional
|
|
65
|
+
// suffixes that DON'T contribute a syllable; we leave alone the
|
|
66
|
+
// ones that do.
|
|
67
|
+
//
|
|
68
|
+
// v1.9.1 fix: pre-fix unconditionally stripped "-es", which made
|
|
69
|
+
// `processes` (3 syllables: pro-ces-ses) look like 2-syllable
|
|
70
|
+
// `process`, leading Gunning Fog and SMOG to UNDER-count complex
|
|
71
|
+
// words and report falsely low grade levels — the unsafe direction
|
|
72
|
+
// for an ICF readability tool. Now we strip only when the suffix
|
|
73
|
+
// is non-syllabic: compare the syllable count before and after, and
|
|
74
|
+
// strip only if it's unchanged.
|
|
66
75
|
if (!word)
|
|
67
76
|
return false;
|
|
68
77
|
let base = word.toLowerCase().replace(/[^a-z]/g, "");
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
78
|
+
if (base.length === 0)
|
|
79
|
+
return false;
|
|
80
|
+
const tryStrip = (suffix, minLen) => {
|
|
81
|
+
if (!base.endsWith(suffix))
|
|
82
|
+
return null;
|
|
83
|
+
if (base.length <= minLen)
|
|
84
|
+
return null;
|
|
85
|
+
const stripped = base.slice(0, -suffix.length);
|
|
86
|
+
if (stripped.length === 0)
|
|
87
|
+
return null;
|
|
88
|
+
if (countSyllables(stripped) === countSyllables(base)) {
|
|
89
|
+
return stripped;
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
};
|
|
93
|
+
const after = tryStrip("ing", 4) ?? tryStrip("es", 3) ?? tryStrip("ed", 3);
|
|
94
|
+
if (after !== null)
|
|
95
|
+
base = after;
|
|
96
|
+
// "ied" (carried, married) keeps the syllable from the consonant+ied;
|
|
97
|
+
// covered above by the syllable-count check for "ed".
|
|
77
98
|
return countSyllables(base) >= 3;
|
|
78
99
|
}
|
|
79
100
|
//# sourceMappingURL=syllables.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syllables.js","sourceRoot":"","sources":["../../src/icf/syllables.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,MAAM,GAAG,UAAU,CAAC;AAE1B,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,IAAI,CAAC,OAAO;QAAE,OAAO,CAAC,CAAC;IACvB,IAAI,IAAI,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACxD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAChC,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAE/B,uDAAuD;IACvD,IACE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAClB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QACpB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QACpB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EACpB,CAAC;QACD,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IACD,+DAA+D;IAC/D,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC9C,IAAI,QAAQ,KAAK,GAAG,IAAI,QAAQ,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACnE,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,+DAA+D;IAC/D,gEAAgE;IAChE,+DAA+D;IAC/D,gEAAgE;IAChE,oBAAoB;IACpB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,KAAK,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;QACtB,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YACpB,IAAI,CAAC,OAAO;gBAAE,KAAK,EAAE,CAAC;YACtB,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,KAAK,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,8DAA8D;IAC9D,gEAAgE;IAChE
|
|
1
|
+
{"version":3,"file":"syllables.js","sourceRoot":"","sources":["../../src/icf/syllables.ts"],"names":[],"mappings":"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"}
|
package/dist/icf/types.d.ts
CHANGED
|
@@ -72,10 +72,14 @@ export interface IcfReadabilityAssessment {
|
|
|
72
72
|
/** User-supplied or default target grade level (e.g., 8). */
|
|
73
73
|
target_grade_level: number;
|
|
74
74
|
/**
|
|
75
|
-
* Overall verdict:
|
|
75
|
+
* Overall verdict (v1.9.1: aligned to actual code which uses AND):
|
|
76
76
|
* pass — FKGL ≤ target AND <20% sentences exceed target
|
|
77
|
-
* borderline — FKGL
|
|
78
|
-
*
|
|
77
|
+
* borderline — FKGL ≤ target+1.5 AND <40% sentences exceed target
|
|
78
|
+
* (and not already pass)
|
|
79
|
+
* fail — anything else (FKGL > target+1.5 OR ≥40% exceed)
|
|
80
|
+
* The AND semantics are stricter than an OR alternative; a passing
|
|
81
|
+
* FKGL with many bad sentences (or vice versa) drops to fail. This
|
|
82
|
+
* is the patient-safety direction.
|
|
79
83
|
*/
|
|
80
84
|
verdict: Verdict;
|
|
81
85
|
/**
|
package/dist/icf/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/icf/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,2DAA2D;IAC3D,aAAa,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,+BAA+B;IAC/B,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,+DAA+D;IAC/D,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,WAAW,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5D,qCAAqC;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,YAAY,GAAG,MAAM,CAAC;AAErD,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,kEAAkE;IAClE,eAAe,EAAE,aAAa,EAAE,CAAC;IACjC,6DAA6D;IAC7D,kBAAkB,EAAE,MAAM,CAAC;IAC3B
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/icf/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,2DAA2D;IAC3D,aAAa,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,+BAA+B;IAC/B,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,+DAA+D;IAC/D,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,8CAA8C;IAC9C,WAAW,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5D,qCAAqC;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,OAAO,GAAG,MAAM,GAAG,YAAY,GAAG,MAAM,CAAC;AAErD,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,kEAAkE;IAClE,eAAe,EAAE,aAAa,EAAE,CAAC;IACjC,6DAA6D;IAC7D,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;OASG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,sEAAsE;IACtE,WAAW,EAAE,SAAS,CAAC;CACxB;AAED,MAAM,WAAW,wBAAwB;IACvC,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oFAAoF;IACpF,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,eAAO,MAAM,WAAW,EAAG,SAAkB,CAAC"}
|
package/dist/icf/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/icf/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/icf/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAoGH,MAAM,CAAC,MAAM,WAAW,GAAG,SAAkB,CAAC"}
|
package/dist/models/evppi.d.ts
CHANGED
|
@@ -60,5 +60,12 @@ export interface PSAIterationData {
|
|
|
60
60
|
delta_qaly: number;
|
|
61
61
|
params: Record<string, number>;
|
|
62
62
|
}
|
|
63
|
-
export declare function computeEVPPI(iterations: PSAIterationData[], lambda: number, parameterNames: string[]
|
|
63
|
+
export declare function computeEVPPI(iterations: PSAIterationData[], lambda: number, parameterNames: string[],
|
|
64
|
+
/**
|
|
65
|
+
* Optional RNG. Defaults to `Math.random` for production. Tests pass
|
|
66
|
+
* a seeded mulberry32 so the bootstrap CI is reproducible. v1.9.2:
|
|
67
|
+
* pre-fix all bootstrap calls used `Math.random` unconditionally,
|
|
68
|
+
* which made tests like "CI tightens at N" theoretically flaky.
|
|
69
|
+
*/
|
|
70
|
+
rng?: () => number): EVPPIResult[];
|
|
64
71
|
//# sourceMappingURL=evppi.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evppi.d.ts","sourceRoot":"","sources":["../../src/models/evppi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;
|
|
1
|
+
{"version":3,"file":"evppi.d.ts","sourceRoot":"","sources":["../../src/models/evppi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4EAA4E;IAC5E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAiJD,wBAAgB,YAAY,CAC1B,UAAU,EAAE,gBAAgB,EAAE,EAC9B,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,EAAE;AACxB;;;;;GAKG;AACH,GAAG,GAAE,MAAM,MAAoB,GAC9B,WAAW,EAAE,CAkEf"}
|
package/dist/models/evppi.js
CHANGED
|
@@ -136,25 +136,38 @@ function rawEVPPIPoint(iterations, lambda, paramName) {
|
|
|
136
136
|
* Bootstrap CI for one parameter's EVPPI. Returns mean + 95% CI bounds
|
|
137
137
|
* + standard error from resamples. Computationally O(B · N log N).
|
|
138
138
|
*/
|
|
139
|
-
function bootstrapEVPPICI(iterations, lambda, paramName, totalEVPI) {
|
|
139
|
+
function bootstrapEVPPICI(iterations, lambda, paramName, totalEVPI, rng = Math.random) {
|
|
140
140
|
const B = BOOTSTRAP_RESAMPLES;
|
|
141
141
|
const N = iterations.length;
|
|
142
142
|
const samples = [];
|
|
143
143
|
for (let b = 0; b < B; b++) {
|
|
144
144
|
const resample = new Array(N);
|
|
145
145
|
for (let i = 0; i < N; i++) {
|
|
146
|
-
resample[i] = iterations[Math.floor(
|
|
146
|
+
resample[i] = iterations[Math.floor(rng() * N)];
|
|
147
147
|
}
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
// v1.9.1 fix: do NOT cap at the original totalEVPI here. Capping
|
|
149
|
+
// inside the bootstrap loop truncates the upper tail of the
|
|
150
|
+
// bootstrap distribution whenever a resample produces a higher raw
|
|
151
|
+
// EVPPI than the original — that's a systematic downward bias on
|
|
152
|
+
// evppi_ci_upper. Each bootstrap resample has its own empirical
|
|
153
|
+
// totalEVPI; let the distribution range freely. We only cap the
|
|
154
|
+
// FINAL reported percentile bounds at totalEVPI below.
|
|
155
|
+
samples.push(Math.max(0, rawEVPPIPoint(resample, lambda, paramName)));
|
|
150
156
|
}
|
|
151
157
|
samples.sort((a, b) => a - b);
|
|
152
|
-
const lower = Math.max(0, quantile(samples, 0.025));
|
|
153
|
-
const upper = Math.max(0, quantile(samples, 0.975));
|
|
158
|
+
const lower = Math.max(0, Math.min(quantile(samples, 0.025), totalEVPI));
|
|
159
|
+
const upper = Math.max(0, Math.min(quantile(samples, 0.975), totalEVPI));
|
|
154
160
|
const se = stddev(samples);
|
|
155
161
|
return { lower, upper, se };
|
|
156
162
|
}
|
|
157
|
-
export function computeEVPPI(iterations, lambda, parameterNames
|
|
163
|
+
export function computeEVPPI(iterations, lambda, parameterNames,
|
|
164
|
+
/**
|
|
165
|
+
* Optional RNG. Defaults to `Math.random` for production. Tests pass
|
|
166
|
+
* a seeded mulberry32 so the bootstrap CI is reproducible. v1.9.2:
|
|
167
|
+
* pre-fix all bootstrap calls used `Math.random` unconditionally,
|
|
168
|
+
* which made tests like "CI tightens at N" theoretically flaky.
|
|
169
|
+
*/
|
|
170
|
+
rng = Math.random) {
|
|
158
171
|
const N = iterations.length;
|
|
159
172
|
if (N < 20)
|
|
160
173
|
return [];
|
|
@@ -194,7 +207,7 @@ export function computeEVPPI(iterations, lambda, parameterNames) {
|
|
|
194
207
|
};
|
|
195
208
|
// Bootstrap CI when sample is large enough to be meaningful.
|
|
196
209
|
if (N >= MIN_N_FOR_BOOTSTRAP) {
|
|
197
|
-
const ci = bootstrapEVPPICI(iterations, lambda, paramName, totalEVPI);
|
|
210
|
+
const ci = bootstrapEVPPICI(iterations, lambda, paramName, totalEVPI, rng);
|
|
198
211
|
result.evppi_ci_lower = ci.lower;
|
|
199
212
|
result.evppi_ci_upper = ci.upper;
|
|
200
213
|
result.evppi_se = ci.se;
|
package/dist/models/evppi.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evppi.js","sourceRoot":"","sources":["../../src/models/evppi.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"evppi.js","sourceRoot":"","sources":["../../src/models/evppi.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"survivalFitting.d.ts","sourceRoot":"","sources":["../../src/models/survivalFitting.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC;CACd;AAED,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb,SAAS,GACT,cAAc,GACd,YAAY,GACZ,UAAU,CAAC;AAEf,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,gBAAgB,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACjC,eAAe,EAAE,MAAM,CAAC;IACxB,wBAAwB,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,kBAAkB,EAAE,CAAC;IAC3B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,KAAK,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;CACJ;
|
|
1
|
+
{"version":3,"file":"survivalFitting.d.ts","sourceRoot":"","sources":["../../src/models/survivalFitting.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC;CACd;AAED,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb,SAAS,GACT,cAAc,GACd,YAAY,GACZ,UAAU,CAAC;AAEf,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,gBAAgB,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACnC,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACjC,eAAe,EAAE,MAAM,CAAC;IACxB,wBAAwB,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,kBAAkB,EAAE,CAAC;IAC3B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,KAAK,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;CACJ;AA6sBD;;GAEG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,cAAc,EAAE,EACxB,QAAQ,GAAE,MAAiB,GAC1B,iBAAiB,CAwDnB;AA8DD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,WAAW,EAAE,EACnB,QAAQ,GAAE,MAAiB,GAC1B,iBAAiB,CAiDnB"}
|
|
@@ -138,8 +138,26 @@ function nelderMead(fn, initial, maxIter = 500) {
|
|
|
138
138
|
point[i] = point[i] * 1.5 + 0.1;
|
|
139
139
|
simplex.push({ point, value: fn(point) });
|
|
140
140
|
}
|
|
141
|
+
// Convergence tolerance — when the spread of objective values across
|
|
142
|
+
// the simplex falls below this in absolute or relative terms, we
|
|
143
|
+
// declare convergence and exit early. v1.9.2 added: pre-fix the
|
|
144
|
+
// optimizer always ran maxIter iterations, wasting compute on
|
|
145
|
+
// already-converged simplices and giving no signal when it failed
|
|
146
|
+
// to converge before maxIter ran out.
|
|
147
|
+
const TOL_ABS = 1e-8;
|
|
148
|
+
const TOL_REL = 1e-6;
|
|
141
149
|
for (let iter = 0; iter < maxIter; iter++) {
|
|
142
150
|
simplex.sort((a, b) => a.value - b.value);
|
|
151
|
+
// Convergence check — function-value spread across simplex vertices.
|
|
152
|
+
// Use both absolute and relative tolerances so well-scaled and
|
|
153
|
+
// ill-scaled objectives both terminate appropriately.
|
|
154
|
+
const fBest = simplex[0].value;
|
|
155
|
+
const fWorst = simplex[n].value;
|
|
156
|
+
const spread = Math.abs(fWorst - fBest);
|
|
157
|
+
if (spread < TOL_ABS ||
|
|
158
|
+
spread < TOL_REL * Math.max(Math.abs(fBest), Math.abs(fWorst), 1)) {
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
143
161
|
// Centroid (excluding worst)
|
|
144
162
|
const centroid = new Array(n).fill(0);
|
|
145
163
|
for (let i = 0; i < n; i++) {
|
|
@@ -313,13 +331,19 @@ function fitGompertz(data) {
|
|
|
313
331
|
* Uses f(t) = h(t)·S(t). Numerically guarded against log(0).
|
|
314
332
|
*/
|
|
315
333
|
function logLikelihoodFromEvents(events, survFn, hazardFn) {
|
|
334
|
+
// Log floor: 1e-30 ⇒ log = -69. v1.9.2 raised from 1e-300 (log = -690).
|
|
335
|
+
// R's flexsurv / survival packages use a similar order-of-magnitude
|
|
336
|
+
// floor; values further into the tail produce nearly-flat likelihood
|
|
337
|
+
// surfaces that confuse Nelder-Mead navigation without contributing
|
|
338
|
+
// useful gradient information.
|
|
339
|
+
const LOG_FLOOR = 1e-30;
|
|
316
340
|
let ll = 0;
|
|
317
341
|
for (const row of events) {
|
|
318
342
|
const t = row.time;
|
|
319
|
-
const s = Math.max(
|
|
343
|
+
const s = Math.max(LOG_FLOOR, survFn(t));
|
|
320
344
|
if (row.event === 1) {
|
|
321
345
|
// log f(t) = log h(t) + log S(t)
|
|
322
|
-
const h = Math.max(
|
|
346
|
+
const h = Math.max(LOG_FLOOR, hazardFn(t));
|
|
323
347
|
ll += Math.log(h) + Math.log(s);
|
|
324
348
|
}
|
|
325
349
|
else {
|
|
@@ -340,7 +364,7 @@ function initialMedian(events) {
|
|
|
340
364
|
return 1;
|
|
341
365
|
return sorted[Math.floor(sorted.length / 2)];
|
|
342
366
|
}
|
|
343
|
-
function fitExponentialFromEvents(events) {
|
|
367
|
+
function fitExponentialFromEvents(events, kmTable) {
|
|
344
368
|
const m = initialMedian(events);
|
|
345
369
|
const lambdaInit = Math.max(1e-6, Math.log(2) / m);
|
|
346
370
|
const opt = nelderMead((p) => -logLikelihoodFromEvents(events, (t) => expSurvival(t, Math.max(1e-9, p[0])), (_t) => Math.max(1e-9, p[0])), [lambdaInit]);
|
|
@@ -348,84 +372,120 @@ function fitExponentialFromEvents(events) {
|
|
|
348
372
|
const ll = logLikelihoodFromEvents(events, (t) => expSurvival(t, lambda), () => lambda);
|
|
349
373
|
const k = 1;
|
|
350
374
|
const n = events.length;
|
|
375
|
+
const survFn = (t) => expSurvival(t, lambda);
|
|
351
376
|
return {
|
|
352
377
|
name: "exponential",
|
|
353
378
|
params: { lambda },
|
|
354
379
|
aic: -2 * ll + 2 * k,
|
|
355
380
|
bic: -2 * ll + k * Math.log(n),
|
|
356
381
|
log_likelihood: ll,
|
|
357
|
-
survival_at:
|
|
382
|
+
survival_at: survFn,
|
|
358
383
|
hazard_at: () => lambda,
|
|
359
384
|
median_survival: Math.log(2) / lambda,
|
|
360
|
-
|
|
385
|
+
// True restricted mean ∫₀ᵀ S(t)dt up to max observed time, via the
|
|
386
|
+
// KM table built from the same event data. Pre-v1.9.1 returned
|
|
387
|
+
// 1/lambda (the unrestricted mean) — wrong field semantics.
|
|
388
|
+
mean_survival_restricted: restrictedMean(kmTable, survFn),
|
|
361
389
|
};
|
|
362
390
|
}
|
|
363
|
-
function fitWeibullFromEvents(events) {
|
|
391
|
+
function fitWeibullFromEvents(events, kmTable) {
|
|
364
392
|
const m = initialMedian(events);
|
|
365
393
|
const scaleInit = Math.max(0.01, m / Math.pow(Math.log(2), 1));
|
|
366
|
-
const opt = nelderMead((p) => -logLikelihoodFromEvents(events, (t) => weibullSurvival(t, Math.max(0.05, p[0]), Math.max(0.01, p[1])), (t) => weibullHazard(t, Math.max(0.05, p[0]), Math.max(0.01, p[1]))),
|
|
394
|
+
const opt = nelderMead((p) => -logLikelihoodFromEvents(events, (t) => weibullSurvival(t, Math.max(0.05, p[0]), Math.max(0.01, p[1])), (t) => weibullHazard(t, Math.max(0.05, p[0]), Math.max(0.01, p[1]))),
|
|
395
|
+
// shape=1 ⇒ Weibull degenerates to Exponential — neutral start that
|
|
396
|
+
// doesn't bias toward increasing or decreasing hazard. scaleInit
|
|
397
|
+
// derived from empirical median assumes shape≈1 (correct for the
|
|
398
|
+
// start, refined by the optimizer).
|
|
399
|
+
[1.0, scaleInit], 800);
|
|
367
400
|
const shape = Math.max(0.05, opt[0]);
|
|
368
401
|
const scale = Math.max(0.01, opt[1]);
|
|
369
402
|
const ll = logLikelihoodFromEvents(events, (t) => weibullSurvival(t, shape, scale), (t) => weibullHazard(t, shape, scale));
|
|
370
403
|
const k = 2;
|
|
371
404
|
const n = events.length;
|
|
405
|
+
const survFn = (t) => weibullSurvival(t, shape, scale);
|
|
372
406
|
return {
|
|
373
407
|
name: "weibull",
|
|
374
408
|
params: { shape, scale },
|
|
375
409
|
aic: -2 * ll + 2 * k,
|
|
376
410
|
bic: -2 * ll + k * Math.log(n),
|
|
377
411
|
log_likelihood: ll,
|
|
378
|
-
survival_at:
|
|
412
|
+
survival_at: survFn,
|
|
379
413
|
hazard_at: (t) => weibullHazard(t, shape, scale),
|
|
380
414
|
median_survival: scale * Math.pow(Math.log(2), 1 / shape),
|
|
381
|
-
|
|
415
|
+
// True RMST via numerical integration of S(t) over [0, max_observed].
|
|
416
|
+
// Pre-v1.9.1 returned scale·Γ(1+1/shape) = unrestricted mean.
|
|
417
|
+
mean_survival_restricted: restrictedMean(kmTable, survFn),
|
|
382
418
|
};
|
|
383
419
|
}
|
|
384
|
-
function fitLogLogisticFromEvents(events) {
|
|
420
|
+
function fitLogLogisticFromEvents(events, kmTable) {
|
|
385
421
|
const m = initialMedian(events);
|
|
386
|
-
const opt = nelderMead((p) => -logLikelihoodFromEvents(events, (t) => logLogisticSurvival(t, Math.max(0.01, p[0]), Math.max(0.1, p[1])), (t) => logLogisticHazard(t, Math.max(0.01, p[0]), Math.max(0.1, p[1]))),
|
|
422
|
+
const opt = nelderMead((p) => -logLikelihoodFromEvents(events, (t) => logLogisticSurvival(t, Math.max(0.01, p[0]), Math.max(0.1, p[1])), (t) => logLogisticHazard(t, Math.max(0.01, p[0]), Math.max(0.1, p[1]))),
|
|
423
|
+
// α=median, β=1.5: β>1 means the hazard is unimodal (rises then
|
|
424
|
+
// falls), which is the most common shape in survival data. β=1.5
|
|
425
|
+
// is empirically the median of fitted β values across published
|
|
426
|
+
// log-logistic survival curves; β<1 (monotone-decreasing hazard)
|
|
427
|
+
// is rarer.
|
|
428
|
+
[m, 1.5], 800);
|
|
387
429
|
const alpha = Math.max(0.01, opt[0]);
|
|
388
430
|
const beta = Math.max(0.1, opt[1]);
|
|
389
431
|
const ll = logLikelihoodFromEvents(events, (t) => logLogisticSurvival(t, alpha, beta), (t) => logLogisticHazard(t, alpha, beta));
|
|
390
432
|
const k = 2;
|
|
391
433
|
const n = events.length;
|
|
434
|
+
const survFn = (t) => logLogisticSurvival(t, alpha, beta);
|
|
392
435
|
return {
|
|
393
436
|
name: "log_logistic",
|
|
394
437
|
params: { alpha, beta },
|
|
395
438
|
aic: -2 * ll + 2 * k,
|
|
396
439
|
bic: -2 * ll + k * Math.log(n),
|
|
397
440
|
log_likelihood: ll,
|
|
398
|
-
survival_at:
|
|
441
|
+
survival_at: survFn,
|
|
399
442
|
hazard_at: (t) => logLogisticHazard(t, alpha, beta),
|
|
400
443
|
median_survival: alpha,
|
|
401
|
-
|
|
444
|
+
// True RMST via numerical integration. Pre-v1.9.1 returned alpha
|
|
445
|
+
// (the median, not the mean) as a fallback because the unrestricted
|
|
446
|
+
// mean is undefined for β ≤ 1; restricted mean over [0, T] is
|
|
447
|
+
// always finite and is the correct field semantics.
|
|
448
|
+
mean_survival_restricted: restrictedMean(kmTable, survFn),
|
|
402
449
|
};
|
|
403
450
|
}
|
|
404
|
-
function fitLogNormalFromEvents(events) {
|
|
451
|
+
function fitLogNormalFromEvents(events, kmTable) {
|
|
405
452
|
const m = initialMedian(events);
|
|
406
453
|
const muInit = Math.log(Math.max(0.01, m));
|
|
407
|
-
const opt = nelderMead((p) => -logLikelihoodFromEvents(events, (t) => logNormalSurvival(t, p[0], Math.max(0.01, p[1])), (t) => logNormalHazard(t, p[0], Math.max(0.01, p[1]))),
|
|
454
|
+
const opt = nelderMead((p) => -logLikelihoodFromEvents(events, (t) => logNormalSurvival(t, p[0], Math.max(0.01, p[1])), (t) => logNormalHazard(t, p[0], Math.max(0.01, p[1]))),
|
|
455
|
+
// μ_init=log(median): exact when σ=0, biased upward when σ>0 but a
|
|
456
|
+
// good neighborhood. σ_init=0.8: oncology log-normal fits typically
|
|
457
|
+
// have σ in [0.5, 1.5]; 0.8 is the conservative middle. A larger
|
|
458
|
+
// start would over-disperse the initial likelihood and slow convergence.
|
|
459
|
+
[muInit, 0.8], 800);
|
|
408
460
|
const mu = opt[0];
|
|
409
461
|
const sigma = Math.max(0.01, opt[1]);
|
|
410
462
|
const ll = logLikelihoodFromEvents(events, (t) => logNormalSurvival(t, mu, sigma), (t) => logNormalHazard(t, mu, sigma));
|
|
411
463
|
const k = 2;
|
|
412
464
|
const n = events.length;
|
|
465
|
+
const survFn = (t) => logNormalSurvival(t, mu, sigma);
|
|
413
466
|
return {
|
|
414
467
|
name: "log_normal",
|
|
415
468
|
params: { mu, sigma },
|
|
416
469
|
aic: -2 * ll + 2 * k,
|
|
417
470
|
bic: -2 * ll + k * Math.log(n),
|
|
418
471
|
log_likelihood: ll,
|
|
419
|
-
survival_at:
|
|
472
|
+
survival_at: survFn,
|
|
420
473
|
hazard_at: (t) => logNormalHazard(t, mu, sigma),
|
|
421
474
|
median_survival: Math.exp(mu),
|
|
422
|
-
|
|
475
|
+
// True RMST. Pre-v1.9.1 returned exp(μ + σ²/2) = unrestricted mean.
|
|
476
|
+
mean_survival_restricted: restrictedMean(kmTable, survFn),
|
|
423
477
|
};
|
|
424
478
|
}
|
|
425
|
-
function fitGompertzFromEvents(events) {
|
|
479
|
+
function fitGompertzFromEvents(events, kmTable) {
|
|
426
480
|
const m = initialMedian(events);
|
|
427
481
|
const rateInit = Math.max(1e-6, Math.log(2) / m);
|
|
428
|
-
const opt = nelderMead((p) => -logLikelihoodFromEvents(events, (t) => gompertzSurvival(t, p[0], Math.max(1e-6, p[1])), (t) => gompertzHazard(t, p[0], Math.max(1e-6, p[1]))),
|
|
482
|
+
const opt = nelderMead((p) => -logLikelihoodFromEvents(events, (t) => gompertzSurvival(t, p[0], Math.max(1e-6, p[1])), (t) => gompertzHazard(t, p[0], Math.max(1e-6, p[1]))),
|
|
483
|
+
// shape=0.01 ≈ flat hazard ≈ Exponential. Gompertz shape>0 gives
|
|
484
|
+
// increasing hazard (mortality acceleration with age, the typical
|
|
485
|
+
// case); shape<0 gives decreasing hazard. Starting near 0 lets the
|
|
486
|
+
// optimizer choose the sign without bias. rate_init = log(2)/median
|
|
487
|
+
// is exact for exponential and a reasonable neighborhood for Gompertz.
|
|
488
|
+
[0.01, rateInit], 800);
|
|
429
489
|
const shape = opt[0];
|
|
430
490
|
const rate = Math.max(1e-6, opt[1]);
|
|
431
491
|
const ll = logLikelihoodFromEvents(events, (t) => gompertzSurvival(t, shape, rate), (t) => gompertzHazard(t, shape, rate));
|
|
@@ -439,16 +499,21 @@ function fitGompertzFromEvents(events) {
|
|
|
439
499
|
break;
|
|
440
500
|
}
|
|
441
501
|
}
|
|
502
|
+
const survFn = (t) => gompertzSurvival(t, shape, rate);
|
|
442
503
|
return {
|
|
443
504
|
name: "gompertz",
|
|
444
505
|
params: { shape, rate },
|
|
445
506
|
aic: -2 * ll + 2 * k,
|
|
446
507
|
bic: -2 * ll + k * Math.log(n),
|
|
447
508
|
log_likelihood: ll,
|
|
448
|
-
survival_at:
|
|
509
|
+
survival_at: survFn,
|
|
449
510
|
hazard_at: (t) => gompertzHazard(t, shape, rate),
|
|
450
511
|
median_survival: median,
|
|
451
|
-
|
|
512
|
+
// True RMST via numerical integration. Pre-v1.9.1 returned
|
|
513
|
+
// `median × 1.4427` — that's `1/ln(2)`, the *exponential
|
|
514
|
+
// distribution's* mean/median ratio, applied to a Gompertz median.
|
|
515
|
+
// Reviewer caught this: wrong distribution entirely.
|
|
516
|
+
mean_survival_restricted: restrictedMean(kmTable, survFn),
|
|
452
517
|
};
|
|
453
518
|
}
|
|
454
519
|
/**
|
|
@@ -484,18 +549,23 @@ export function fitSurvivalCurvesFromEventData(events, timeUnit = "months") {
|
|
|
484
549
|
throw new Error("At least 5 patient-level event-data rows required for parametric fitting");
|
|
485
550
|
}
|
|
486
551
|
const sorted = [...events].sort((a, b) => a.time - b.time);
|
|
552
|
+
// Build the KM table FIRST so each fitter can use it for the
|
|
553
|
+
// restricted-mean integration (numerical ∫₀ᵀ S(t)dt up to max
|
|
554
|
+
// observed time, where T = sorted[-1].time). v1.9.1 fix: pre-fix the
|
|
555
|
+
// IPD fitters returned unrestricted means (or in Gompertz's case
|
|
556
|
+
// median × 1/ln(2), an exponential-distribution constant!) labeled
|
|
557
|
+
// as "restricted mean", which propagated wrong RMST → wrong QALY in
|
|
558
|
+
// downstream cost-effectiveness models.
|
|
559
|
+
const kmTable = computeKaplanMeier(sorted);
|
|
487
560
|
const fits = [
|
|
488
|
-
fitExponentialFromEvents(sorted),
|
|
489
|
-
fitWeibullFromEvents(sorted),
|
|
490
|
-
fitLogLogisticFromEvents(sorted),
|
|
491
|
-
fitLogNormalFromEvents(sorted),
|
|
492
|
-
fitGompertzFromEvents(sorted),
|
|
561
|
+
fitExponentialFromEvents(sorted, kmTable),
|
|
562
|
+
fitWeibullFromEvents(sorted, kmTable),
|
|
563
|
+
fitLogLogisticFromEvents(sorted, kmTable),
|
|
564
|
+
fitLogNormalFromEvents(sorted, kmTable),
|
|
565
|
+
fitGompertzFromEvents(sorted, kmTable),
|
|
493
566
|
];
|
|
494
567
|
const byAIC = [...fits].sort((a, b) => a.aic - b.aic);
|
|
495
568
|
const byBIC = [...fits].sort((a, b) => a.bic - b.bic);
|
|
496
|
-
// Build a synthetic KM table from the event data for the markdown
|
|
497
|
-
// extrapolation comparison column. Standard Kaplan-Meier estimator.
|
|
498
|
-
const kmTable = computeKaplanMeier(sorted);
|
|
499
569
|
// Extrapolations 0..2× max observed time.
|
|
500
570
|
const maxObserved = sorted[sorted.length - 1].time;
|
|
501
571
|
const extrapolationTimes = [];
|