MediaWiki:Gadget-calculator-neuro.js

From WikiAnesthesia

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
( function() {
    mw.calculators.addUnitsBases( {
        temperature: {
            toString: function( units ) {
                units = units.replace( 'deg', '°' );

                return units;
            }
        }
    } );

    var gcsEyeResponseOptions = [
        'Not testable',
        'No eye opening',
        'To pain',
        'To voice',
        'Spontaneous'
    ];

    var gcsVerbalResponseOptions = [
        'Not testable',
        'Makes no sounds',
        'Incomprehensible sounds',
        'Inappropriate words',
        'Confused',
        'Oriented'
    ];

    var gcsMotorResponseOptions = [
        'Not testable',
        'No movements',
        'Extension to pain',
        'Flexion to pain',
        'Withdrawal from pain',
        'Localizes Pain',
        'Obeys commands'
    ];

    var avmEloquenceOfAdjacentBrainOptions = [
        'Non-eloquent',
        'Eloquent'
    ];

    var avmVenousDrainageOptions = [
        'Superficial veins only',
        'Deep veins'
    ];

    var avmRupturedPresentationOptions = [
        'Unruptured',
        'Ruptured'
    ];

    var avmNidusCompactnessOptions = [
        'Compact',
        'Diffuse'
    ];

    mw.calculators.addVariables( {
        paCO2: {
            name: 'PaCO<sub>2</sub>',
            type: 'number',
            abbreviation: 'PaCO<sub>2</sub>',
            minValue: '20 mmHg',
            defaultValue: '40 mmHg',
            maxLength: 3,
            units: [
                'mmHg'
            ]
        },
        temperature: {
            name: 'Temperature',
            type: 'number',
            abbreviation: 'Temp',
            minValue: '20 degC',
            maxValue: '44 degC',
            defaultValue: '37 degC',
            maxLength: 5,
            units: [
                'degC',
                'degF'
            ]
        },
        gcsEyeResponse: {
            name: 'Eye response',
            type: 'string',
            abbreviation: 'Eye',
            defaultValue: 'Not testable',
            options: gcsEyeResponseOptions
        },
        gcsVerbalResponse: {
            name: 'Verbal response',
            type: 'string',
            abbreviation: 'Verbal',
            defaultValue: 'Not testable',
            options: gcsVerbalResponseOptions
        },
        gcsMotorResponse: {
            name: 'Motor response',
            type: 'string',
            abbreviation: 'Motor',
            defaultValue: 'Not testable',
            options: gcsMotorResponseOptions
        },
        avmSize: {
            name: 'AVM Size',
            type: 'number',
            minValue: '0.1 cm',
            maxValue: '20 cm',
            abbreviation: 'AVM size',
            defaultValue: '1 cm',
            units: [
                'cm'
            ]
        },
        avmEloquenceOfAdjacentBrain: {
            name: 'Eloquence of adjacent brain',
            type: 'string',
            abbreviation: 'Eloquence',
            defaultValue: 'Non-eloquent',
            options: avmEloquenceOfAdjacentBrainOptions
        },
        avmVenousDrainage: {
            name: 'Venous drainage',
            type: 'string',
            abbreviation: 'Venous drainage',
            defaultValue: 'Superficial veins only',
            options: avmVenousDrainageOptions
        },
        avmRupturedPresentation: {
            name: 'Ruptured presentation',
            type: 'string',
            abbreviation: 'Ruptured',
            defaultValue: 'No',
            options: avmRupturedPresentationOptions
        },
        avmNidusCompactness: {
            name: 'Nidus compactness',
            type: 'string',
            abbreviation: 'Compactness',
            defaultValue: 'No',
            options: avmNidusCompactnessOptions
        }
    } );

    // 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 sex 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'
            ],
            searchData: 'cmro2',
            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;
            }
        },
        glasgowComaScale: {
            name: 'Glasgow Coma Scale',
            abbreviation: 'Glasgow Coma Scale',
            data: {
                variables: {
                    required: [ 'gcsEyeResponse', 'gcsVerbalResponse', 'gcsMotorResponse' ]
                }
            },
            type: 'string',
            references: [
                'Teasdale G, Jennett B. Assessment of coma and impaired consciousness. A practical scale. Lancet. 1974 Jul 13;2(7872):81-4. doi: 10.1016/s0140-6736(74)91639-0. PMID: 4136544.'
            ],
            calculate: function( data ) {
                var gcsEyeResponse = gcsEyeResponseOptions.indexOf( data.gcsEyeResponse );
                var gcsVerbalResponse = gcsVerbalResponseOptions.indexOf( data.gcsVerbalResponse );
                var gcsMotorResponse = gcsMotorResponseOptions.indexOf( data.gcsMotorResponse );

                var gcsScore;

                if( !gcsEyeResponse || !gcsVerbalResponse || !gcsMotorResponse ) {
                    gcsScore = 'Cannot be calculated because one or more components are not testable';

                    gcsEyeResponse = gcsEyeResponse ? gcsEyeResponse : 'NT';
                    gcsVerbalResponse = gcsVerbalResponse ? gcsVerbalResponse : 'NT';
                    gcsMotorResponse = gcsMotorResponse ? gcsMotorResponse : 'NT';
                } else {
                    gcsScore = gcsEyeResponse + gcsVerbalResponse + gcsMotorResponse;
                }

                var gcsScale = 'E(' + gcsEyeResponse + ') V(' + gcsVerbalResponse + ') M(' + gcsMotorResponse + ')';

                var $gcsResult = $( '<div>' , { 'class': 'grid' } ).append(
                    $( '<div>', { 'class': 'row' } ).append(
                        $( '<div>', { 'class': 'col' } ).append( 'Glasgow coma score:' ),
                        $( '<div>', { 'class': 'col' } ).append( gcsScore )
                    ),
                    $( '<div>', { 'class': 'row' } ).append(
                        $( '<div>', { 'class': 'col' } ).append( 'Glasgow coma scale:' ),
                        $( '<div>', { 'class': 'col' } ).append( gcsScale )
                    )
                );

                return $gcsResult.html();
            }
        },
        avmSpetlzerMartinGrade: {
            name: 'Spetlzer-Martin AVM grading scale',
            abbreviation: 'Spetzler-Martin grade',
            data: {
                variables: {
                    required: [ 'avmSize', 'avmEloquenceOfAdjacentBrain', 'avmVenousDrainage' ]
                }
            },
            type: 'number',
            calculate: function( data ) {
                var avmSize = data.avmSize.toNumber( 'cm' );
                var avmEloquenceOfAdjacentBrain = data.avmEloquenceOfAdjacentBrain;
                var avmVenousDrainage = data.avmVenousDrainage;

                var spetzlerMartinGrade = 0;

                // AVM size
                if( avmSize < 3 ) {
                    spetzlerMartinGrade += 1;
                } else if( avmSize <= 6 ) {
                    spetzlerMartinGrade += 2;
                } else {
                    spetzlerMartinGrade += 3;
                }

                // Eloquence of adjacent brain
                // 0 no, 1 yes
                spetzlerMartinGrade += avmEloquenceOfAdjacentBrainOptions.indexOf( avmEloquenceOfAdjacentBrain );

                // Venous drainage
                // 0 superficial, 1 deep
                spetzlerMartinGrade += avmVenousDrainageOptions.indexOf( avmVenousDrainage );

                return spetzlerMartinGrade;
            }
        },
        avmSpetzlerMartinGradeRisk: {
            name: 'Spetlzer-Martin AVM grading scale',
            abbreviation: 'Spetzler-Martin AVM grade',
            data: {
                calculations: {
                    required: [ 'avmSpetlzerMartinGrade' ]
                },
                variables: {
                    required: [ 'avmSize', 'avmEloquenceOfAdjacentBrain', 'avmVenousDrainage' ]
                }
            },
            type: 'string',
            description: '<p>The Spetzler-Martin AVM grading system predicts the morbidity/mortality risk of surgery using angiographic features</p><ul><li>Size of nidus<ul><li>0: Small (<3 cm)</li><li>1: Medium (3-6 cm)</li><li>2: Large (>6 cm)</li></ul></li><li>Eloquence of adjacent brain area<ul><li>0: Non-eloquent</li><li>1: Eloquent</li></ul></li><li>Venous drainage<ul><li>0: Superficial veins only</li><li>1: Deep veins</li></ul></li></ul>',
            references: [
                'Spetzler RF, Martin NA. A proposed grading system for arteriovenous malformations. J Neurosurg. 1986 Oct;65(4):476-83. doi: 10.3171/jns.1986.65.4.0476. PMID: 3760956.'
            ],
            calculate: function( data ) {
                var spetzlerMartinGrade = data.avmSpetlzerMartinGrade.toNumber();

                var spetzlerMartinGradeRisk = math.roman( spetzlerMartinGrade );

                if( spetzlerMartinGrade <= 3 ) {
                    spetzlerMartinGradeRisk += ' (low-to-moderate risk)';
                } else {
                    spetzlerMartinGradeRisk += ' (high-risk)';
                }

                return spetzlerMartinGradeRisk;
            }
        },
        avmSupplementalGrade: {
            name: 'Supplemental AVM grading scale',
            abbreviation: 'Supplemental AVM grade',
            data: {
                variables: {
                    required: [ 'age', 'avmRupturedPresentation', 'avmNidusCompactness' ]
                }
            },
            type: 'number',
            calculate: function( data ) {
                var age = data.age ? data.age.toNumber( 'yr' ) : 0;
                var avmRupturedPresentation = data.avmRupturedPresentation ? data.avmRupturedPresentation : null;
                var avmNidusCompactness = data.avmNidusCompactness ? data.avmNidusCompactness : null;

                var supplementalGrade = 0;

                // Age
                if( age < 20 ) {
                    supplementalGrade += 1;
                } else if( age <= 40 ) {
                    supplementalGrade += 2;
                } else {
                    supplementalGrade += 3;
                }

                // Ruptured presentation
                // 0 unruptured, 1 ruptured
                supplementalGrade += avmRupturedPresentationOptions.indexOf( avmRupturedPresentation );

                // Diffuse nidus
                // 0 compact, 1 diffuse
                supplementalGrade += avmNidusCompactnessOptions.indexOf( avmNidusCompactness );

                return supplementalGrade;
            }
        },
        avmSupplementalGradeRisk: {
            name: 'Supplemental AVM grading scale',
            abbreviation: 'Supplemental AVM grade',
            data: {
                calculations: {
                    required: [ 'avmSupplementalGrade' ]
                },
                variables: {
                    required: [ 'age', 'avmRupturedPresentation', 'avmNidusCompactness' ]
                }
            },
            type: 'string',
            description: '<p>The Supplemental AVM grading system provides additional surgical risk stratification in addition to the Spetzler-Martin grade.</p><ul><li>Age<ul><li>1: <20 yo</li><li>2: 20-40 yo</li><li>3: >40 yo</li></ul></li><li>Ruptured presentation<ul><li>0: Unruptured</li><li>1: Ruptured</li></ul></li><li>Nidus compactness<ul><li>0: Compact</li><li>1: Diffuse</li></ul></li></ul>',
            references: [
                'Lawton MT, Kim H, McCulloch CE, Mikhak B, Young WL. A supplementary grading scale for selecting patients with brain arteriovenous malformations for surgery. Neurosurgery. 2010 Apr;66(4):702-13; discussion 713. doi: 10.1227/01.NEU.0000367555.16733.E1. PMID: 20190666; PMCID: PMC2847513.'
            ],
            calculate: function( data ) {
                var supplementalGrade = data.avmSupplementalGrade.toNumber();

                var supplementalGradeRisk = math.roman( supplementalGrade );

                if( supplementalGrade <= 3 ) {
                    supplementalGradeRisk += ' (low-to-moderate risk)';
                } else {
                    supplementalGradeRisk += ' (high-risk)';
                }

                return supplementalGradeRisk;
            }
        }
    } );
}() );