diff --git a/docker-compose.monitoring.yml b/docker-compose.monitoring.yml index 1603947..460b816 100644 --- a/docker-compose.monitoring.yml +++ b/docker-compose.monitoring.yml @@ -10,7 +10,7 @@ services: loki: image: grafana/loki:3.4.2 ports: - - "127.0.0.1:3100:3100" + - "127.0.0.1:3101:3100" command: -config.file=/etc/loki/loki-config.yaml volumes: - loki-data:/loki diff --git a/public/components/calculators.html b/public/components/calculators.html index 7bc69ee..95fc3be 100644 --- a/public/components/calculators.html +++ b/public/components/calculators.html @@ -372,7 +372,9 @@ - + + +
diff --git a/public/js/calculators.js b/public/js/calculators.js index 5bfa607..c5b41c1 100644 --- a/public/js/calculators.js +++ b/public/js/calculators.js @@ -1282,21 +1282,37 @@ // Values read from published nomogram curves at key time points // NOTE: The AAP 2022 raised thresholds ~2 mg/dL above the 2004 guidelines - // >= 38 weeks, no neurotoxicity risk factors (Figure 2, upper curve) + // AAP 2022 exact phototherapy thresholds (extracted from PediTools/AAP nomograms) + // >= 38 weeks, no neurotoxicity risk factors var photoThresholds38 = { - 12: 8.0, 24: 12.0, 36: 14.0, 48: 15.5, 60: 17.0, 72: 18.0, 84: 18.5, 96: 19.0, 108: 19.5, 120: 20.0 + 12: 10.1, 24: 12.3, 36: 14.2, 48: 16.0, 60: 17.5, 72: 18.8, 84: 19.9, 96: 20.7, 120: 20.9 }; - // >= 38 weeks, WITH neurotoxicity risk factors (Figure 2, lower curve) + // >= 38 weeks, WITH neurotoxicity risk factors var photoThresholds38risk = { - 12: 6.0, 24: 10.0, 36: 12.0, 48: 13.5, 60: 15.0, 72: 16.0, 84: 16.5, 96: 17.0, 108: 17.5, 120: 18.0 + 12: 8.5, 24: 10.5, 36: 12.4, 48: 14.0, 60: 15.4, 72: 16.6, 84: 17.5, 96: 18.2, 120: 18.2 }; - // 35-37 weeks, no neurotoxicity risk factors (Figure 3, upper curve) + // 36 weeks, no neurotoxicity risk factors + var photoThresholds36 = { + 12: 9.0, 24: 11.2, 36: 13.1, 48: 14.8, 60: 16.2, 72: 17.5, 84: 18.5, 96: 19.3, 120: 19.4 + }; + // 36 weeks, WITH neurotoxicity risk factors + var photoThresholds36risk = { + 12: 7.4, 24: 9.4, 36: 11.2, 48: 12.8, 60: 14.2, 72: 15.4, 84: 16.3, 96: 17.0, 120: 17.1 + }; + // 35 weeks, no neurotoxicity risk factors var photoThresholds35 = { - 12: 5.5, 24: 9.0, 36: 11.0, 48: 12.5, 60: 14.0, 72: 14.5, 84: 15.0, 96: 15.5, 108: 16.0, 120: 16.0 + 12: 8.5, 24: 10.6, 36: 12.5, 48: 14.2, 60: 15.6, 72: 16.8, 84: 17.8, 96: 18.6, 120: 18.7 }; - // 35-37 weeks, WITH neurotoxicity risk factors (Figure 3, lower curve) + // 35 weeks, WITH neurotoxicity risk factors var photoThresholds35risk = { - 12: 4.0, 24: 7.5, 36: 9.0, 48: 10.5, 60: 12.0, 72: 12.5, 84: 13.0, 96: 13.5, 108: 14.0, 120: 14.0 + 12: 6.9, 24: 8.9, 36: 10.6, 48: 12.2, 60: 13.5, 72: 14.6, 84: 15.5, 96: 16.1, 120: 16.3 + }; + // Exchange transfusion thresholds (AAP 2022) + var exchangeThresholds38 = { + 12: 19.7, 24: 21.4, 36: 22.8, 48: 24.0, 60: 25.1, 72: 25.9, 84: 26.6, 96: 27.0 + }; + var exchangeThresholds38risk = { + 12: 16.3, 24: 17.7, 36: 19.0, 48: 20.1, 60: 21.2, 72: 22.1, 84: 22.9, 96: 23.5 }; function interpolateThreshold(table, hours) { @@ -1333,16 +1349,24 @@ var risk = document.getElementById('bili-risk').value; if (!ga || isNaN(hours) || isNaN(tsb)) { showToast('Fill in all fields', 'error'); return; } + var gaNum = parseInt(ga); var table; - if (parseInt(ga) >= 38) table = risk === 'medium' ? photoThresholds38risk : photoThresholds38; + if (gaNum >= 38) table = risk === 'medium' ? photoThresholds38risk : photoThresholds38; + else if (gaNum === 36 || gaNum === 37) table = risk === 'medium' ? photoThresholds36risk : photoThresholds36; else table = risk === 'medium' ? photoThresholds35risk : photoThresholds35; var threshold = interpolateThreshold(table, hours); var aboveThreshold = tsb >= threshold; - var cl = aboveThreshold - ? { text: 'Above Phototherapy Threshold', color: '#ef4444', bg: '#fee2e2' } - : { text: 'Below Phototherapy Threshold', color: '#10b981', bg: '#d1fae5' }; + // Check exchange transfusion threshold too + var exchangeTable = gaNum >= 38 ? (risk === 'medium' ? exchangeThresholds38risk : exchangeThresholds38) : null; + var exchangeThreshold = exchangeTable ? interpolateThreshold(exchangeTable, hours) : null; + var aboveExchange = exchangeThreshold && tsb >= exchangeThreshold; + + var cl; + if (aboveExchange) cl = { text: 'ABOVE EXCHANGE TRANSFUSION THRESHOLD', color: '#7f1d1d', bg: '#fecaca' }; + else if (aboveThreshold) cl = { text: 'Above Phototherapy Threshold', color: '#ef4444', bg: '#fee2e2' }; + else cl = { text: 'Below Phototherapy Threshold', color: '#10b981', bg: '#d1fae5' }; var resultDiv = document.getElementById('bili-result'); resultDiv.classList.remove('hidden'); @@ -1353,15 +1377,20 @@ '
' + '
' + '
Patient TSB
' + tsb + '
mg/dL
' + - '
Threshold
' + threshold.toFixed(1) + '
mg/dL at ' + hours + 'h
' + - '
Margin
' + (tsb >= threshold ? '+' : '') + (tsb - threshold).toFixed(1) + '
mg/dL ' + (aboveThreshold ? 'above' : 'below') + '
' + + '
Photo Threshold
' + threshold.toFixed(1) + '
mg/dL at ' + hours + 'h
' + + '
Margin
' + (tsb >= threshold ? '+' : '') + (tsb - threshold).toFixed(1) + '
mg/dL ' + (aboveThreshold ? 'above' : 'below') + ' photo
' + + (exchangeThreshold ? '
Exchange Threshold
' + exchangeThreshold.toFixed(1) + '
mg/dL' + (aboveExchange ? ' — EXCEEDED' : '') + '
' : '') + '
' + - '

GA ' + ga + ' weeks, ' + (risk === 'medium' ? 'with' : 'without') + ' neurotoxicity risk factors. AAP 2022 CPG. Always use clinical judgment.

'; + '

GA ' + ga + ' weeks, ' + (risk === 'medium' ? 'with' : 'without') + ' neurotoxicity risk factors. AAP 2022 CPG (exact values from published nomograms). Always use clinical judgment.

'; - // Chart: phototherapy threshold line vs patient - renderBiliChart(hours, tsb, [ + // Chart: phototherapy + exchange threshold lines vs patient + var chartDatasets = [ { label: 'Phototherapy Threshold', data: generateThresholdCurve(table), borderColor: '#ef4444', borderWidth: 2, borderDash: [], fill: { target: 'origin', above: 'rgba(239,68,68,0.08)' } } - ]); + ]; + if (exchangeTable) { + chartDatasets.push({ label: 'Exchange Transfusion', data: generateThresholdCurve(exchangeTable), borderColor: '#7f1d1d', borderWidth: 2, borderDash: [6,3], fill: false }); + } + renderBiliChart(hours, tsb, chartDatasets); }); document.getElementById('btn-clear-bili-aap').addEventListener('click', function() {