Difference between revisions of "MediaWiki:Gadget-calculator-anatomyPhysiology.js"

From WikiAnesthesia
 
(74 intermediate revisions by the same user not shown)
Line 1: Line 1:
( function() {
( function() {
     var moduleId = 'patientStats';
     mw.calculators.addUnitsBases( {
        bpm: {
            toString: function( units ) {
                units = units.replace( 'bpm', 'beats/min' );


    mw.calculators.addUnitsBases( {
                return units;
            }
        },
         hgb: {
         hgb: {
             toString: function( units ) {
             toString: function( units ) {
                 units = units.replace( 'hgbperdL', '/dL' );
                 units = units.replace( 'hgbperdL', '/dL' );
                 units = units.replace( 'pcthct', '%' );
                 units = units.replace( /\s?pcthct/, '%' );
 
                return units;
            }
        },
        o2: {
            toString: function( units ) {
                units = units.replace( /\s?pcto2/, '%' );
 
                return units;
            }
        },
        temperature: {
            toString: function( units ) {
                units = units.replace( 'deg', '°' );


                 return units;
                 return units;
Line 14: Line 33:


     mw.calculators.addUnits( {
     mw.calculators.addUnits( {
        bpm: {
            baseName: 'bpm'
        },
         pcthct: {
         pcthct: {
             baseName: 'hgb',
             baseName: 'hgb'
             digits: 0
        },
        pcto2: {
             baseName: 'o2'
         },
         },
         ghgbperdL: {
         ghgbperdL: {
             baseName: 'hgb',
             baseName: 'hgb',
            digits: 1,
             prefixes: 'short',
             prefixes: 'short',
             definition: '3 pcthct'
             definition: '3 pcthct'
Line 27: Line 50:


     mw.calculators.addVariables( {
     mw.calculators.addVariables( {
         caseDuration: {
         fiO2: {
             name: 'Case duration',
             name: 'FiO<sub>2</sub>',
             type: 'number',
             type: 'number',
             abbreviation: 'Duration',
             abbreviation: 'FiO<sub>2</sub>',
            minValue: '10 pcto2',
            maxValue: '100 pcto2',
            defaultValue: '21 pcto2',
             maxLength: 3,
             maxLength: 3,
             units: [
             units: [
                 'hr',
                 'pcto2'
                'min'
             ]
             ]
         },
         },
         hct: {
         heartRate: {
             name: 'Current hematocrit',
             name: 'Heart rate',
             type: 'number',
             type: 'number',
             abbreviation: 'Current hct',
             abbreviation: 'HR',
             defaultValue: '45 pcthct',
             defaultValue: '60 bpm',
            maxLength: 4,
            units: [
                'bpm'
            ]
        },
        hgb: {
            name: 'Hemoglobin/hematocrit',
            type: 'number',
            abbreviation: 'HgB',
            minValue: '3 ghgbperdL',
            maxValue: '25 ghgbperdL',
            defaultValue: '13 ghgbperdL',
             maxLength: 4,
             maxLength: 4,
             units: [
             units: [
Line 48: Line 85:
             ]
             ]
         },
         },
         minHct: {
         paCO2: {
             name: 'Minimum hematocrit',
             name: 'PaCO<sub>2</sub>',
             type: 'number',
             type: 'number',
             abbreviation: 'Min hct',
             abbreviation: 'PaCO<sub>2</sub>',
             defaultValue: '21 pcthct',
            minValue: '20 mmHg',
            defaultValue: '40 mmHg',
            maxLength: 3,
            units: [
                'mmHg'
            ]
        },
        paO2: {
            name: 'PaO<sub>2</sub>',
            type: 'number',
            abbreviation: 'PaO<sub>2</sub>',
            minValue: '25 mmHg',
            defaultValue: '100 mmHg',
            maxLength: 3,
            units: [
                'mmHg'
            ]
        },
        pAtm: {
            name: 'Atmospheric pressure',
            type: 'number',
            abbreviation: 'P<sub>atm</sub>',
            minValue: '0 mmHg',
             defaultValue: '760 mmHg',
             maxLength: 4,
             maxLength: 4,
             units: [
             units: [
                 'pcthct',
                 'mmHg'
                 'ghgbperdL'
            ]
        },
        saO2: {
            name: 'SaO<sub>2</sub>',
            type: 'number',
            abbreviation: 'SaO<sub>2</sub>',
            minValue: '25 pcto2',
            maxValue: '100 pcto2',
            defaultValue: '100 pcto2',
            maxLength: 3,
            units: [
                'pcto2'
            ]
        },
        smvO2: {
            name: 'SmvO<sub>2</sub>',
            type: 'number',
            abbreviation: 'SmvO<sub>2</sub>',
            minValue: '25 pcto2',
            maxValue: '100 pcto2',
            defaultValue: '75 pcto2',
            maxLength: 3,
            units: [
                'pcto2'
            ]
        },
        raceSpirometry: {
            name: 'Race',
            type: 'string',
            abbreviation: 'Race',
            defaultValue: 'unknown',
            options: {
                unknown: 'Unknown',
                black: 'Black',
                caucasian: 'Caucasian',
                mexican: 'Mexican-American'
            }
        },
        temperature: {
            name: 'Temperature',
            type: 'number',
            abbreviation: 'Temp',
            minValue: '20 degC',
            maxValue: '44 degC',
            defaultValue: '37 degC',
            maxLength: 5,
            units: [
                'degC',
                 'degF'
             ]
             ]
         },
         },
         npoTime: {
         weightBasedTidalVolumePerKgMin: {
             name: 'Time spent NPO',
             name: 'Minimum tidal volume',
             type: 'number',
             type: 'number',
             abbreviation: 'NPO time',
             abbreviation: 'Min TV',
             defaultValue: '8 hr',
            minValue: '3 mL/kgwt',
            maxValue: '12 mL/kgwt',
             defaultValue: '6 mL/kgwt',
             maxLength: 2,
             maxLength: 2,
             units: [
             units: [
                 'hr'
                 'mL/kgwt'
             ]
             ]
         },
         },
         surgicalTrauma: {
         weightBasedTidalVolumePerKgMax: {
             name: 'Severity of surgical trauma',
             name: 'Maximum tidal volume',
             type: 'string',
             type: 'number',
             abbreviation: 'Surgical trauma',
             abbreviation: 'Max TV',
             defaultValue: 'Minimal',
             minValue: '3 mL/kgwt',
             options: [
             maxValue: '12 mL/kgwt',
                'Minimal',
            defaultValue: '8 mL/kgwt',
                'Moderate',
            maxLength: 2,
                 'Severe'
            units: [
                 'mL/kgwt'
             ]
             ]
         }
         }
     } );
     } );


 
    // Force re-render of ibw and lbw. This is necessary to remove the additional inputs for patient variables from the
    // calculation which are now provided by the patient input toolbar.
    mw.calculators.calculations.ibw.render();
    mw.calculators.calculations.lbw.render();


     mw.calculators.addCalculations( {
     mw.calculators.addCalculations( {
         bladeMacSize: {
         bmi: {
             name: 'Laryngoscope blade size (MAC)',
             name: 'Body mass index',
             abbreviation: 'Blade (MAC)',
             abbreviation: 'BMI',
             data: {
             data: {
                 variables: {
                 variables: {
                     required: [ 'age' ]
                     required: [ 'weight', 'height' ]
                 }
                 }
             },
             },
             type: 'string',
             digits: 0,
             references: [
            units: 'kg/m^2',
                'Smith\'s Anesthesia for Infants and Children. 8e. p356'
             formula: '<math>\\mathrm{BMI} = \\frac{\\mathrm{mass_{kg}}}{{(\\mathrm{height_{m}}})^2}</math>',
             ],
            link: '[[Body mass index]]',
             references: [],
             calculate: function( data ) {
             calculate: function( data ) {
                 var age = data.age.toNumber( 'yo' );
                 return data.weight.toNumber( 'kgwt' ) / Math.pow( data.height.toNumber( 'm' ), 2 );
 
                if( age >= 6 ) {
                    return '3';
                } else if( age >= 1 ) {
                    // ( age + 16 ) / 4
                    // To nicely display in increments of 0.5, double the calculation, round (floor), then divide by 2
                    return '2';
                } else {
                    return '-';
                }
             }
             }
         },
         },
         bladeMillerSize: {
         bsa: {
             name: 'Laryngoscope blade size (Miller)',
             name: 'Body surface area',
             abbreviation: 'Blade (Miller)',
             abbreviation: 'BSA',
             data: {
             data: {
                 variables: {
                 variables: {
                     required: [ 'age' ]
                     required: [ 'weight', 'height' ]
                 }
                 }
             },
             },
             type: 'string',
             digits: 2,
            units: 'm^2',
            formula: '<math>\\mathrm{BSA} = \\sqrt{\\frac{\\mathrm{weight_{kg}}*\\mathrm{height_{cm}}}{3600}}</math>',
            link: false,
             references: [
             references: [
                 'Smith\'s Anesthesia for Infants and Children. 8e. p356'
                 'Mosteller RD. Simplified calculation of body-surface area. N Engl J Med. 1987 Oct 22;317(17):1098. doi: 10.1056/NEJM198710223171717. PMID: 3657876.'
             ],
             ],
             calculate: function( data ) {
             calculate: function( data ) {
                 var age = data.age.toNumber( 'yo' );
                 return Math.sqrt( data.height.toNumber( 'cm' ) * data.weight.toNumber( 'kgwt' ) / 3600 );
 
                if( age >= 2 ) {
                    return '2';
                } else if( age >= 1 / 12 ) {
                    return '1';
                } else if( age >= 0 ) {
                    return '0-1';
                } else {
                    return '0';
                }
             }
             }
         },
         },
Line 181: Line 279:
                     systolicMin = 60;
                     systolicMin = 60;
                     systolicMax = 75;
                     systolicMax = 75;
                }
            }
        }
    } );
    // Cardiovascular
    mw.calculators.addCalculations( {
        vO2: {
            name: 'Rate of oxygen consumption (VO<sub>2</sub>)',
            abbreviation: 'VO<sub>2</sub>',
            data: {
                calculations: {
                    required: [ 'bsa' ]
                },
                variables: {
                    optional: [ 'age' ]
                }
            },
            units: 'mL/min',
            formula: '<math>\\mathrm{VO_2} = \\begin{cases} 125 * \\mathrm{BSA}  & \\text{if age} < 70 \\\\ 110 * \\mathrm{BSA} & \\text{if age} \\geq 70 \\end{cases}</math>',
            references: [],
            calculate: function( data ) {
                var bsa = data.bsa.toNumber();
                var age = data.age ? data.age.toNumber( 'yr' ) : null;
                if( age < 70 ) {
                    return 125 * bsa;
                } else {
                    return 110 * bsa;
                 }
                 }
             }
             }
         },
         },
         bmi: {
         cardiacOutputFick: {
             name: 'Body mass index',
             name: 'Cardiac output (Fick)',
             abbreviation: 'BMI',
             abbreviation: 'CO (Fick)',
             data: {
             data: {
                 variables: {
                 variables: {
                     required: [ 'weight', 'height' ]
                     required: [ 'saO2', 'smvO2', 'hgb' ]
                },
                calculations: {
                    required: [ 'vO2' ]
                }
            },
            units: 'L/min',
            formula: '<math>\\mathrm{CO_{Fick}}=\\frac{\\mathrm{VO_2}}{(\\mathrm{S_aO_2} - \\mathrm{S_{mv}O_2}) * H_b * 13.4}</math>',
            link: false,
            references: [],
            calculate: function( data ) {
                var vO2 = data.vO2.toNumber( 'mL/min' );
                var saO2 = data.saO2.toNumber() / 100;
                var smvO2 = data.smvO2.toNumber() / 100;
                var hgb = data.hgb.toNumber( 'ghgbperdL' );
 
                return vO2 / ( ( saO2 - smvO2 ) * hgb * 13.4 );
            }
        },
        cardiacIndex: {
            name: 'Cardiac index',
            abbreviation: 'CI',
            data: {
                calculations: {
                    required: [ 'bsa', 'cardiacOutputFick' ]
                 }
                 }
             },
             },
            digits: 0,
             units: 'L/min/m^2',
             units: 'kg/m^2',
             formula: '<math>\\mathrm{CI}=\\frac{\\mathrm{CO}}{\\mathrm{BSA}}</math>',
             formula: '<math>\\mathrm{BMI} = \\frac{\\mathrm{mass_{kg}}}{{\\mathrm{height_{m}}}^2}</math>',
             link: false,
             link: '[[Body mass index]]',
             references: [],
             references: [],
             calculate: function( data ) {
             calculate: function( data ) {
                 return data.weight.toNumber( 'kgwt' ) / Math.pow( data.height.toNumber( 'm' ), 2 );
                 var cardiacOutput = data.cardiacOutputFick.toNumber( 'L/min' );
                var bsa = data.bsa.toNumber( 'm^2' );
 
                return cardiacOutput / bsa;
             }
             }
         },
         },
         bsa: {
         strokeVolume: {
             name: 'Body surface area',
             name: 'Stroke volume',
             abbreviation: 'BSA',
             abbreviation: 'SV',
             data: {
             data: {
                 variables: {
                 variables: {
                     required: [ 'weight', 'height' ]
                     required: [ 'heartRate' ]
                },
                calculations: {
                    required: [ 'cardiacOutputFick' ]
                 }
                 }
             },
             },
            digits: 2,
             units: 'mL',
             units: 'm^2',
             formula: '<math>\\mathrm{SV}=\\frac{\\mathrm{CO}}{\\mathrm{HR}}</math>',
             formula: '<math>\\mathrm{BSA} = \\sqrt{\\frac{\\mathrm{weight_{kg}}*\\mathrm{height_{cm}}}{3600}}</math>',
             link: false,
             link: false,
             references: [
             references: [],
                'Mosteller RD. Simplified calculation of body-surface area. N Engl J Med. 1987 Oct 22;317(17):1098. doi: 10.1056/NEJM198710223171717. PMID: 3657876.'
            ],
             calculate: function( data ) {
             calculate: function( data ) {
                 return Math.sqrt( data.height.toNumber( 'cm' ) * data.weight.toNumber( 'kgwt' ) / 3600 );
                 var cardiacOutput = data.cardiacOutputFick.toNumber( 'mL/min' );
                var heartRate = data.heartRate.toNumber();
 
                return cardiacOutput / heartRate;
             }
             }
         },
         }
         ebv: {
    } );
             name: 'Estimated blood volume',
 
            abbreviation: 'EBV',
    // Neuro
    mw.calculators.addCalculations( {
         brainMass: {
             name: 'Brain mass',
             data: {
             data: {
                 variables: {
                 variables: {
                     required: [ 'weight', 'age' ]
                     optional: [ 'age', 'gender' ]
                 }
                 }
             },
             },
             digits: 0,
             digits: 0,
             units: 'mL',
             units: 'gwt',
             formula: '',
             description: 'This calculation will give a more precise estimate of brain mass if age and/or gender are provided.',
             references: [
             references: [
                 'Morgan & Mikhail\'s Clinical Anesthesiology. 5e. p1168'
                 'Dekaban AS. Changes in brain weights during the span of human life: relation of brain weights to body heights and body weights. Ann Neurol. 1978 Oct;4(4):345-56. doi: 10.1002/ana.410040410. PMID: 727739.'
             ],
             ],
             calculate: function( data ) {
             calculate: function( data ) {
                 var weight = data.weight.toNumber( 'kgwt' );
                 var age = data.age ? data.age.toNumber( 'yr' ) : null;
                 var age = data.age.toNumber( 'yo' );
                 var gender = data.gender ? data.gender : null;
 
                var brainMassFemale = 1290;
                var brainMassMale = 1450;


                 var ebvPerKg;
                 if( age !== null ) {
                    if( age <= 10 / 365 ) {
                        // <=10 days
                        brainMassFemale = 360;
                        brainMassMale = 380;
                    } else if( age <= 4 * 30 / 365 ) {
                        // Less than 4 months. This is a gap in the reported data of the paper, so linearly interpolate?
                        var ageFactor = 1 - ( 4 * 30 / 365 - age ) / ( 4 * 30 / 365 - 10 / 365 );


                if( age >= 1 ) {
                        brainMassFemale = 360 + ageFactor * ( 580 - 360 );
                     if( data.gender === 'F' ) {
                        brainMassMale = 380 + ageFactor * ( 640 - 380 );
                         ebvPerKg = 65;
                    } else if( age <= 8 * 30 / 365 ) {
                        // <=8 months
                        brainMassFemale = 580;
                        brainMassMale = 640;
                     } else if( age <= 18 * 30 / 365 ) {
                        // <=18 months
                        brainMassFemale = 940;
                        brainMassMale = 970;
                    } else if( age <= 30 * 30 / 365 ) {
                         // <=30 months
                        brainMassFemale = 1040;
                        brainMassMale = 1120;
                    } else if( age <= 43 * 30 / 365 ) {
                        // <=43 months
                        brainMassFemale = 1090;
                        brainMassMale = 1270;
                    } else if( age <= 5 ) {
                        brainMassFemale = 1150;
                        brainMassMale = 1300;
                    } else if( age <= 7 ) {
                        brainMassFemale = 1210;
                        brainMassMale = 1330;
                    } else if( age <= 9 ) {
                        brainMassFemale = 1180;
                        brainMassMale = 1370;
                    } else if( age <= 12 ) {
                        brainMassFemale = 1260;
                        brainMassMale = 1440;
                    } else if( age <= 15 ) {
                        brainMassFemale = 1280;
                        brainMassMale = 1410;
                    } else if( age <= 18 ) {
                        brainMassFemale = 1340;
                        brainMassMale = 1440;
                    } else if( age <= 21 ) {
                        brainMassFemale = 1310;
                        brainMassMale = 1450;
                    } else if( age <= 30 ) {
                        brainMassFemale = 1300;
                        brainMassMale = 1440;
                    } else if( age <= 40 ) {
                        brainMassFemale = 1290;
                        brainMassMale = 1440;
                    } else if( age <= 50 ) {
                        brainMassFemale = 1290;
                        brainMassMale = 1430;
                    } else if( age <= 55 ) {
                        brainMassFemale = 1280;
                        brainMassMale = 1410;
                    } else if( age <= 60 ) {
                        brainMassFemale = 1250;
                        brainMassMale = 1370;
                    } else if( age <= 65 ) {
                        brainMassFemale = 1240;
                        brainMassMale = 1370;
                    } else if( age <= 70 ) {
                        brainMassFemale = 1240;
                        brainMassMale = 1360;
                    } else if( age <= 75 ) {
                        brainMassFemale = 1230;
                        brainMassMale = 1350;
                    } else if( age <= 80 ) {
                        brainMassFemale = 1190;
                        brainMassMale = 1330;
                    } else if( age <= 85 ) {
                        brainMassFemale = 1170;
                        brainMassMale = 1310;
                     } else {
                     } else {
                         ebvPerKg = 75;
                         brainMassFemale = 1140;
                        brainMassMale = 1290;
                     }
                     }
                 } else if( age >= 1/12 ) {
                 }
                     ebvPerKg = 80;
 
                 } else if( age >= 0 ) {
                if( gender === 'F' ) {
                     ebvPerKg = 85;
                     return brainMassFemale;
                 } else if( gender === 'M' ) {
                     return brainMassMale;
                 } else {
                 } else {
                     ebvPerKg = 95;
                     return ( brainMassFemale + brainMassMale ) / 2;
                 }
                 }
                return weight * ebvPerKg;
             }
             }
         },
         },
         ettDepth: {
         cerebralBloodVolume: {
             name: 'Endotracheal tube depth',
             name: 'Cerebral blood volume',
             abbreviation: 'ETT depth',
             abbreviation: 'CBV',
             data: {
             data: {
                 variables: {
                 calculations: {
                     required: [ 'age' ]
                     required: [ 'brainMass' ]
                 }
                 }
             },
             },
             type: 'string',
             units: 'mL',
            description: '4 mL per 100g of brain mass',
             references: [
             references: [
                 'Smith\'s Anesthesia for Infants and Children. 8e. p356'
                 'Tameem A, Krovvidi H, Cerebral physiology, Continuing Education in Anaesthesia Critical Care & Pain, Volume 13, Issue 4, August 2013, Pages 113–118, https://doi.org/10.1093/bjaceaccp/mkt001'
             ],
             ],
             calculate: function( data ) {
             calculate: function( data ) {
                 var age = data.age.toNumber( 'yo' );
                 var brainMass = data.brainMass.toNumber( 'gwt' );
                var depth;
 
                if( age >= 12 ) {
                    depth = '20+';
                } else if( age >= 2 ) {
                    // ( age / 2 ) + 12
                    depth = Math.round( age / 2 + 12 );
                } else if( age >= 1 ) {
                    depth = 12;
                } else if( age >= 0.5 ) {
                    depth = 11;
                } else if( age >= 0 ) {
                    depth = 9;
                } else {
                    depth = '7-8';
                }


                 return depth + ' cm from teeth';
                 return 4 * brainMass / 100;
             }
             }
         },
         },
         ettSize: {
         cerebralMetabolicRateFactor: {
             name: 'Endotracheal tube size',
             name: 'Cerebral metabolic rate factor',
             abbreviation: 'ETT size',
             abbreviation: '%CMR',
             data: {
             data: {
                 variables: {
                 variables: {
                     required: [ 'age' ]
                     optional: [ 'temperature' ]
                 }
                 }
             },
             },
             type: 'string',
             description: '7% change in CMR for every 1 &deg;C change in temperature',
             references: [
             references: [
                 'Smith\'s Anesthesia for Infants and Children. 8e. p356'
                 'Tameem A, Krovvidi H, Cerebral physiology, Continuing Education in Anaesthesia Critical Care & Pain, Volume 13, Issue 4, August 2013, Pages 113–118, https://doi.org/10.1093/bjaceaccp/mkt001'
             ],
             ],
             calculate: function( data ) {
             calculate: function( data ) {
                 var age = data.age.toNumber( 'yo' );
                 var temperature = data.temperature ? data.temperature.toNumber( 'degC' ) : null;
                 var size;
 
                 var cerebralMetabolicRateFactor = 1;


                 if( age >= 12 ) {
                 if( temperature ) {
                     size = '6+';
                     cerebralMetabolicRateFactor += 0.07 * ( temperature - 37 );
                } else if( age >= 1 ) {
                    // ( age + 16 ) / 4
                    // To nicely display in increments of 0.5, double the calculation, round (floor), then divide by 2
                    size = String( Math.floor( 2 * ( ( age + 16 ) / 4 ) ) / 2 );
                } else if( age >= 0.5 ) {
                    size = '3.5-4';
                } else if( age >= 0 ) {
                    size = '3-3.5';
                } else {
                    size = '2.5-3';
                 }
                 }


                 return size + ' mm (ID)';
                 return cerebralMetabolicRateFactor;
             }
             }
         },
         },
         fluidMaintenanceRate: {
         cerebralMetabolicRateO2: {
             name: 'Fluid maintenance rate',
             name: 'Cerebral metabolic rate (O<sub>2</sub>)',
             abbreviation: 'Fluid maint.',
             abbreviation: 'CMRO<sub>2</sub>',
             data: {
             data: {
                calculations: {
                    required: [ 'brainMass', 'cerebralMetabolicRateFactor' ]
                },
                 variables: {
                 variables: {
                     required: [ 'weight' ]
                     optional: [ 'temperature' ]
                 }
                 }
             },
             },
            digits: 0,
             units: 'mL/min',
             units: 'mL/hr',
             description: '<ul><li>3 mL O<sub>2</sub>/min per 100g of brain mass</li><li>If temperature is provided, adjusts estimate using 7% change in CMR for every 1 &deg;C change in temperature</li></ul>',
             formula: '',
             references: [
             references: [
                 'Miller\'s Anesthesia 7e, section IV, pg. 1728'
                 'Tameem A, Krovvidi H, Cerebral physiology, Continuing Education in Anaesthesia Critical Care & Pain, Volume 13, Issue 4, August 2013, Pages 113–118, https://doi.org/10.1093/bjaceaccp/mkt001'
             ],
             ],
             calculate: function( data ) {
             calculate: function( data ) {
                 var weight = data.weight.toNumber( 'kgwt' );
                // Temperature is included as an optional variable to generate the input.
                // It is used by cerebralMetabolicRateFactor, which is an internal calculation not typically shown.
                 var brainMass = data.brainMass.toNumber( 'gwt' );
                var cerebralMetabolicRateFactor = data.cerebralMetabolicRateFactor.toNumber();


                 // Uses 4-2-1 rule
                 return cerebralMetabolicRateFactor * 3 * brainMass / 100;
                var maintenanceRate = 4 * Math.min( weight, 10 );
            }
 
        },
                 if( weight > 10 ) {
        cerebralMetabolicRateGlucose: {
                     maintenanceRate += 2 * Math.min( weight - 10, 10 );
            name: 'Cerebral metabolic rate (Glucose)',
            abbreviation: 'CMR<sub>glu</sub>',
            data: {
                 calculations: {
                     required: [ 'brainMass', 'cerebralMetabolicRateFactor' ]
                 }
                 }
            },
            units: 'mg/min',
            description: '<ul><li>5 mg glucose/min per 100g of brain mass</li><li>7% change in CMR for every 1 &deg;C change in temperature</li></ul>',
            references: [
                'Tameem A, Krovvidi H, Cerebral physiology, Continuing Education in Anaesthesia Critical Care & Pain, Volume 13, Issue 4, August 2013, Pages 113–118, https://doi.org/10.1093/bjaceaccp/mkt001'
            ],
            calculate: function( data ) {
                var brainMass = data.brainMass.toNumber( 'gwt' );
                var cerebralMetabolicRateFactor = data.cerebralMetabolicRateFactor.toNumber();


                if( weight > 20) {
                 return cerebralMetabolicRateFactor * 5 * brainMass / 100;
                    maintenanceRate += weight - 20;
                }
 
                 return maintenanceRate;
             }
             }
         },
         },
         intraopFluids: {
         cerebralBloodFlow: {
             name: 'Intraoperative fluid dosing',
             name: 'Cerebral blood flow',
             abbreviation: 'Intraop fluids',
             abbreviation: 'CBF',
             data: {
             data: {
                 calculations: {
                 calculations: {
                     required: [ 'fluidMaintenanceRate' ]
                     required: [ 'brainMass', 'cerebralMetabolicRateFactor' ]
                 },
                 },
                 variables: {
                 variables: {
                     required: [ 'weight', 'npoTime', 'surgicalTrauma' ]
                     optional: [ 'paCO2' ]
                 }
                 }
             },
             },
             type: 'string',
             units: 'mL/min',
            description: '<ul><li>50 mL/min per 100g of brain mass.</li><li>Every mmHg in PaCO2 changes CBF by 1.5 mL/min per 100g of brain mass.</li><li>Cerebral blood flow and cerebral metabolic rate are coupled. Factors that alter CMR (e.g. temperature) will proportionally alter CBF.</li>',
             references: [
             references: [
                 'Corcoran T, Rhodes JE, Clarke S, Myles PS, Ho KM. Perioperative fluid management strategies in major surgery: a stratified meta-analysis. Anesth Analg. 2012 Mar;114(3):640-51. doi: 10.1213/ANE.0b013e318240d6eb. Epub 2012 Jan 16. PMID: 22253274.'
                 'Tameem A, Krovvidi H, Cerebral physiology, Continuing Education in Anaesthesia Critical Care & Pain, Volume 13, Issue 4, August 2013, Pages 113–118, https://doi.org/10.1093/bjaceaccp/mkt001',
                'Brian JE Jr. Carbon dioxide and the cerebral circulation. Anesthesiology. 1998 May;88(5):1365-86. doi: 10.1097/00000542-199805000-00029. PMID: 9605698.'
             ],
             ],
             calculate: function( data ) {
             calculate: function( data ) {
                 var weight = data.weight.toNumber( 'kgwt' );
                 var brainMass = data.brainMass.toNumber( 'gwt' );
                 var maintenanceRate = data.fluidMaintenanceRate.toNumber( 'mL/hr' );
                 var cerebralMetabolicRateFactor = data.cerebralMetabolicRateFactor.toNumber();
                 var npoTime = data.npoTime.toNumber( 'hr' );
                 var paCO2 = data.paCO2.toNumber( 'mmHg' );
                var surgicalTrauma = data.surgicalTrauma;


                 var output = '';
                 var cerebralBloodFlow = cerebralMetabolicRateFactor * 50 * brainMass / 100;


                 var npoDeficit = npoTime * maintenanceRate;
                 if( paCO2 ) {
                    // CO2 reductions don't reduce CBF more than 50%
                    var minCerebralBloodFlow = cerebralBloodFlow / 2;


                var surgicalLossMin, surgicalLossMax;
                    cerebralBloodFlow += 1.5 * brainMass / 100 * ( paCO2 - 40 );


                if( surgicalTrauma === 'Minimal' ) {
                     cerebralBloodFlow = math.max( cerebralBloodFlow, minCerebralBloodFlow );
                     surgicalLossMin = 2 * weight;
                    surgicalLossMax = 4 * weight;
                } else if( surgicalTrauma === 'Moderate' ) {
                    surgicalLossMin = 4 * weight;
                    surgicalLossMax = 6 * weight;
                } else {
                    surgicalLossMin = 6 * weight;
                    surgicalLossMax = 8 * weight;
                 }
                 }


                 var firstHour = Math.round( npoDeficit / 2 ) + maintenanceRate;
                 return cerebralBloodFlow;
                var nextHoursMin = Math.round( npoDeficit / 4 ) + maintenanceRate + surgicalLossMin;
            }
                var nextHoursMax = Math.round( npoDeficit / 4 ) + maintenanceRate + surgicalLossMax;
        }
                var remainingHoursMin = maintenanceRate + surgicalLossMin;
    } );
                var remainingHoursMax = maintenanceRate + surgicalLossMax;


                output += 'NPO deficit: ' + Math.round( npoDeficit ) + ' mL<br/>';
                output += 'Surgical losses: ' + surgicalLossMin + '-' + surgicalLossMax + ' mL/hr<br/>';
                output += '1st hour: ' + firstHour + ' mL<br/>';
                output += '2nd hour: ' + nextHoursMin + '-' + nextHoursMax + ' mL<br/>';
                output += '3rd hour: ' + nextHoursMin + '-' + nextHoursMax + ' mL<br/>';
                output += '4+ hours: ' + remainingHoursMin + '-' + remainingHoursMax + ' mL<br/>';


                return output;
 
            }
    // Pulmonary
        },
    mw.calculators.addCalculations( {
         lmaSize: {
         paO2Predicted: {
             name: 'Laryngeal mask airway size',
             name: 'PaO<sub>2</sub> (predicted)',
             abbreviation: 'LMA size',
             abbreviation: 'PaO<sub>2</sub> pred.',
             data: {
             data: {
                 variables: {
                 variables: {
                     required: [ 'weight' ]
                     required: [ 'pAtm', 'fiO2', 'paCO2' ]
                 }
                 }
             },
             },
             type: 'string',
             units: 'mmHg',
            formula: '<math>P_{aO_2Predicted} = FiO_2*(P_{atm}-P_{H_{2}O})-\\frac{P_{aCO_2}}{R}</math>',
             references: [
             references: [
                 'Smith\'s Anesthesia for Infants and Children. 8e. p312'
                 'McFarlane MJ, Imperiale TF. Use of the alveolar-arterial oxygen gradient in the diagnosis of pulmonary embolism. Am J Med. 1994 Jan;96(1):57-62. doi: 10.1016/0002-9343(94)90116-3. PMID: 8304364.'
             ],
             ],
             calculate: function( data ) {
             calculate: function( data ) {
                 var weight = data.weight.toNumber( 'kgwt' );
                 var fiO2 = data.fiO2.toNumber( 'pcto2' ) / 100;
                 var size;
                 var pAtm = data.pAtm.toNumber( 'mmHg' );
 
                 var pH2O = 47; // mmHg
                if( weight > 100 ) {
                 var paCO2 = data.paCO2.toNumber( 'mmHg' );
                    size = '6';
                 var r = 0.8;
                } else if( weight > 70 ) {
                    size = '5';
                } else if( weight > 50 ) {
                    size = '4';
                 } else if( weight > 30 ) {
                    size = '3';
                 } else if( weight > 20 ) {
                    size = '2.5';
                } else if( weight > 10 ) {
                    size = '2';
                 } else if( weight > 5 ) {
                    size = '1.5';
                } else {
                    size = '1';
                }


                 return size;
                 return fiO2 * ( pAtm - pH2O ) - paCO2 / r;
             }
             }
         },
         },
         maxAbl: {
         aaGradientO2: {
             name: 'Maximum allowable blood loss',
             name: 'A-a O<sub>2</sub> gradient',
             abbreviation: 'Max ABL',
             abbreviation: 'A-a O<sub>2</sub>',
             data: {
             data: {
                 calculations: {
                 calculations: {
                     required: [ 'ebv' ]
                     required: [ 'paO2Predicted' ]
                 },
                 },
                 variables: {
                 variables: {
                     required: [ 'weight', 'age', 'hct', 'minHct' ]
                     required: [ 'paO2' ]
                 }
                 }
             },
             },
            digits: 0,
             units: 'mmHg',
             units: 'mL',
             formula: '<math>\\text{A-a gradient}_{\\mathrm{O}_2} = P_{aO_2Predicted}-P_{aO_2} </math>',
             formula: '',
             references: [
             references: [
                 'Morgan & Mikhail\'s Clinical Anesthesiology. 5e. p1168'
                 'McFarlane MJ, Imperiale TF. Use of the alveolar-arterial oxygen gradient in the diagnosis of pulmonary embolism. Am J Med. 1994 Jan;96(1):57-62. doi: 10.1016/0002-9343(94)90116-3. PMID: 8304364.'
             ],
             ],
             calculate: function( data ) {
             calculate: function( data ) {
                 var currentHct = data.hct.toNumber( 'pcthct' );
                 var paO2Predicted = data.paO2Predicted.toNumber( 'mmHg' );
                 var minHct = data.minHct.toNumber( 'pcthct' );
                 var paO2 = data.paO2.toNumber( 'mmHg' );


                 if( currentHct < minHct ) {
                 return math.round( paO2Predicted - paO2 );
                     return '-';
            }
        },
        aaGradientO2Predicted: {
            name: 'A-a O<sub>2</sub> gradient (predicted)',
            abbreviation: 'A-a O<sub>2</sub> pred.',
            data: {
                variables: {
                     required: [ 'age' ]
                 }
                 }
            },
            units: 'mmHg',
            formula: '<math>\\text{Predicted A-a gradient}_{\\mathrm{O}_2} = \\frac{(\\mathrm{age_{yr} + 10)}}{4}</math>',
            references: [
                'Hantzidiamantis PJ, Amaro E. Physiology, Alveolar to Arterial Oxygen Gradient. 2021 Feb 22. In: StatPearls [Internet]. Treasure Island (FL): StatPearls Publishing; 2021 Jan–. PMID: 31424737.'
            ],
            calculate: function( data ) {
                var age = data.age.toNumber( 'yr' );


                 return data.ebv.toNumber( 'mL' ) * ( currentHct - minHct ) / currentHct;
                 return ( age + 10 ) / 4;
             }
             }
         },
         },
         minUop: {
         weightBasedTidalVolume: {
             name: 'Minimum urine output',
             name: 'Weight-based tidal volume',
             abbreviation: 'Min UOP',
             abbreviation: 'Weight-based TV',
             data: {
             data: {
                calculations: {
                    required: [ 'ibw' ]
                },
                 variables: {
                 variables: {
                     required: [ 'weight', 'age' ],
                     required: [ 'weightBasedTidalVolumePerKgMin', 'weightBasedTidalVolumePerKgMax' ]
                    optional: [ 'caseDuration' ]
                 }
                 }
             },
             },
             type: 'string',
             type: 'string',
             formula: '',
             description: '<ul><li>Calculated using ideal body weight</li><li>Low tidal volume uses 6-8 mL/kg<sup>1</sup><ul><li>Current evidence does not show benefit of intraoperative low tidal volumes for patients without pulmonary injury<sup>2</sup></li></ul></li>',
             references: [
             references: [
                 'Klahr S, Miller SB. Acute oliguria. N Engl J Med. 1998 Mar 5;338(10):671-5. doi: 10.1056/NEJM199803053381007. PMID: 9486997.',
                 'Acute Respiratory Distress Syndrome Network, Brower RG, Matthay MA, Morris A, Schoenfeld D, Thompson BT, Wheeler A. Ventilation with lower tidal volumes as compared with traditional tidal volumes for acute lung injury and the acute respiratory distress syndrome. N Engl J Med. 2000 May 4;342(18):1301-8. doi: 10.1056/NEJM200005043421801. PMID: 10793162.',
                 'Arant BS Jr. Postnatal development of renal function during the first year of life. Pediatr Nephrol. 1987 Jul;1(3):308-13. doi: 10.1007/BF00849229. PMID: 3153294.'
                 'Karalapillai D, Weinberg L, Peyton P, Ellard L, Hu R, Pearce B, Tan CO, Story D, O\'Donnell M, Hamilton P, Oughton C, Galtieri J, Wilson A, Serpa Neto A, Eastwood G, Bellomo R, Jones DA. Effect of Intraoperative Low Tidal Volume vs Conventional Tidal Volume on Postoperative Pulmonary Complications in Patients Undergoing Major Surgery: A Randomized Clinical Trial. JAMA. 2020 Sep 1;324(9):848-858. doi: 10.1001/jama.2020.12866. PMID: 32870298; PMCID: PMC7489812.'
             ],
             ],
             calculate: function( data ) {
             calculate: function( data ) {
                 var weight = data.weight.toNumber( 'kgwt' );
                 var ibw = data.ibw.toNumber( 'kgwt' );
                 var age = data.age.toNumber( 'yo' );
                 var weightBasedTidalVolumePerKgMin = data.weightBasedTidalVolumePerKgMin.toNumber( 'mL/kgwt' );
                 var caseDuration = data.caseDuration ? data.caseDuration.toNumber( 'hr' ) : null;
                 var weightBasedTidalVolumePerKgMax = data.weightBasedTidalVolumePerKgMax.toNumber( 'mL/kgwt' );


                 var minUop;
                 return math.round( weightBasedTidalVolumePerKgMin * ibw ) + '-' + math.round( weightBasedTidalVolumePerKgMax * ibw ) + ' mL';
 
                if( age > 1 ) {
                    minUop = 0.5 * weight;
                } else {
                    minUop = 1 * weight;
                }
 
                if( caseDuration ) {
                    minUop = minUop * caseDuration + ' mL';
                } else {
                    minUop = minUop + ' mL/hr';
                }
 
                return minUop;
             }
             }
        }
    }, 'SimpleCalculation' );
    var tableMaxWidth = 600;
    mw.calculators.addCalculators( moduleId, {
        anatomy: {
            name: 'Patient statistics',
            calculations: [
                'bmi',
                'bsa',
                'ibw',
                'lbw'
            ],
            css: {
                'max-width': tableMaxWidth
            },
            table: true
        },
        airway: {
            name: 'Airway management',
            calculations: [
                'bladeMacSize',
                'bladeMillerSize',
                'ettSize',
                'ettDepth',
                'lmaSize'
            ],
            css: {
                'max-width': tableMaxWidth
            },
            table: true
        },
        fluidManagement: {
            name: 'Fluid management',
            calculations: [
                'fluidMaintenanceRate',
                'intraopFluids',
                'ebv',
                'maxAbl',
                'minUop'
            ],
            css: {
                'max-width': tableMaxWidth
            },
            table: true
         }
         }
     } );
     } );
}() );
}() );

Latest revision as of 06:27, 19 March 2022

( function() {
    mw.calculators.addUnitsBases( {
        bpm: {
            toString: function( units ) {
                units = units.replace( 'bpm', 'beats/min' );

                return units;
            }
        },
        hgb: {
            toString: function( units ) {
                units = units.replace( 'hgbperdL', '/dL' );
                units = units.replace( /\s?pcthct/, '%' );

                return units;
            }
        },
        o2: {
            toString: function( units ) {
                units = units.replace( /\s?pcto2/, '%' );

                return units;
            }
        },
        temperature: {
            toString: function( units ) {
                units = units.replace( 'deg', '&deg;' );

                return units;
            }
        }
    } );

    mw.calculators.addUnits( {
        bpm: {
            baseName: 'bpm'
        },
        pcthct: {
            baseName: 'hgb'
        },
        pcto2: {
            baseName: 'o2'
        },
        ghgbperdL: {
            baseName: 'hgb',
            prefixes: 'short',
            definition: '3 pcthct'
        }
    } );

    mw.calculators.addVariables( {
        fiO2: {
            name: 'FiO<sub>2</sub>',
            type: 'number',
            abbreviation: 'FiO<sub>2</sub>',
            minValue: '10 pcto2',
            maxValue: '100 pcto2',
            defaultValue: '21 pcto2',
            maxLength: 3,
            units: [
                'pcto2'
            ]
        },
        heartRate: {
            name: 'Heart rate',
            type: 'number',
            abbreviation: 'HR',
            defaultValue: '60 bpm',
            maxLength: 4,
            units: [
                'bpm'
            ]
        },
        hgb: {
            name: 'Hemoglobin/hematocrit',
            type: 'number',
            abbreviation: 'HgB',
            minValue: '3 ghgbperdL',
            maxValue: '25 ghgbperdL',
            defaultValue: '13 ghgbperdL',
            maxLength: 4,
            units: [
                'pcthct',
                'ghgbperdL'
            ]
        },
        paCO2: {
            name: 'PaCO<sub>2</sub>',
            type: 'number',
            abbreviation: 'PaCO<sub>2</sub>',
            minValue: '20 mmHg',
            defaultValue: '40 mmHg',
            maxLength: 3,
            units: [
                'mmHg'
            ]
        },
        paO2: {
            name: 'PaO<sub>2</sub>',
            type: 'number',
            abbreviation: 'PaO<sub>2</sub>',
            minValue: '25 mmHg',
            defaultValue: '100 mmHg',
            maxLength: 3,
            units: [
                'mmHg'
            ]
        },
        pAtm: {
            name: 'Atmospheric pressure',
            type: 'number',
            abbreviation: 'P<sub>atm</sub>',
            minValue: '0 mmHg',
            defaultValue: '760 mmHg',
            maxLength: 4,
            units: [
                'mmHg'
            ]
        },
        saO2: {
            name: 'SaO<sub>2</sub>',
            type: 'number',
            abbreviation: 'SaO<sub>2</sub>',
            minValue: '25 pcto2',
            maxValue: '100 pcto2',
            defaultValue: '100 pcto2',
            maxLength: 3,
            units: [
                'pcto2'
            ]
        },
        smvO2: {
            name: 'SmvO<sub>2</sub>',
            type: 'number',
            abbreviation: 'SmvO<sub>2</sub>',
            minValue: '25 pcto2',
            maxValue: '100 pcto2',
            defaultValue: '75 pcto2',
            maxLength: 3,
            units: [
                'pcto2'
            ]
        },
        raceSpirometry: {
            name: 'Race',
            type: 'string',
            abbreviation: 'Race',
            defaultValue: 'unknown',
            options: {
                unknown: 'Unknown',
                black: 'Black',
                caucasian: 'Caucasian',
                mexican: 'Mexican-American'
            }
        },
        temperature: {
            name: 'Temperature',
            type: 'number',
            abbreviation: 'Temp',
            minValue: '20 degC',
            maxValue: '44 degC',
            defaultValue: '37 degC',
            maxLength: 5,
            units: [
                'degC',
                'degF'
            ]
        },
        weightBasedTidalVolumePerKgMin: {
            name: 'Minimum tidal volume',
            type: 'number',
            abbreviation: 'Min TV',
            minValue: '3 mL/kgwt',
            maxValue: '12 mL/kgwt',
            defaultValue: '6 mL/kgwt',
            maxLength: 2,
            units: [
                'mL/kgwt'
            ]
        },
        weightBasedTidalVolumePerKgMax: {
            name: 'Maximum tidal volume',
            type: 'number',
            abbreviation: 'Max TV',
            minValue: '3 mL/kgwt',
            maxValue: '12 mL/kgwt',
            defaultValue: '8 mL/kgwt',
            maxLength: 2,
            units: [
                'mL/kgwt'
            ]
        }
    } );

    // Force re-render of ibw and lbw. This is necessary to remove the additional inputs for patient variables from the
    // calculation which are now provided by the patient input toolbar.
    mw.calculators.calculations.ibw.render();
    mw.calculators.calculations.lbw.render();

    mw.calculators.addCalculations( {
        bmi: {
            name: 'Body mass index',
            abbreviation: 'BMI',
            data: {
                variables: {
                    required: [ 'weight', 'height' ]
                }
            },
            digits: 0,
            units: 'kg/m^2',
            formula: '<math>\\mathrm{BMI} = \\frac{\\mathrm{mass_{kg}}}{{(\\mathrm{height_{m}}})^2}</math>',
            link: '[[Body mass index]]',
            references: [],
            calculate: function( data ) {
                return data.weight.toNumber( 'kgwt' ) / Math.pow( data.height.toNumber( 'm' ), 2 );
            }
        },
        bsa: {
            name: 'Body surface area',
            abbreviation: 'BSA',
            data: {
                variables: {
                    required: [ 'weight', 'height' ]
                }
            },
            digits: 2,
            units: 'm^2',
            formula: '<math>\\mathrm{BSA} = \\sqrt{\\frac{\\mathrm{weight_{kg}}*\\mathrm{height_{cm}}}{3600}}</math>',
            link: false,
            references: [
                'Mosteller RD. Simplified calculation of body-surface area. N Engl J Med. 1987 Oct 22;317(17):1098. doi: 10.1056/NEJM198710223171717. PMID: 3657876.'
            ],
            calculate: function( data ) {
                return Math.sqrt( data.height.toNumber( 'cm' ) * data.weight.toNumber( 'kgwt' ) / 3600 );
            }
        },
        systolicBloodPressure: {
            name: 'Systolic blood pressure',
            abbreviation: 'SBP',
            data: {
                variables: {
                    required: [ 'age' ]
                }
            },
            type: 'string',
            references: [
                'Baby Miller 6e, ch. 16, pg. 550'
            ],
            calculate: function( data ) {
                var age = data.age.toNumber( 'yo' );

                var systolicMin, systolicMax, diastolicMin, diastolicMax, meanMin, meanMax;

                if( age >= 16 ) {
                    systolicMin = 100;
                    systolicMax = 125;
                } else if( age >= 13 ) {
                    systolicMin = 95;
                    systolicMax = 120;
                } else if( age >= 9 ) {
                    systolicMin = 90;
                    systolicMax = 115;
                } else if( age >= 6 ) {
                    systolicMin = 85;
                    systolicMax = 105;
                } else if( age >= 3 ) {
                    systolicMin = 80;
                    systolicMax = 100;
                } else if( age >= 1 ) {
                    systolicMin = 75;
                    systolicMax = 95;
                } else if( age >= 6 / 12 ) {
                    systolicMin = 70;
                    systolicMax = 90;
                } else if( age >= 1 / 12 ) {
                    systolicMin = 65;
                    systolicMax = 85;
                } else {
                    systolicMin = 60;
                    systolicMax = 75;
                }
            }
        }
    } );

    // Cardiovascular
    mw.calculators.addCalculations( {
        vO2: {
            name: 'Rate of oxygen consumption (VO<sub>2</sub>)',
            abbreviation: 'VO<sub>2</sub>',
            data: {
                calculations: {
                    required: [ 'bsa' ]
                },
                variables: {
                    optional: [ 'age' ]
                }
            },
            units: 'mL/min',
            formula: '<math>\\mathrm{VO_2} = \\begin{cases} 125 * \\mathrm{BSA}  & \\text{if age} < 70 \\\\ 110 * \\mathrm{BSA} & \\text{if age} \\geq 70 \\end{cases}</math>',
            references: [],
            calculate: function( data ) {
                var bsa = data.bsa.toNumber();
                var age = data.age ? data.age.toNumber( 'yr' ) : null;

                if( age < 70 ) {
                    return 125 * bsa;
                } else {
                    return 110 * bsa;
                }
            }
        },
        cardiacOutputFick: {
            name: 'Cardiac output (Fick)',
            abbreviation: 'CO (Fick)',
            data: {
                variables: {
                    required: [ 'saO2', 'smvO2', 'hgb' ]
                },
                calculations: {
                    required: [ 'vO2' ]
                }
            },
            units: 'L/min',
            formula: '<math>\\mathrm{CO_{Fick}}=\\frac{\\mathrm{VO_2}}{(\\mathrm{S_aO_2} - \\mathrm{S_{mv}O_2}) * H_b * 13.4}</math>',
            link: false,
            references: [],
            calculate: function( data ) {
                var vO2 = data.vO2.toNumber( 'mL/min' );
                var saO2 = data.saO2.toNumber() / 100;
                var smvO2 = data.smvO2.toNumber() / 100;
                var hgb = data.hgb.toNumber( 'ghgbperdL' );

                return vO2 / ( ( saO2 - smvO2 ) * hgb * 13.4 );
            }
        },
        cardiacIndex: {
            name: 'Cardiac index',
            abbreviation: 'CI',
            data: {
                calculations: {
                    required: [ 'bsa', 'cardiacOutputFick' ]
                }
            },
            units: 'L/min/m^2',
            formula: '<math>\\mathrm{CI}=\\frac{\\mathrm{CO}}{\\mathrm{BSA}}</math>',
            link: false,
            references: [],
            calculate: function( data ) {
                var cardiacOutput = data.cardiacOutputFick.toNumber( 'L/min' );
                var bsa = data.bsa.toNumber( 'm^2' );

                return cardiacOutput / bsa;
            }
        },
        strokeVolume: {
            name: 'Stroke volume',
            abbreviation: 'SV',
            data: {
                variables: {
                    required: [ 'heartRate' ]
                },
                calculations: {
                    required: [ 'cardiacOutputFick' ]
                }
            },
            units: 'mL',
            formula: '<math>\\mathrm{SV}=\\frac{\\mathrm{CO}}{\\mathrm{HR}}</math>',
            link: false,
            references: [],
            calculate: function( data ) {
                var cardiacOutput = data.cardiacOutputFick.toNumber( 'mL/min' );
                var heartRate = data.heartRate.toNumber();

                return cardiacOutput / heartRate;
            }
        }
    } );

    // Neuro
    mw.calculators.addCalculations( {
        brainMass: {
            name: 'Brain mass',
            data: {
                variables: {
                    optional: [ 'age', 'gender' ]
                }
            },
            digits: 0,
            units: 'gwt',
            description: 'This calculation will give a more precise estimate of brain mass if age and/or gender are provided.',
            references: [
                'Dekaban AS. Changes in brain weights during the span of human life: relation of brain weights to body heights and body weights. Ann Neurol. 1978 Oct;4(4):345-56. doi: 10.1002/ana.410040410. PMID: 727739.'
            ],
            calculate: function( data ) {
                var age = data.age ? data.age.toNumber( 'yr' ) : null;
                var gender = data.gender ? data.gender : null;

                var brainMassFemale = 1290;
                var brainMassMale = 1450;

                if( age !== null ) {
                    if( age <= 10 / 365 ) {
                        // <=10 days
                        brainMassFemale = 360;
                        brainMassMale = 380;
                    } else if( age <= 4 * 30 / 365 ) {
                        // Less than 4 months. This is a gap in the reported data of the paper, so linearly interpolate?
                        var ageFactor = 1 - ( 4 * 30 / 365 - age ) / ( 4 * 30 / 365 - 10 / 365 );

                        brainMassFemale = 360 + ageFactor * ( 580 - 360 );
                        brainMassMale = 380 + ageFactor * ( 640 - 380 );
                    } else if( age <= 8 * 30 / 365 ) {
                        // <=8 months
                        brainMassFemale = 580;
                        brainMassMale = 640;
                    } else if( age <= 18 * 30 / 365 ) {
                        // <=18 months
                        brainMassFemale = 940;
                        brainMassMale = 970;
                    } else if( age <= 30 * 30 / 365 ) {
                        // <=30 months
                        brainMassFemale = 1040;
                        brainMassMale = 1120;
                    } else if( age <= 43 * 30 / 365 ) {
                        // <=43 months
                        brainMassFemale = 1090;
                        brainMassMale = 1270;
                    } else if( age <= 5 ) {
                        brainMassFemale = 1150;
                        brainMassMale = 1300;
                    } else if( age <= 7 ) {
                        brainMassFemale = 1210;
                        brainMassMale = 1330;
                    } else if( age <= 9 ) {
                        brainMassFemale = 1180;
                        brainMassMale = 1370;
                    } else if( age <= 12 ) {
                        brainMassFemale = 1260;
                        brainMassMale = 1440;
                    } else if( age <= 15 ) {
                        brainMassFemale = 1280;
                        brainMassMale = 1410;
                    } else if( age <= 18 ) {
                        brainMassFemale = 1340;
                        brainMassMale = 1440;
                    } else if( age <= 21 ) {
                        brainMassFemale = 1310;
                        brainMassMale = 1450;
                    } else if( age <= 30 ) {
                        brainMassFemale = 1300;
                        brainMassMale = 1440;
                    } else if( age <= 40 ) {
                        brainMassFemale = 1290;
                        brainMassMale = 1440;
                    } else if( age <= 50 ) {
                        brainMassFemale = 1290;
                        brainMassMale = 1430;
                    } else if( age <= 55 ) {
                        brainMassFemale = 1280;
                        brainMassMale = 1410;
                    } else if( age <= 60 ) {
                        brainMassFemale = 1250;
                        brainMassMale = 1370;
                    } else if( age <= 65 ) {
                        brainMassFemale = 1240;
                        brainMassMale = 1370;
                    } else if( age <= 70 ) {
                        brainMassFemale = 1240;
                        brainMassMale = 1360;
                    } else if( age <= 75 ) {
                        brainMassFemale = 1230;
                        brainMassMale = 1350;
                    } else if( age <= 80 ) {
                        brainMassFemale = 1190;
                        brainMassMale = 1330;
                    } else if( age <= 85 ) {
                        brainMassFemale = 1170;
                        brainMassMale = 1310;
                    } else {
                        brainMassFemale = 1140;
                        brainMassMale = 1290;
                    }
                }

                if( gender === 'F' ) {
                    return brainMassFemale;
                } else if( gender === 'M' ) {
                    return brainMassMale;
                } else {
                    return ( brainMassFemale + brainMassMale ) / 2;
                }
            }
        },
        cerebralBloodVolume: {
            name: 'Cerebral blood volume',
            abbreviation: 'CBV',
            data: {
                calculations: {
                    required: [ 'brainMass' ]
                }
            },
            units: 'mL',
            description: '4 mL per 100g of brain mass',
            references: [
                'Tameem A, Krovvidi H, Cerebral physiology, Continuing Education in Anaesthesia Critical Care & Pain, Volume 13, Issue 4, August 2013, Pages 113–118, https://doi.org/10.1093/bjaceaccp/mkt001'
            ],
            calculate: function( data ) {
                var brainMass = data.brainMass.toNumber( 'gwt' );

                return 4 * brainMass / 100;
            }
        },
        cerebralMetabolicRateFactor: {
            name: 'Cerebral metabolic rate factor',
            abbreviation: '%CMR',
            data: {
                variables: {
                    optional: [ 'temperature' ]
                }
            },
            description: '7% change in CMR for every 1 &deg;C change in temperature',
            references: [
                'Tameem A, Krovvidi H, Cerebral physiology, Continuing Education in Anaesthesia Critical Care & Pain, Volume 13, Issue 4, August 2013, Pages 113–118, https://doi.org/10.1093/bjaceaccp/mkt001'
            ],
            calculate: function( data ) {
                var temperature = data.temperature ? data.temperature.toNumber( 'degC' ) : null;

                var cerebralMetabolicRateFactor = 1;

                if( temperature ) {
                    cerebralMetabolicRateFactor += 0.07 * ( temperature - 37 );
                }

                return cerebralMetabolicRateFactor;
            }
        },
        cerebralMetabolicRateO2: {
            name: 'Cerebral metabolic rate (O<sub>2</sub>)',
            abbreviation: 'CMRO<sub>2</sub>',
            data: {
                calculations: {
                    required: [ 'brainMass', 'cerebralMetabolicRateFactor' ]
                },
                variables: {
                    optional: [ 'temperature' ]
                }
            },
            units: 'mL/min',
            description: '<ul><li>3 mL O<sub>2</sub>/min per 100g of brain mass</li><li>If temperature is provided, adjusts estimate using 7% change in CMR for every 1 &deg;C change in temperature</li></ul>',
            references: [
                'Tameem A, Krovvidi H, Cerebral physiology, Continuing Education in Anaesthesia Critical Care & Pain, Volume 13, Issue 4, August 2013, Pages 113–118, https://doi.org/10.1093/bjaceaccp/mkt001'
            ],
            calculate: function( data ) {
                // Temperature is included as an optional variable to generate the input.
                // It is used by cerebralMetabolicRateFactor, which is an internal calculation not typically shown.
                var brainMass = data.brainMass.toNumber( 'gwt' );
                var cerebralMetabolicRateFactor = data.cerebralMetabolicRateFactor.toNumber();

                return cerebralMetabolicRateFactor * 3 * brainMass / 100;
            }
        },
        cerebralMetabolicRateGlucose: {
            name: 'Cerebral metabolic rate (Glucose)',
            abbreviation: 'CMR<sub>glu</sub>',
            data: {
                calculations: {
                    required: [ 'brainMass', 'cerebralMetabolicRateFactor' ]
                }
            },
            units: 'mg/min',
            description: '<ul><li>5 mg glucose/min per 100g of brain mass</li><li>7% change in CMR for every 1 &deg;C change in temperature</li></ul>',
            references: [
                'Tameem A, Krovvidi H, Cerebral physiology, Continuing Education in Anaesthesia Critical Care & Pain, Volume 13, Issue 4, August 2013, Pages 113–118, https://doi.org/10.1093/bjaceaccp/mkt001'
            ],
            calculate: function( data ) {
                var brainMass = data.brainMass.toNumber( 'gwt' );
                var cerebralMetabolicRateFactor = data.cerebralMetabolicRateFactor.toNumber();

                return cerebralMetabolicRateFactor * 5 * brainMass / 100;
            }
        },
        cerebralBloodFlow: {
            name: 'Cerebral blood flow',
            abbreviation: 'CBF',
            data: {
                calculations: {
                    required: [ 'brainMass', 'cerebralMetabolicRateFactor' ]
                },
                variables: {
                    optional: [ 'paCO2' ]
                }
            },
            units: 'mL/min',
            description: '<ul><li>50 mL/min per 100g of brain mass.</li><li>Every mmHg in PaCO2 changes CBF by 1.5 mL/min per 100g of brain mass.</li><li>Cerebral blood flow and cerebral metabolic rate are coupled. Factors that alter CMR (e.g. temperature) will proportionally alter CBF.</li>',
            references: [
                'Tameem A, Krovvidi H, Cerebral physiology, Continuing Education in Anaesthesia Critical Care & Pain, Volume 13, Issue 4, August 2013, Pages 113–118, https://doi.org/10.1093/bjaceaccp/mkt001',
                'Brian JE Jr. Carbon dioxide and the cerebral circulation. Anesthesiology. 1998 May;88(5):1365-86. doi: 10.1097/00000542-199805000-00029. PMID: 9605698.'
            ],
            calculate: function( data ) {
                var brainMass = data.brainMass.toNumber( 'gwt' );
                var cerebralMetabolicRateFactor = data.cerebralMetabolicRateFactor.toNumber();
                var paCO2 = data.paCO2.toNumber( 'mmHg' );

                var cerebralBloodFlow = cerebralMetabolicRateFactor * 50 * brainMass / 100;

                if( paCO2 ) {
                    // CO2 reductions don't reduce CBF more than 50%
                    var minCerebralBloodFlow = cerebralBloodFlow / 2;

                    cerebralBloodFlow += 1.5 * brainMass / 100 * ( paCO2 - 40 );

                    cerebralBloodFlow = math.max( cerebralBloodFlow, minCerebralBloodFlow );
                }

                return cerebralBloodFlow;
            }
        }
    } );



    // Pulmonary
    mw.calculators.addCalculations( {
        paO2Predicted: {
            name: 'PaO<sub>2</sub> (predicted)',
            abbreviation: 'PaO<sub>2</sub> pred.',
            data: {
                variables: {
                    required: [ 'pAtm', 'fiO2', 'paCO2' ]
                }
            },
            units: 'mmHg',
            formula: '<math>P_{aO_2Predicted} = FiO_2*(P_{atm}-P_{H_{2}O})-\\frac{P_{aCO_2}}{R}</math>',
            references: [
                'McFarlane MJ, Imperiale TF. Use of the alveolar-arterial oxygen gradient in the diagnosis of pulmonary embolism. Am J Med. 1994 Jan;96(1):57-62. doi: 10.1016/0002-9343(94)90116-3. PMID: 8304364.'
            ],
            calculate: function( data ) {
                var fiO2 = data.fiO2.toNumber( 'pcto2' ) / 100;
                var pAtm = data.pAtm.toNumber( 'mmHg' );
                var pH2O = 47; // mmHg
                var paCO2 = data.paCO2.toNumber( 'mmHg' );
                var r = 0.8;

                return fiO2 * ( pAtm - pH2O ) - paCO2 / r;
            }
        },
        aaGradientO2: {
            name: 'A-a O<sub>2</sub> gradient',
            abbreviation: 'A-a O<sub>2</sub>',
            data: {
                calculations: {
                    required: [ 'paO2Predicted' ]
                },
                variables: {
                    required: [ 'paO2' ]
                }
            },
            units: 'mmHg',
            formula: '<math>\\text{A-a gradient}_{\\mathrm{O}_2} = P_{aO_2Predicted}-P_{aO_2} </math>',
            references: [
                'McFarlane MJ, Imperiale TF. Use of the alveolar-arterial oxygen gradient in the diagnosis of pulmonary embolism. Am J Med. 1994 Jan;96(1):57-62. doi: 10.1016/0002-9343(94)90116-3. PMID: 8304364.'
            ],
            calculate: function( data ) {
                var paO2Predicted = data.paO2Predicted.toNumber( 'mmHg' );
                var paO2 = data.paO2.toNumber( 'mmHg' );

                return math.round( paO2Predicted - paO2 );
            }
        },
        aaGradientO2Predicted: {
            name: 'A-a O<sub>2</sub> gradient (predicted)',
            abbreviation: 'A-a O<sub>2</sub> pred.',
            data: {
                variables: {
                    required: [ 'age' ]
                }
            },
            units: 'mmHg',
            formula: '<math>\\text{Predicted A-a gradient}_{\\mathrm{O}_2} = \\frac{(\\mathrm{age_{yr} + 10)}}{4}</math>',
            references: [
                'Hantzidiamantis PJ, Amaro E. Physiology, Alveolar to Arterial Oxygen Gradient. 2021 Feb 22. In: StatPearls [Internet]. Treasure Island (FL): StatPearls Publishing; 2021 Jan–. PMID: 31424737.'
            ],
            calculate: function( data ) {
                var age = data.age.toNumber( 'yr' );

                return ( age + 10 ) / 4;
            }
        },
        weightBasedTidalVolume: {
            name: 'Weight-based tidal volume',
            abbreviation: 'Weight-based TV',
            data: {
                calculations: {
                    required: [ 'ibw' ]
                },
                variables: {
                    required: [ 'weightBasedTidalVolumePerKgMin', 'weightBasedTidalVolumePerKgMax' ]
                }
            },
            type: 'string',
            description: '<ul><li>Calculated using ideal body weight</li><li>Low tidal volume uses 6-8 mL/kg<sup>1</sup><ul><li>Current evidence does not show benefit of intraoperative low tidal volumes for patients without pulmonary injury<sup>2</sup></li></ul></li>',
            references: [
                'Acute Respiratory Distress Syndrome Network, Brower RG, Matthay MA, Morris A, Schoenfeld D, Thompson BT, Wheeler A. Ventilation with lower tidal volumes as compared with traditional tidal volumes for acute lung injury and the acute respiratory distress syndrome. N Engl J Med. 2000 May 4;342(18):1301-8. doi: 10.1056/NEJM200005043421801. PMID: 10793162.',
                'Karalapillai D, Weinberg L, Peyton P, Ellard L, Hu R, Pearce B, Tan CO, Story D, O\'Donnell M, Hamilton P, Oughton C, Galtieri J, Wilson A, Serpa Neto A, Eastwood G, Bellomo R, Jones DA. Effect of Intraoperative Low Tidal Volume vs Conventional Tidal Volume on Postoperative Pulmonary Complications in Patients Undergoing Major Surgery: A Randomized Clinical Trial. JAMA. 2020 Sep 1;324(9):848-858. doi: 10.1001/jama.2020.12866. PMID: 32870298; PMCID: PMC7489812.'
            ],
            calculate: function( data ) {
                var ibw = data.ibw.toNumber( 'kgwt' );
                var weightBasedTidalVolumePerKgMin = data.weightBasedTidalVolumePerKgMin.toNumber( 'mL/kgwt' );
                var weightBasedTidalVolumePerKgMax = data.weightBasedTidalVolumePerKgMax.toNumber( 'mL/kgwt' );

                return math.round( weightBasedTidalVolumePerKgMin * ibw ) + '-' + math.round( weightBasedTidalVolumePerKgMax * ibw ) + ' mL';
            }
        }
    } );
}() );