public NeurologyForm() { C1 = new NeurologyFormLevel { Ordinal = 0, IsKeyMuscle = false, IsLowerMuscle = false, Name = "C1", Previous = null, RightMotorName = "5", RightMotorValue = 5, LeftMotorName = "5", LeftMotorValue = 5, RightTouchName = "2", RightTouchValue = 2, LeftTouchName = "2", LeftTouchValue = 2, RightPrickName = "2", RightPrickValue = 2, LeftPrickName = "2", LeftPrickValue = 2 }; _levels = new Dictionary<string, NeurologyFormLevel>(); var previousLevel = C1; for (var i = 0; i < LevelNames.Length; i++) { var name = LevelNames[i]; var currentLevel = new NeurologyFormLevel { IsKeyMuscle = KeyMuscles.Contains(name), IsLowerMuscle = (i >= 20 && i <= 24), Name = name, Ordinal = i + 1, Previous = previousLevel }; previousLevel.Next = currentLevel; previousLevel = currentLevel; _levels.Add(name, currentLevel); } }
public void AddRightSensoryZppValue(NeurologyFormLevel level) { if (_rightSensoryZppValues.Any(l => l.Name.ToUpper() == level.Name) || "S4_5".Equals(level.Name)) return; _rightSensoryZppValues.Add(level); }
public void AddRightMotorValue(NeurologyFormLevel level) { if (_rightMotorValues.Any(l => l.Name.ToUpper() == level.Name)) return; if (MostRostralRightMotor == null || level.Ordinal < MostRostralRightMotor.Ordinal) MostRostralRightMotor = level; if (MostCaudalRightMotor == null || level.Ordinal > MostCaudalRightMotor.Ordinal) MostCaudalRightMotor = level; _rightMotorValues.Add(level); }
public void AddNeurologicalLevelOfInjury(NeurologyFormLevel level) { if (_neurologicalLevelsOfInjury.Any(l => l.Name.ToLower() == level.Name.ToLower())) return; if (MostRostralNeurologicalLevelOfInjury == null || level.Ordinal < MostRostralNeurologicalLevelOfInjury.Ordinal) MostRostralNeurologicalLevelOfInjury = level; if (MostCaudalNeurologicalLevelOfInjury == null || level.Ordinal > MostCaudalNeurologicalLevelOfInjury.Ordinal) MostCaudalNeurologicalLevelOfInjury = level; _neurologicalLevelsOfInjury.Add(level); }
public void AddLeftSensoryValue(NeurologyFormLevel level) { if (_leftSensoryValues.Any(l => l.Name.ToUpper() == level.Name)) return; _leftSensoryValues.Add(level); }
public void AddLeftMotorZppValue(NeurologyFormLevel level) { if (_leftMotorZppValues.Any(l => l.Name.ToUpper() == level.Name) || "S4_5".Equals(level.Name)) return; _leftMotorZppValues.Add(level); }
private static void UpdateLevel(NeurologyFormLevel level, string rightTouchName, string leftTouchName, string rightPrickName, string leftPrickName, string rightMotorName, string leftMotorName) { // Right Touch level.RightTouchName = rightTouchName; level.RightTouchValue = GetDermatomeValue(rightTouchName, NormalSensoryValue); level.RightTouchImpairmentNotDueToSci = NonSciImpairmentRegex.IsMatch(rightTouchName); // Left Touch level.LeftTouchName = leftTouchName; level.LeftTouchValue = GetDermatomeValue(leftTouchName, NormalSensoryValue); level.LeftTouchImpairmentNotDueToSci = NonSciImpairmentRegex.IsMatch(leftTouchName); // Right Prick level.RightPrickName = rightPrickName; level.RightPrickValue = GetDermatomeValue(rightPrickName, NormalSensoryValue); level.RightPrickImpairmentNotDueToSci = NonSciImpairmentRegex.IsMatch(rightPrickName); // Left Prick level.LeftPrickName = leftPrickName; level.LeftPrickValue = GetDermatomeValue(leftPrickName, NormalSensoryValue); level.LeftPrickImpairmentNotDueToSci = NonSciImpairmentRegex.IsMatch(leftPrickName); // Right Motor level.RightMotorName = rightMotorName; level.RightMotorValue = GetDermatomeValue(rightMotorName, NormalMotorValue); level.RightMotorImpairmentNotDueToSci = NonSciImpairmentRegex.IsMatch(rightMotorName); // Left Motor level.LeftMotorName = leftMotorName; level.LeftMotorValue = GetDermatomeValue(leftMotorName, NormalMotorValue); level.LeftMotorImpairmentNotDueToSci = NonSciImpairmentRegex.IsMatch(leftMotorName); if (!level.IsKeyMuscle) { if ((level.RightTouchValue == 2 || level.RightTouchImpairmentNotDueToSci) && (level.RightPrickValue == 2 || level.RightPrickImpairmentNotDueToSci)) { level.RightMotorName = "5"; level.RightMotorValue = 5; } else { level.RightMotorName = (NtRegex.IsMatch(level.RightTouchName) || level.RightTouchValue == 2) && (NtRegex.IsMatch(level.RightPrickName) || level.RightPrickValue == 2) ? "NT" : "0"; level.RightMotorValue = 0; } if ((level.LeftTouchValue == 2 || level.LeftTouchImpairmentNotDueToSci) && (level.LeftPrickValue == 2 || level.LeftPrickImpairmentNotDueToSci)) { level.LeftMotorName = "5"; level.LeftMotorValue = 5; } else { level.LeftMotorName = (NtRegex.IsMatch(level.LeftTouchName) || level.LeftTouchValue == 2) && (NtRegex.IsMatch(level.LeftPrickName) || level.LeftPrickValue == 2) ? "NT" : "0"; level.LeftMotorValue = 0; } } }
public void SetRightLowestNonKeyMuscleWithMotorFunction(string levelName) { if (string.IsNullOrEmpty(levelName)) return; var key = levelName.ToUpper(); if (!_levels.ContainsKey(key)) return; if (RightLowestNonKeyMuscleWithMotorFunction != null) RightLowestNonKeyMuscleWithMotorFunction.HasOtherRightMotorFunction = false; RightLowestNonKeyMuscleWithMotorFunction = _levels[key]; RightLowestNonKeyMuscleWithMotorFunction.HasOtherRightMotorFunction = true; }
/// <summary> /// Recursive method which iterates through the values in a nuerology form while it updates the totals generating the results produced by the algorithm. /// </summary> /// <param name="neurologyForm">Form being evaluated.</param> /// <param name="totals">Brand new totals object where the results are to be stored.</param> /// <param name="level">Current neurology level being evaluated</param> /// <param name="nextNonKeyMuscleShouldBeRightMotor">Flag used to evaluate the Kathy Collins condition on the right motor results.</param> /// <param name="nextNonKeyMuscleShouldBeLeftMotor">Flag used to evaluate the Kathy Collins condition on the left motor results.</param> private static void UpdateTotalsWithLevelAt(NeurologyForm neurologyForm, NeurologyFormTotals totals, NeurologyFormLevel level, bool nextNonKeyMuscleShouldBeRightMotor, bool nextNonKeyMuscleShouldBeLeftMotor) { totals.RightTouchTotal += level.RightTouchValue; totals.LeftTouchTotal += level.LeftTouchValue; totals.RightPrickTotal += level.RightPrickValue; totals.LeftPrickTotal += level.LeftPrickValue; if (level.IsKeyMuscle) { if (level.IsLowerMuscle) { if (level.RightMotorImpairmentNotDueToSci && !totals.RightLowerMotorTotalHasImpairmentNotDueToSci) totals.RightLowerMotorTotalHasImpairmentNotDueToSci = true; if (level.LeftMotorImpairmentNotDueToSci && !totals.LeftLowerMotorTotalHasImpairmentNotDueToSci) totals.LeftLowerMotorTotalHasImpairmentNotDueToSci = true; if (NtRegex.IsMatch(level.RightMotorName) && !level.RightMotorImpairmentNotDueToSci) totals.RightLowerMotorContainsNt = true; if (NtRegex.IsMatch(level.LeftMotorName) && !level.LeftMotorImpairmentNotDueToSci) totals.LeftLowerMotorContainsNt = true; } else { if (level.RightMotorImpairmentNotDueToSci && !totals.RightUpperMotorTotalHasImpairmentNotDueToSci) totals.RightUpperMotorTotalHasImpairmentNotDueToSci = true; if (level.LeftMotorImpairmentNotDueToSci && !totals.LeftUpperMotorTotalHasImpairmentNotDueToSci) totals.LeftUpperMotorTotalHasImpairmentNotDueToSci = true; if (NtRegex.IsMatch(level.RightMotorName) && !level.RightMotorImpairmentNotDueToSci) totals.RightUpperMotorContainsNt = true; if (NtRegex.IsMatch(level.LeftMotorName) && !level.LeftMotorImpairmentNotDueToSci) totals.LeftUpperMotorContainsNt = true; } } else { if (nextNonKeyMuscleShouldBeRightMotor) { nextNonKeyMuscleShouldBeRightMotor = false; totals.AddRightMotorValue(level.Previous); if (!totals.RightSensoryHasOnlySoftValues) totals.RightMotorHasOnlySoftValues = false; } if (nextNonKeyMuscleShouldBeLeftMotor) { nextNonKeyMuscleShouldBeLeftMotor = false; totals.AddLeftMotorValue(level.Previous); if (!totals.LeftSensoryHasOnlySoftValues) totals.LeftMotorHasOnlySoftValues = false; } } if (level.RightTouchImpairmentNotDueToSci && !totals.RightTouchTotalHasImpairmentNotDueToSci) totals.RightTouchTotalHasImpairmentNotDueToSci = true; if (level.LeftTouchImpairmentNotDueToSci && !totals.LeftTouchTotalHasImpairmentNotDueToSci) totals.LeftTouchTotalHasImpairmentNotDueToSci = true; if (level.RightPrickImpairmentNotDueToSci && !totals.RightPrickTotalHasImpairmentNotDueToSci) totals.RightPrickTotalHasImpairmentNotDueToSci = true; if (level.LeftPrickImpairmentNotDueToSci && !totals.LeftPrickTotalHasImpairmentNotDueToSci) totals.LeftPrickTotalHasImpairmentNotDueToSci = true; // Check if a column contains any NT value so we can properly format the total presented to the user if (NtRegex.IsMatch(level.RightTouchName) && !level.RightTouchImpairmentNotDueToSci && !totals.RightTouchContainsNt) totals.RightTouchContainsNt = true; if (NtRegex.IsMatch(level.LeftTouchName) && !level.LeftTouchImpairmentNotDueToSci && !totals.LeftTouchContainsNt) totals.LeftTouchContainsNt = true; if (NtRegex.IsMatch(level.RightPrickName) && !level.RightPrickImpairmentNotDueToSci && !totals.RightPrickContainsNt) totals.RightPrickContainsNt = true; if (NtRegex.IsMatch(level.LeftPrickName) && !level.LeftPrickImpairmentNotDueToSci && !totals.LeftPrickContainsNt) totals.LeftPrickContainsNt = true; if (totals.RightSensoryHasOnlySoftValues && ((level.RightTouchValue != 2 && !level.RightTouchImpairmentNotDueToSci) || (level.RightPrickValue != 2 && !level.RightPrickImpairmentNotDueToSci))) { totals.AddRightSensoryValue(level.Previous); if ("S4_5".Equals(level.Name) && (level.RightTouchValue == 2 || NtRegex.IsMatch(level.RightTouchName)) && (level.RightPrickValue == 2 || NtRegex.IsMatch(level.RightPrickName))) { totals.AddRightSensoryValue(level); if (totals.NeurologicalLevelOfInjuryHasOnlySoftValues) totals.AddNeurologicalLevelOfInjury(level); } if (totals.NeurologicalLevelOfInjuryHasOnlySoftValues) totals.AddNeurologicalLevelOfInjury(level.Previous); if ((level.RightTouchValue != 2 && !NtRegex.IsMatch(level.RightTouchName)) || (level.RightPrickValue != 2 && !NtRegex.IsMatch(level.RightPrickName))) { totals.RightSensoryHasOnlySoftValues = false; totals.NeurologicalLevelOfInjuryHasOnlySoftValues = false; } if (level.IsKeyMuscle) { nextNonKeyMuscleShouldBeRightMotor = true; totals.HasRightCollins = true; } } if (totals.LeftSensoryHasOnlySoftValues && ((level.LeftTouchValue != 2 && !level.LeftTouchImpairmentNotDueToSci) || (level.LeftPrickValue != 2 && !level.LeftPrickImpairmentNotDueToSci))) { totals.AddLeftSensoryValue(level.Previous); if ("S4_5".Equals(level.Name) && (level.LeftTouchValue == 2 || NtRegex.IsMatch(level.LeftTouchName)) && (level.LeftPrickValue == 2 || NtRegex.IsMatch(level.LeftPrickName))) { totals.AddLeftSensoryValue(level); if (totals.NeurologicalLevelOfInjuryHasOnlySoftValues) totals.AddNeurologicalLevelOfInjury(level); } if (totals.NeurologicalLevelOfInjuryHasOnlySoftValues) totals.AddNeurologicalLevelOfInjury(level.Previous); if ((level.LeftTouchValue != 2 && !NtRegex.IsMatch(level.LeftTouchName)) || (level.LeftPrickValue != 2 && !NtRegex.IsMatch(level.LeftPrickName))) { totals.LeftSensoryHasOnlySoftValues = false; totals.NeurologicalLevelOfInjuryHasOnlySoftValues = false; } if (level.IsKeyMuscle) { nextNonKeyMuscleShouldBeLeftMotor = true; totals.HasLeftCollins = true; } } if (totals.RightMotorHasOnlySoftValues && level.RightMotorValue != 5 && !level.RightMotorImpairmentNotDueToSci) { if (level.IsKeyMuscle && (level.RightMotorValue >= 3 || NtRegex.IsMatch(level.RightMotorName))) { totals.AddRightMotorValue(level); // Check if left won't make the NLI have to be the previous level. // Let the logic for left motor handle the SNL instead if (totals.NeurologicalLevelOfInjuryHasOnlySoftValues && (level.LeftMotorValue > 2 || level.LeftMotorImpairmentNotDueToSci || NtRegex.IsMatch(level.LeftMotorName))) { totals.AddNeurologicalLevelOfInjury(level); if (!NtRegex.IsMatch(level.RightMotorName)) totals.NeurologicalLevelOfInjuryHasOnlySoftValues = false; } } if (level.RightMotorValue < 3 || NtRegex.IsMatch(level.RightMotorName)) { totals.AddRightMotorValue(level.Previous); if (totals.NeurologicalLevelOfInjuryHasOnlySoftValues) { totals.AddNeurologicalLevelOfInjury(level.Previous); if (!NtRegex.IsMatch(level.RightMotorName)) totals.NeurologicalLevelOfInjuryHasOnlySoftValues = false; } } if (!NtRegex.IsMatch(level.RightMotorName)) totals.RightMotorHasOnlySoftValues = false; } if (totals.LeftMotorHasOnlySoftValues && level.LeftMotorValue != 5 && !level.LeftMotorImpairmentNotDueToSci) { if (level.IsKeyMuscle && (level.LeftMotorValue >= 3 || NtRegex.IsMatch(level.LeftMotorName))) { totals.AddLeftMotorValue(level); if (totals.NeurologicalLevelOfInjuryHasOnlySoftValues) totals.AddNeurologicalLevelOfInjury(level); } if (level.LeftMotorValue < 3 || NtRegex.IsMatch(level.LeftMotorName)) { totals.AddLeftMotorValue(level.Previous); if (totals.NeurologicalLevelOfInjuryHasOnlySoftValues) totals.AddNeurologicalLevelOfInjury(level.Previous); } if (!NtRegex.IsMatch(level.LeftMotorName)) { totals.LeftMotorHasOnlySoftValues = false; totals.NeurologicalLevelOfInjuryHasOnlySoftValues = false; } } /* -- RECURSIVE CALL --------------- */ if (level.Next != null) UpdateTotalsWithLevelAt(neurologyForm, totals, level.Next, nextNonKeyMuscleShouldBeRightMotor && totals.RightMotorHasOnlySoftValues, nextNonKeyMuscleShouldBeLeftMotor && totals.LeftMotorHasOnlySoftValues); #region This happens when there are INTACT values ------------------------------------------- if ("S4_5".Equals(level.Name)) { if (totals.RightSensoryHasOnlySoftValues && totals.LeftSensoryHasOnlySoftValues && totals.RightMotorHasOnlySoftValues && totals.LeftMotorHasOnlySoftValues) totals.AddNeurologicalLevelOfInjury(level); if (totals.RightSensoryHasOnlySoftValues) { totals.AddRightSensoryValue(level); totals.RightSensoryHasOnlySoftValues = false; } if (totals.LeftSensoryHasOnlySoftValues) { totals.AddLeftSensoryValue(level); totals.LeftSensoryHasOnlySoftValues = false; } if (totals.RightMotorHasOnlySoftValues) { totals.AddRightMotorValue(level); totals.RightMotorHasOnlySoftValues = false; } if (totals.LeftMotorHasOnlySoftValues) { totals.AddLeftMotorValue(level); totals.LeftMotorHasOnlySoftValues = false; } } #endregion if (totals.RightSensoryZppHasOnlySoftValues && (!"0".Equals(level.RightTouchName) || !"0".Equals(level.RightPrickName))) { if ((level.RightTouchValue > 0 || level.RightTouchImpairmentNotDueToSci) || (level.RightPrickValue > 0 || level.RightPrickImpairmentNotDueToSci)) totals.RightSensoryZppHasOnlySoftValues = false; totals.AddRightSensoryZppValue(level); } if (totals.LeftSensoryZppHasOnlySoftValues && (!"0".Equals(level.LeftTouchName) || !"0".Equals(level.LeftPrickName))) { if ((level.LeftTouchValue > 0 || level.LeftTouchImpairmentNotDueToSci) || (level.LeftPrickValue > 0 || level.LeftPrickImpairmentNotDueToSci)) totals.LeftSensoryZppHasOnlySoftValues = false; totals.AddLeftSensoryZppValue(level); } if (totals.RightMotorZppHasOnlySoftValues && (level.HasOtherRightMotorFunction || (!"0".Equals(level.RightMotorName) && (level.IsKeyMuscle || totals.RightMotorContains(level.Name))))) { if ((level.RightMotorImpairmentNotDueToSci || level.HasOtherRightMotorFunction || !NtRegex.IsMatch(level.RightMotorName)) && (level.IsKeyMuscle || level.Ordinal < 4 || (level.Ordinal > 25 && !totals.RightUpperMotorContainsNt && !totals.RightLowerMotorContainsNt && !totals.HasRightCollins) || (level.Ordinal > 8 && level.Ordinal < 21 && !totals.RightUpperMotorContainsNt))) totals.RightMotorZppHasOnlySoftValues = false; totals.AddRightMotorZppValue(level); } if (totals.LeftMotorZppHasOnlySoftValues && (level.HasOtherLeftMotorFunction || (!"0".Equals(level.LeftMotorName) && (level.IsKeyMuscle || totals.LeftMotorContains(level.Name))))) { if ((level.LeftMotorImpairmentNotDueToSci || level.HasOtherLeftMotorFunction || !NtRegex.IsMatch(level.LeftMotorName)) && (level.IsKeyMuscle || level.Ordinal < 4 || (level.Ordinal > 25 && !totals.LeftUpperMotorContainsNt && !totals.LeftLowerMotorContainsNt && !totals.HasLeftCollins) || (level.Ordinal > 8 && level.Ordinal < 21 && !totals.LeftUpperMotorContainsNt))) totals.LeftMotorZppHasOnlySoftValues = false; totals.AddLeftMotorZppValue(level); } // Update most Rostral levels with motor function if ((level.IsKeyMuscle || level.HasOtherRightMotorFunction) && totals.MostRostralRightLevelWithMotorFunction == null && (level.RightMotorImpairmentNotDueToSci || level.HasOtherRightMotorFunction || (level.RightMotorValue != 0 && level.IsKeyMuscle))) totals.MostRostralRightLevelWithMotorFunction = level; if ((level.IsKeyMuscle || level.HasOtherLeftMotorFunction) && totals.MostRostralLeftLevelWithMotorFunction == null && (level.LeftMotorImpairmentNotDueToSci || level.HasOtherLeftMotorFunction || (level.LeftMotorValue != 0 && level.IsKeyMuscle))) totals.MostRostralLeftLevelWithMotorFunction = level; // Update most Caudal levels with motor function if ((level.IsKeyMuscle || level.HasOtherRightMotorFunction) && totals.MostCaudalRightLevelWithMotorFunction == null && (!"0".Equals(level.RightMotorName) || level.HasOtherRightMotorFunction)) totals.MostCaudalRightLevelWithMotorFunction = level; if ((level.IsKeyMuscle || level.HasOtherLeftMotorFunction) && totals.MostCaudalLeftLevelWithMotorFunction == null && (!"0".Equals(level.LeftMotorName) || level.HasOtherLeftMotorFunction)) totals.MostCaudalLeftLevelWithMotorFunction = level; if (!level.IsKeyMuscle) return; if (level.IsLowerMuscle) { totals.RightLowerMotorTotal += level.RightMotorValue; totals.LeftLowerMotorTotal += level.LeftMotorValue; } else { totals.RightUpperMotorTotal += level.RightMotorValue; totals.LeftUpperMotorTotal += level.LeftMotorValue; } }
/// <summary> /// Compares two neurology levels based on property "Ordinal". /// </summary> /// <param name="a">Neurology form level A</param> /// <param name="b">Neurology form level B</param> /// <returns> /// Returns /// – 1 if a is more caudal (the ordinal of a is greater than the one of b) /// – 0 if both ordinal values are the same /// – -1 if b is more caudal (the ordinal of b is greater than the one of a). /// </returns> private static int CompareNeurologyFormTotalsLevelByOrdinal(NeurologyFormLevel a, NeurologyFormLevel b) { // Both are null so they are equal // OR // a is null and b is not so b is greater if (a == null) return b == null ? 0 : -1; // b is null and a is not so a is greater if (b == null) return 1; return a.Ordinal > b.Ordinal ? 1 : a.Ordinal == b.Ordinal ? 0 : -1; }