@cornerstonejs/calculate-suv
Advanced tools
Comparing version 1.0.3 to 1.1.0
@@ -353,9 +353,8 @@ 'use strict'; | ||
let LBM; | ||
const bodyMassIndex = PatientWeight * PatientWeight / (PatientSize * PatientSize * 10000); // convert size in cm | ||
// reference: https://www.medicalconnections.co.uk/kb/calculating-suv-from-pet-images/ | ||
const weightSizeFactor = Math.pow(PatientWeight / (PatientSize * 100), 2); // reference: https://www.medicalconnections.co.uk/kb/calculating-suv-from-pet-images/ | ||
if (PatientSex === 'F') { | ||
LBM = 1.07 * PatientWeight - 148 * bodyMassIndex; | ||
LBM = 1.07 * PatientWeight - 148 * weightSizeFactor; | ||
} else if (PatientSex === 'M') { | ||
LBM = 1.1 * PatientWeight - 120 * bodyMassIndex; | ||
LBM = 1.1 * PatientWeight - 120 * weightSizeFactor; | ||
} else { | ||
@@ -367,3 +366,31 @@ throw new Error(`PatientSex is an invalid value: ${PatientSex}`); | ||
} | ||
/** | ||
* From https://link.springer.com/article/10.1007/s00259-014-2961-x | ||
* and https://link.springer.com/article/10.2165/00003088-200544100-00004 | ||
* and | ||
* @param inputs | ||
* @returns | ||
*/ | ||
function calculateSUVlbmJanmahasatianScalingFactor(inputs) { | ||
const { | ||
PatientSex, | ||
PatientWeight, | ||
PatientSize | ||
} = inputs; | ||
let LBM; | ||
const bodyMassIndex = PatientWeight / Math.pow(PatientSize, 2); | ||
if (PatientSex === 'F') { | ||
LBM = 9270 * PatientWeight / (8780 + 244 * bodyMassIndex); | ||
} else if (PatientSex === 'M') { | ||
LBM = 9270 * PatientWeight / (6680 + 216 * bodyMassIndex); | ||
} else { | ||
throw new Error(`PatientSex is an invalid value: ${PatientSex}`); | ||
} | ||
return LBM * 1000; // convert in gr | ||
} | ||
function calculateSUVbsaScalingFactor(inputs) { | ||
@@ -502,5 +529,6 @@ const { | ||
throw new Error('The set of instances does not appear to come from one Series. Every instance must have identical values for series-level metadata properties'); | ||
} | ||
} // Treat null, undefined and zero as a missing PatientWeight. | ||
if (PatientWeight === null || PatientWeight === undefined) { | ||
if (!PatientWeight) { | ||
throw new Error('PatientWeight value is missing. It is not possible to calculate the SUV factors'); | ||
@@ -568,2 +596,3 @@ } | ||
let suvlbmFactor; | ||
let suvlbmJenmaFactor; | ||
@@ -581,2 +610,3 @@ if (PatientSize === null || PatientSize === undefined) { | ||
suvlbmFactor = calculateSUVlbmScalingFactor(suvlbmInputs); | ||
suvlbmJenmaFactor = calculateSUVlbmJanmahasatianScalingFactor(suvlbmInputs); | ||
} | ||
@@ -597,2 +627,6 @@ | ||
factors.suvlbm = decayCorrectionArray[index] * suvlbmFactor; | ||
} | ||
if (suvlbmJenmaFactor) { | ||
factors.suvlbmJanma = decayCorrectionArray[index] * suvlbmJenmaFactor; | ||
} // factor formulaes taken from: | ||
@@ -599,0 +633,0 @@ // https://www.medicalconnections.co.uk/kb/calculating-suv-from-pet-images/ |
@@ -1,2 +0,2 @@ | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});class e{constructor(e){this.fullDate=e}getTimeInSec(){const e=this.fullDate.substring(0,10),t=this.fullDate.substring(11,28),i=parseInt(e.substring(0,4),10),r=e.length>=7?parseInt(e.substring(5,7),10):void 0,n=e.length>=10?parseInt(e.substring(8,10),10):void 0;if(isNaN(i)||void 0!==r&&isNaN(r)||void 0!==n&&isNaN(n)||i>3e3||r&&(r<1||r>12)||n&&(n<1||n>31))throw new Error(`invalid date '${e}'`);const a=new Date(e+"T00:00:00.000000Z"),o=parseInt(t.substring(0,2),10),s=t.length>=5?parseInt(t.substring(3,5),10):void 0,l=t.length>=8?parseInt(t.substring(6,8),10):void 0,c=t.substring(9,15),u=c?parseInt(c,10)*Math.pow(10,-c.length):void 0;if(isNaN(o)||void 0!==s&&isNaN(s)||void 0!==l&&isNaN(l)||void 0!==u&&isNaN(u)||o<0||o>23||s&&(s<0||s>59)||l&&(l<0||l>59)||u&&(u<0||u>999999))throw new Error(`invalid time '${t}'`);let d=a.getTime()/1e3;return d+=3600*o,void 0!==s&&(d+=60*s),void 0!==l&&(d+=l),void 0!==u&&(d+=u),d}getTimeInMicroSec(){return 1e6*this.getTimeInSec()}}function t(t,i){const r=(""+(i.hours||"00")).padStart(2,"0"),n=(""+(i.minutes||"00")).padStart(2,"0"),a=(""+(i.seconds||"00")).padStart(2,"0"),o=(""+t.month).padStart(2,"0"),s=(""+t.day).padStart(2,"0"),l=(""+(i.fractionalSeconds||"000000")).padEnd(6,"0");return new e(`${t.year}-${o}-${s}T${r}:${n}:${a}.${l}Z`)}function i(e){if(null==e||8!==e.length||"string"!=typeof e)throw new Error(`invalid DA '${e}'`);const t=parseInt(e.substring(0,4),10),i=parseInt(e.substring(4,6),10),r=parseInt(e.substring(6,8),10);if(1!=(n=r,a=i,o=t,!isNaN(o)&&a>0&&a<=12&&n>0&&n<=function(e,t){switch(e){case 2:return t%4==0&&t%100||t%400==0?29:28;case 9:case 4:case 6:case 11:return 30;default:return 31}}(a,o)))throw new Error(`invalid DA '${e}'`);var n,a,o;return{year:t,month:i,day:r}}function r(e){if(null==e||e.length<2||"string"!=typeof e)throw new Error(`invalid TM '${e}'`);const t=parseInt(e.substring(0,2),10),i=e.length>=4?parseInt(e.substring(2,4),10):void 0,r=e.length>=6?parseInt(e.substring(4,6),10):void 0,n=e.length>=8?e.substring(7,13):void 0,a=n?parseInt(n,10)*Math.pow(10,6-n.length):void 0;if(isNaN(t)||void 0!==i&&isNaN(i)||void 0!==r&&isNaN(r)||void 0!==a&&isNaN(a)||t<0||t>23||i&&(i<0||i>59)||r&&(r<0||r>59)||a&&(a<0||a>999999))throw new Error(`invalid TM '${e}'`);return{hours:t,minutes:i,seconds:r,fractionalSeconds:a}}function n(e){if(null==e)throw new Error("dateTimeToFullDateInterface : dateTime not defined.");return t(i(e.substring(0,8)),r(e.substring(8)))}exports.calculateSUVScalingFactors=function(a){const{CorrectedImage:o,Units:s,PhilipsPETPrivateGroup:l,PatientWeight:c,PatientSex:u,PatientSize:d}=a[0];if(!o.includes("ATTN")||!o.includes("DECY"))throw new Error('CorrectedImage must contain "ATTN" and "DECY": '+o);if(!a.every(e=>{return e.Units===s&&((t=e.CorrectedImage)===(i=o)||Array.isArray(t)&&Array.isArray(i)&&t.length===i.length&&t.every((e,t)=>e===i[t]))&&e.PatientWeight===c&&e.PatientSex===u&&e.PatientSize===d&&e.RadionuclideHalfLife===a[0].RadionuclideHalfLife&&e.RadionuclideTotalDose===a[0].RadionuclideTotalDose&&e.DecayCorrection===a[0].DecayCorrection&&e.SeriesDate===a[0].SeriesDate&&e.SeriesTime===a[0].SeriesTime;var t,i}))throw new Error("The set of instances does not appear to come from one Series. Every instance must have identical values for series-level metadata properties");if(null==c)throw new Error("PatientWeight value is missing. It is not possible to calculate the SUV factors");let v=new Array(a.length);v=function(a){const{RadionuclideTotalDose:o,RadionuclideHalfLife:s,RadiopharmaceuticalStartDateTime:l,RadiopharmaceuticalStartTime:c,SeriesDate:u}=a[0];if(null==o)throw new Error("calculateDecayCorrection : RadionuclideTotalDose value not found.");if(null==s)throw new Error("calculateDecayCorrection : RadionuclideHalfLife value not found.");const d=function(a){const{SeriesDate:o,SeriesTime:s,GEPrivatePostInjectionDateTime:l}=a[0],c=new Array(a.length),u=t(i(o),r(s));let d=new e("3000-01-01T00:00:00.000000Z"),v=d.getTimeInSec();if(a.forEach(e=>{const{AcquisitionDate:n,AcquisitionTime:a}=e,o=t(i(n),r(a));d=d.getTimeInSec()>=v||o.getTimeInSec()<d.getTimeInSec()?o:d}),d.getTimeInSec()>=v)throw new Error("Earliest acquisition time or date could not be parsed.");return u.getTimeInSec()<=d.getTimeInSec()?c.fill(u):c.fill(l?n(l):d)}(a),v=function(e){const{RadiopharmaceuticalStartDateTime:a,RadiopharmaceuticalStartTime:o,SeriesDate:s}=e;let l,c;if(a)return n(a);if(o&&s)return l=r(o),c=i(s),t(c,l);throw new Error("Invalid input: "+e)}({RadiopharmaceuticalStartDateTime:l,RadiopharmaceuticalStartTime:c,SeriesDate:u});return a.map((e,t)=>{const i=d[t].getTimeInSec()-v.getTimeInSec();if(i<0)throw new Error("Decay time cannot be less than zero");return 1/(o*Math.pow(2,-i/s))})}(a);let h=new Array(a.length);const p=1e3*c;if("BQML"===s)h=v.map((function(e){return e*p}));else if("CNTS"===s){const e=a.every(e=>{var t,i,r;return e.PhilipsPETPrivateGroup&&null!==(null===(t=e.PhilipsPETPrivateGroup)||void 0===t?void 0:t.SUVScaleFactor)&&void 0!==(null===(i=e.PhilipsPETPrivateGroup)||void 0===i?void 0:i.SUVScaleFactor)&&0!==(null===(r=e.PhilipsPETPrivateGroup)||void 0===r?void 0:r.SUVScaleFactor)}),t=a.every(e=>{var t,i,r;return e.PhilipsPETPrivateGroup&&!(null!==(t=e.PhilipsPETPrivateGroup)&&void 0!==t&&t.SUVScaleFactor)&&void 0!==(null===(i=e.PhilipsPETPrivateGroup)||void 0===i?void 0:i.ActivityConcentrationScaleFactor)&&0!==(null===(r=e.PhilipsPETPrivateGroup)||void 0===r?void 0:r.ActivityConcentrationScaleFactor)});if(e)h=a.map(e=>e.PhilipsPETPrivateGroup.SUVScaleFactor);else{if(!t)throw new Error("Units are in CNTS, but PhilipsPETPrivateGroup has invalid values: "+JSON.stringify(l));h=a.map((e,t)=>e.PhilipsPETPrivateGroup.ActivityConcentrationScaleFactor*v[t]*p)}}else{if("GML"!==s)throw new Error("Units has an invalid value: "+s);h.fill(1)}let S,f;return null==d?console.warn("PatientSize value is missing. It is not possible to calculate the SUV bsa factors"):S=function(e){const{PatientWeight:t,PatientSize:i}=e;return Math.pow(t,.425)*Math.pow(100*i,.725)*71.84}({PatientWeight:c,PatientSize:d}),null==d?console.warn("PatientSize value is missing. It is not possible to calculate the SUV lbm factors"):null==u?console.warn("PatientSex value is missing. It is not possible to calculate the SUV lbm factors"):f=function(e){const{PatientSex:t,PatientWeight:i,PatientSize:r}=e;let n;const a=i*i/(r*r*1e4);if("F"===t)n=1.07*i-148*a;else{if("M"!==t)throw new Error("PatientSex is an invalid value: "+t);n=1.1*i-120*a}return 1e3*n}({PatientWeight:c,PatientSex:u,PatientSize:d}),h.map((function(e,t){const i={suvbw:e};return S&&(i.suvbsa=v[t]*S),f&&(i.suvlbm=v[t]*f),i}))}; | ||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});class e{constructor(e){this.fullDate=e}getTimeInSec(){const e=this.fullDate.substring(0,10),t=this.fullDate.substring(11,28),i=parseInt(e.substring(0,4),10),n=e.length>=7?parseInt(e.substring(5,7),10):void 0,r=e.length>=10?parseInt(e.substring(8,10),10):void 0;if(isNaN(i)||void 0!==n&&isNaN(n)||void 0!==r&&isNaN(r)||i>3e3||n&&(n<1||n>12)||r&&(r<1||r>31))throw new Error(`invalid date '${e}'`);const a=new Date(e+"T00:00:00.000000Z"),o=parseInt(t.substring(0,2),10),s=t.length>=5?parseInt(t.substring(3,5),10):void 0,l=t.length>=8?parseInt(t.substring(6,8),10):void 0,c=t.substring(9,15),u=c?parseInt(c,10)*Math.pow(10,-c.length):void 0;if(isNaN(o)||void 0!==s&&isNaN(s)||void 0!==l&&isNaN(l)||void 0!==u&&isNaN(u)||o<0||o>23||s&&(s<0||s>59)||l&&(l<0||l>59)||u&&(u<0||u>999999))throw new Error(`invalid time '${t}'`);let d=a.getTime()/1e3;return d+=3600*o,void 0!==s&&(d+=60*s),void 0!==l&&(d+=l),void 0!==u&&(d+=u),d}getTimeInMicroSec(){return 1e6*this.getTimeInSec()}}function t(t,i){const n=(""+(i.hours||"00")).padStart(2,"0"),r=(""+(i.minutes||"00")).padStart(2,"0"),a=(""+(i.seconds||"00")).padStart(2,"0"),o=(""+t.month).padStart(2,"0"),s=(""+t.day).padStart(2,"0"),l=(""+(i.fractionalSeconds||"000000")).padEnd(6,"0");return new e(`${t.year}-${o}-${s}T${n}:${r}:${a}.${l}Z`)}function i(e){if(null==e||8!==e.length||"string"!=typeof e)throw new Error(`invalid DA '${e}'`);const t=parseInt(e.substring(0,4),10),i=parseInt(e.substring(4,6),10),n=parseInt(e.substring(6,8),10);if(1!=(r=n,a=i,o=t,!isNaN(o)&&a>0&&a<=12&&r>0&&r<=function(e,t){switch(e){case 2:return t%4==0&&t%100||t%400==0?29:28;case 9:case 4:case 6:case 11:return 30;default:return 31}}(a,o)))throw new Error(`invalid DA '${e}'`);var r,a,o;return{year:t,month:i,day:n}}function n(e){if(null==e||e.length<2||"string"!=typeof e)throw new Error(`invalid TM '${e}'`);const t=parseInt(e.substring(0,2),10),i=e.length>=4?parseInt(e.substring(2,4),10):void 0,n=e.length>=6?parseInt(e.substring(4,6),10):void 0,r=e.length>=8?e.substring(7,13):void 0,a=r?parseInt(r,10)*Math.pow(10,6-r.length):void 0;if(isNaN(t)||void 0!==i&&isNaN(i)||void 0!==n&&isNaN(n)||void 0!==a&&isNaN(a)||t<0||t>23||i&&(i<0||i>59)||n&&(n<0||n>59)||a&&(a<0||a>999999))throw new Error(`invalid TM '${e}'`);return{hours:t,minutes:i,seconds:n,fractionalSeconds:a}}function r(e){if(null==e)throw new Error("dateTimeToFullDateInterface : dateTime not defined.");return t(i(e.substring(0,8)),n(e.substring(8)))}exports.calculateSUVScalingFactors=function(a){const{CorrectedImage:o,Units:s,PhilipsPETPrivateGroup:l,PatientWeight:c,PatientSex:u,PatientSize:d}=a[0];if(!o.includes("ATTN")||!o.includes("DECY"))throw new Error('CorrectedImage must contain "ATTN" and "DECY": '+o);if(!a.every(e=>{return e.Units===s&&((t=e.CorrectedImage)===(i=o)||Array.isArray(t)&&Array.isArray(i)&&t.length===i.length&&t.every((e,t)=>e===i[t]))&&e.PatientWeight===c&&e.PatientSex===u&&e.PatientSize===d&&e.RadionuclideHalfLife===a[0].RadionuclideHalfLife&&e.RadionuclideTotalDose===a[0].RadionuclideTotalDose&&e.DecayCorrection===a[0].DecayCorrection&&e.SeriesDate===a[0].SeriesDate&&e.SeriesTime===a[0].SeriesTime;var t,i}))throw new Error("The set of instances does not appear to come from one Series. Every instance must have identical values for series-level metadata properties");if(!c)throw new Error("PatientWeight value is missing. It is not possible to calculate the SUV factors");let h=new Array(a.length);h=function(a){const{RadionuclideTotalDose:o,RadionuclideHalfLife:s,RadiopharmaceuticalStartDateTime:l,RadiopharmaceuticalStartTime:c,SeriesDate:u}=a[0];if(null==o)throw new Error("calculateDecayCorrection : RadionuclideTotalDose value not found.");if(null==s)throw new Error("calculateDecayCorrection : RadionuclideHalfLife value not found.");const d=function(a){const{SeriesDate:o,SeriesTime:s,GEPrivatePostInjectionDateTime:l}=a[0],c=new Array(a.length),u=t(i(o),n(s));let d=new e("3000-01-01T00:00:00.000000Z"),h=d.getTimeInSec();if(a.forEach(e=>{const{AcquisitionDate:r,AcquisitionTime:a}=e,o=t(i(r),n(a));d=d.getTimeInSec()>=h||o.getTimeInSec()<d.getTimeInSec()?o:d}),d.getTimeInSec()>=h)throw new Error("Earliest acquisition time or date could not be parsed.");return u.getTimeInSec()<=d.getTimeInSec()?c.fill(u):c.fill(l?r(l):d)}(a),h=function(e){const{RadiopharmaceuticalStartDateTime:a,RadiopharmaceuticalStartTime:o,SeriesDate:s}=e;let l,c;if(a)return r(a);if(o&&s)return l=n(o),c=i(s),t(c,l);throw new Error("Invalid input: "+e)}({RadiopharmaceuticalStartDateTime:l,RadiopharmaceuticalStartTime:c,SeriesDate:u});return a.map((e,t)=>{const i=d[t].getTimeInSec()-h.getTimeInSec();if(i<0)throw new Error("Decay time cannot be less than zero");return 1/(o*Math.pow(2,-i/s))})}(a);let v=new Array(a.length);const p=1e3*c;if("BQML"===s)v=h.map((function(e){return e*p}));else if("CNTS"===s){const e=a.every(e=>{var t,i,n;return e.PhilipsPETPrivateGroup&&null!==(null===(t=e.PhilipsPETPrivateGroup)||void 0===t?void 0:t.SUVScaleFactor)&&void 0!==(null===(i=e.PhilipsPETPrivateGroup)||void 0===i?void 0:i.SUVScaleFactor)&&0!==(null===(n=e.PhilipsPETPrivateGroup)||void 0===n?void 0:n.SUVScaleFactor)}),t=a.every(e=>{var t,i,n;return e.PhilipsPETPrivateGroup&&!(null!==(t=e.PhilipsPETPrivateGroup)&&void 0!==t&&t.SUVScaleFactor)&&void 0!==(null===(i=e.PhilipsPETPrivateGroup)||void 0===i?void 0:i.ActivityConcentrationScaleFactor)&&0!==(null===(n=e.PhilipsPETPrivateGroup)||void 0===n?void 0:n.ActivityConcentrationScaleFactor)});if(e)v=a.map(e=>e.PhilipsPETPrivateGroup.SUVScaleFactor);else{if(!t)throw new Error("Units are in CNTS, but PhilipsPETPrivateGroup has invalid values: "+JSON.stringify(l));v=a.map((e,t)=>e.PhilipsPETPrivateGroup.ActivityConcentrationScaleFactor*h[t]*p)}}else{if("GML"!==s)throw new Error("Units has an invalid value: "+s);v.fill(1)}let f,S,g;if(null==d?console.warn("PatientSize value is missing. It is not possible to calculate the SUV bsa factors"):f=function(e){const{PatientWeight:t,PatientSize:i}=e;return Math.pow(t,.425)*Math.pow(100*i,.725)*71.84}({PatientWeight:c,PatientSize:d}),null==d)console.warn("PatientSize value is missing. It is not possible to calculate the SUV lbm factors");else if(null==u)console.warn("PatientSex value is missing. It is not possible to calculate the SUV lbm factors");else{const e={PatientWeight:c,PatientSex:u,PatientSize:d};S=function(e){const{PatientSex:t,PatientWeight:i,PatientSize:n}=e;let r;const a=Math.pow(i/(100*n),2);if("F"===t)r=1.07*i-148*a;else{if("M"!==t)throw new Error("PatientSex is an invalid value: "+t);r=1.1*i-120*a}return 1e3*r}(e),g=function(e){const{PatientSex:t,PatientWeight:i,PatientSize:n}=e;let r;const a=i/Math.pow(n,2);if("F"===t)r=9270*i/(8780+244*a);else{if("M"!==t)throw new Error("PatientSex is an invalid value: "+t);r=9270*i/(6680+216*a)}return 1e3*r}(e)}return v.map((function(e,t){const i={suvbw:e};return f&&(i.suvbsa=h[t]*f),S&&(i.suvlbm=h[t]*S),g&&(i.suvlbmJanma=h[t]*g),i}))}; | ||
//# sourceMappingURL=calculate-suv.cjs.production.min.js.map |
@@ -349,9 +349,8 @@ /** | ||
let LBM; | ||
const bodyMassIndex = PatientWeight * PatientWeight / (PatientSize * PatientSize * 10000); // convert size in cm | ||
// reference: https://www.medicalconnections.co.uk/kb/calculating-suv-from-pet-images/ | ||
const weightSizeFactor = Math.pow(PatientWeight / (PatientSize * 100), 2); // reference: https://www.medicalconnections.co.uk/kb/calculating-suv-from-pet-images/ | ||
if (PatientSex === 'F') { | ||
LBM = 1.07 * PatientWeight - 148 * bodyMassIndex; | ||
LBM = 1.07 * PatientWeight - 148 * weightSizeFactor; | ||
} else if (PatientSex === 'M') { | ||
LBM = 1.1 * PatientWeight - 120 * bodyMassIndex; | ||
LBM = 1.1 * PatientWeight - 120 * weightSizeFactor; | ||
} else { | ||
@@ -363,3 +362,31 @@ throw new Error(`PatientSex is an invalid value: ${PatientSex}`); | ||
} | ||
/** | ||
* From https://link.springer.com/article/10.1007/s00259-014-2961-x | ||
* and https://link.springer.com/article/10.2165/00003088-200544100-00004 | ||
* and | ||
* @param inputs | ||
* @returns | ||
*/ | ||
function calculateSUVlbmJanmahasatianScalingFactor(inputs) { | ||
const { | ||
PatientSex, | ||
PatientWeight, | ||
PatientSize | ||
} = inputs; | ||
let LBM; | ||
const bodyMassIndex = PatientWeight / Math.pow(PatientSize, 2); | ||
if (PatientSex === 'F') { | ||
LBM = 9270 * PatientWeight / (8780 + 244 * bodyMassIndex); | ||
} else if (PatientSex === 'M') { | ||
LBM = 9270 * PatientWeight / (6680 + 216 * bodyMassIndex); | ||
} else { | ||
throw new Error(`PatientSex is an invalid value: ${PatientSex}`); | ||
} | ||
return LBM * 1000; // convert in gr | ||
} | ||
function calculateSUVbsaScalingFactor(inputs) { | ||
@@ -498,5 +525,6 @@ const { | ||
throw new Error('The set of instances does not appear to come from one Series. Every instance must have identical values for series-level metadata properties'); | ||
} | ||
} // Treat null, undefined and zero as a missing PatientWeight. | ||
if (PatientWeight === null || PatientWeight === undefined) { | ||
if (!PatientWeight) { | ||
throw new Error('PatientWeight value is missing. It is not possible to calculate the SUV factors'); | ||
@@ -564,2 +592,3 @@ } | ||
let suvlbmFactor; | ||
let suvlbmJenmaFactor; | ||
@@ -577,2 +606,3 @@ if (PatientSize === null || PatientSize === undefined) { | ||
suvlbmFactor = calculateSUVlbmScalingFactor(suvlbmInputs); | ||
suvlbmJenmaFactor = calculateSUVlbmJanmahasatianScalingFactor(suvlbmInputs); | ||
} | ||
@@ -593,2 +623,6 @@ | ||
factors.suvlbm = decayCorrectionArray[index] * suvlbmFactor; | ||
} | ||
if (suvlbmJenmaFactor) { | ||
factors.suvlbmJanma = decayCorrectionArray[index] * suvlbmJenmaFactor; | ||
} // factor formulaes taken from: | ||
@@ -595,0 +629,0 @@ // https://www.medicalconnections.co.uk/kb/calculating-suv-from-pet-images/ |
@@ -7,7 +7,7 @@ /** | ||
*/ | ||
export interface SUVbsaScalingFactorInput { | ||
interface SUVbsaScalingFactorInput { | ||
PatientSize: number; | ||
PatientWeight: number; | ||
} | ||
export default function calculateSUVbsaScalingFactor(inputs: SUVbsaScalingFactorInput): number; | ||
export { calculateSUVbsaScalingFactor }; | ||
declare function calculateSUVbsaScalingFactor(inputs: SUVbsaScalingFactorInput): number; | ||
export { calculateSUVbsaScalingFactor, SUVbsaScalingFactorInput }; |
@@ -7,3 +7,3 @@ /** | ||
*/ | ||
export interface SUVlbmScalingFactorInput { | ||
interface SUVlbmScalingFactorInput { | ||
PatientSize: number; | ||
@@ -13,3 +13,11 @@ PatientSex: string; | ||
} | ||
export default function calculateSUVlbmScalingFactor(inputs: SUVlbmScalingFactorInput): number; | ||
export { calculateSUVlbmScalingFactor }; | ||
declare function calculateSUVlbmScalingFactor(inputs: SUVlbmScalingFactorInput): number; | ||
/** | ||
* From https://link.springer.com/article/10.1007/s00259-014-2961-x | ||
* and https://link.springer.com/article/10.2165/00003088-200544100-00004 | ||
* and | ||
* @param inputs | ||
* @returns | ||
*/ | ||
declare function calculateSUVlbmJanmahasatianScalingFactor(inputs: SUVlbmScalingFactorInput): number; | ||
export { calculateSUVlbmScalingFactor, calculateSUVlbmJanmahasatianScalingFactor, SUVlbmScalingFactorInput, }; |
@@ -11,2 +11,3 @@ import { InstanceMetadata } from './types'; | ||
suvlbm?: number; | ||
suvlbmJanma?: number; | ||
suvbsa?: number; | ||
@@ -13,0 +14,0 @@ } |
{ | ||
"name": "@cornerstonejs/calculate-suv", | ||
"version": "1.0.3", | ||
"version": "1.1.0", | ||
"license": "MIT", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
@@ -7,3 +7,3 @@ /** | ||
*/ | ||
export interface SUVbsaScalingFactorInput { | ||
interface SUVbsaScalingFactorInput { | ||
PatientSize: number; | ||
@@ -13,3 +13,3 @@ PatientWeight: number; | ||
export default function calculateSUVbsaScalingFactor( | ||
function calculateSUVbsaScalingFactor( | ||
inputs: SUVbsaScalingFactorInput | ||
@@ -25,2 +25,2 @@ ): number { | ||
export { calculateSUVbsaScalingFactor }; | ||
export { calculateSUVbsaScalingFactor, SUVbsaScalingFactorInput }; |
@@ -7,3 +7,3 @@ /** | ||
*/ | ||
export interface SUVlbmScalingFactorInput { | ||
interface SUVlbmScalingFactorInput { | ||
PatientSize: number; // m | ||
@@ -14,3 +14,3 @@ PatientSex: string; //'M' | 'F' | 'O'; | ||
export default function calculateSUVlbmScalingFactor( | ||
function calculateSUVlbmScalingFactor( | ||
inputs: SUVlbmScalingFactorInput | ||
@@ -21,9 +21,8 @@ ): number { | ||
let LBM; | ||
const bodyMassIndex = | ||
(PatientWeight * PatientWeight) / (PatientSize * PatientSize * 10000); // convert size in cm | ||
const weightSizeFactor = Math.pow(PatientWeight / (PatientSize * 100), 2); | ||
// reference: https://www.medicalconnections.co.uk/kb/calculating-suv-from-pet-images/ | ||
if (PatientSex === 'F') { | ||
LBM = 1.07 * PatientWeight - 148 * bodyMassIndex; | ||
LBM = 1.07 * PatientWeight - 148 * weightSizeFactor; | ||
} else if (PatientSex === 'M') { | ||
LBM = 1.1 * PatientWeight - 120 * bodyMassIndex; | ||
LBM = 1.1 * PatientWeight - 120 * weightSizeFactor; | ||
} else { | ||
@@ -36,2 +35,31 @@ throw new Error(`PatientSex is an invalid value: ${PatientSex}`); | ||
export { calculateSUVlbmScalingFactor }; | ||
/** | ||
* From https://link.springer.com/article/10.1007/s00259-014-2961-x | ||
* and https://link.springer.com/article/10.2165/00003088-200544100-00004 | ||
* and | ||
* @param inputs | ||
* @returns | ||
*/ | ||
function calculateSUVlbmJanmahasatianScalingFactor( | ||
inputs: SUVlbmScalingFactorInput | ||
): number { | ||
const { PatientSex, PatientWeight, PatientSize } = inputs; | ||
let LBM; | ||
const bodyMassIndex = PatientWeight / Math.pow(PatientSize, 2); | ||
if (PatientSex === 'F') { | ||
LBM = (9270 * PatientWeight) / (8780 + 244 * bodyMassIndex); | ||
} else if (PatientSex === 'M') { | ||
LBM = (9270 * PatientWeight) / (6680 + 216 * bodyMassIndex); | ||
} else { | ||
throw new Error(`PatientSex is an invalid value: ${PatientSex}`); | ||
} | ||
return LBM * 1000; // convert in gr | ||
} | ||
export { | ||
calculateSUVlbmScalingFactor, | ||
calculateSUVlbmJanmahasatianScalingFactor, | ||
SUVlbmScalingFactorInput, | ||
}; |
import { FullDateInterface } from './combineDateTime'; | ||
import { calculateScanTimes } from './calculateScanTimes'; | ||
import calculateSUVlbmScalingFactor from './calculateSUVlbmScalingFactor'; | ||
import { SUVlbmScalingFactorInput } from './calculateSUVlbmScalingFactor'; | ||
import calculateSUVbsaScalingFactor from './calculateSUVbsaScalingFactor'; | ||
import { SUVbsaScalingFactorInput } from './calculateSUVbsaScalingFactor'; | ||
import { | ||
calculateSUVlbmJanmahasatianScalingFactor, | ||
calculateSUVlbmScalingFactor, | ||
SUVlbmScalingFactorInput, | ||
} from './calculateSUVlbmScalingFactor'; | ||
import { | ||
calculateSUVbsaScalingFactor, | ||
SUVbsaScalingFactorInput, | ||
} from './calculateSUVbsaScalingFactor'; | ||
import { calculateStartTime } from './calculateStartTime'; | ||
@@ -19,2 +24,3 @@ import { InstanceMetadata } from './types'; | ||
suvlbm?: number; | ||
suvlbmJanma?: number; | ||
suvbsa?: number; | ||
@@ -145,3 +151,4 @@ } | ||
if (PatientWeight === null || PatientWeight === undefined) { | ||
// Treat null, undefined and zero as a missing PatientWeight. | ||
if (!PatientWeight) { | ||
throw new Error( | ||
@@ -237,2 +244,3 @@ 'PatientWeight value is missing. It is not possible to calculate the SUV factors' | ||
let suvlbmFactor: number | undefined; | ||
let suvlbmJenmaFactor: number | undefined; | ||
if (PatientSize === null || PatientSize === undefined) { | ||
@@ -254,2 +262,3 @@ console.warn( | ||
suvlbmFactor = calculateSUVlbmScalingFactor(suvlbmInputs); | ||
suvlbmJenmaFactor = calculateSUVlbmJanmahasatianScalingFactor(suvlbmInputs); | ||
} | ||
@@ -272,2 +281,6 @@ | ||
if (suvlbmJenmaFactor) { | ||
factors.suvlbmJanma = decayCorrectionArray[index] * suvlbmJenmaFactor; | ||
} | ||
// factor formulaes taken from: | ||
@@ -274,0 +287,0 @@ // https://www.medicalconnections.co.uk/kb/calculating-suv-from-pet-images/ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
218872
2243
1