// Use regular expressions to determine the type of the metric public void DetermineMetricType() { // Parse the objective if (!String.IsNullOrEmpty(DVHObjective)) { var testMatch = objectiveDictionary.Where(x => x.Key.IsMatch(DVHObjective)); if (testMatch.Count() == 1) { // Found a match for a known objective type. var match = testMatch.First().Key.Matches(DVHObjective)[0]; DVHType = testMatch.First().Value; DVHEvalUnit = match.Groups["evalunit"].Value; DVHEvalPt = match.Groups["evalpt"].Value; DVHUnit = match.Groups["unit"].Value; Console.WriteLine("expression {0} => type = {1}, evalPoint = {2}, unit = {3}, evalUnit = {4}", DVHObjective, DVHType, DVHEvalPt, DVHUnit, DVHEvalUnit); // Fix case if needed. List <string> fixcase = new List <string> { "cGy", "Gy", "cc", "%" }; DVHEvalUnit = fixcase.Where(x => x.ToUpper().CompareTo(DVHEvalUnit.ToUpper()) == 0).FirstOrDefault(); DVHUnit = fixcase.Where(x => x.ToUpper().CompareTo(DVHUnit.ToUpper()) == 0).FirstOrDefault(); } } // Parse the Evaluator string eval_pattern = @"^(?<type><|<=|=|>=|>)(?<goal>\d+\p{P}\d+|\d+)$"; if (!String.IsNullOrEmpty(Evaluator)) //Variables remain null if empty { var matches = Regex.Matches(Evaluator, eval_pattern); if (matches.Count == 1) { DVHEvalValue = matches[0].Groups["goal"].ToString(); DVHEvalType = matches[0].Groups["type"].ToString(); } else //If no match, set to not recognized { DVHEvalValue = "Not recognized"; DVHEvalType = "Not recognized"; } } // Parse the Variation string variation_pattern = @"^(\d+\p{P}\d+|\d+)$"; if (!String.IsNullOrEmpty(Variation)) //Variables remain null if empty or no match { var matches = Regex.Matches(Variation, variation_pattern); if (matches.Count == 1) { DVHVariation = matches[0].Value; } else { DVHVariation = "Not recognized"; } } }
// Evaluate min, mean, or max. private string EvaluateMinMaxMean(Structure evalStructure, PlanningItem plan, ref List <string> warnings, string type) { string achieved; // Compute different value based on Min / Max / Mean DoseValue dose; DoseValuePresentation dvp = (DVHEvalUnit.CompareTo("%") == 0 && plan.GetType().Name != "PlanSum") ? DoseValuePresentation.Relative : DoseValuePresentation.Absolute; switch (type) { case "Min": dose = plan.GetDVHCumulativeData(evalStructure, dvp, VolumePresentation.Relative, 0.1).MinDose; break; case "Max": dose = plan.GetDVHCumulativeData(evalStructure, dvp, VolumePresentation.Relative, 0.1).MaxDose; break; case "Mean": dose = plan.GetDVHCumulativeData(evalStructure, dvp, VolumePresentation.Relative, 0.1).MeanDose; break; default: return("Not supported"); } // Checking dose output unit and adapting to template if ((DVHEvalUnit.CompareTo("Gy") == 0) && (dose.Unit.CompareTo(DoseValue.DoseUnit.cGy) == 0)) //Gy to cGy { achieved = new DoseValue(dose.Dose / 100, DoseValue.DoseUnit.Gy).ToString(); } else //Gy to Gy or % to % { if (plan is PlanSum && DVHEvalUnit.CompareTo("%") == 0) { warnings.Add("Relative dose changed to Gy."); if ((dose.Unit.CompareTo(DoseValue.DoseUnit.cGy) == 0)) { //this is valid for V15 because we should return Gy if the user wants the value in Gy. achieved = new DoseValue(dose.Dose / 100, DoseValue.DoseUnit.Gy).ToString(); } else { achieved = dose.ToString(); } } else { achieved = dose.ToString(); } } return(achieved); }
// Evaluate covered volume at dose. private string EvaluateCoveredVolumeAtDose(Structure evalStructure, PlanningItem plan, ref List <string> warnings) { // Covered Volume at Dose DVxGy is equivalent to V_tot - VxGy double Vtot = evalStructure.Volume; StructureObjective tmp = new StructureObjective() { DVHUnit = DVHUnit, DVHEvalPt = DVHEvalPt, DVHEvalUnit = DVHEvalUnit }; string achieved = tmp.EvaluateVolumeAtDose(evalStructure, plan, ref warnings); if (string.IsNullOrEmpty(achieved)) { return(achieved); } double achievedDouble = double.Parse(Regex.Match(achieved, @"^\d*\.?\d*").ToString()); achievedDouble = (DVHEvalUnit.CompareTo("cc") == 0) ? Vtot - achievedDouble : 100 - achievedDouble; achieved = string.Format("{0:0.00} {1}", achievedDouble, DVHEvalUnit); return(achieved); }
// Calculate Volume at Dose private string EvaluateVolumeAtDose(Structure evalStructure, PlanningItem plan, ref List <string> warnings) { string achieved; // Plan sums don't support relative dose. if (plan is PlanSum && DVHUnit.CompareTo("%") == 0) { warnings.Add("Relative dose not supported for plan sums."); return(""); } // Determine Units DoseValue.DoseUnit du = (DVHUnit.CompareTo("%") == 0) ? DoseValue.DoseUnit.Percent : (DVHUnit.CompareTo("Gy") == 0) ? DoseValue.DoseUnit.Gy : (DVHUnit.CompareTo("cGy") == 0) ? DoseValue.DoseUnit.cGy : DoseValue.DoseUnit.Unknown; string doseunit = (plan is PlanSum) ? (plan as PlanSum).PlanSetups.First().DosePerFraction.UnitAsString : (plan as PlanSetup).DosePerFraction.UnitAsString; // If plan sum and relative dose then convert to Gy if (plan is PlanSum && DVHUnit.CompareTo("%") == 0) { du = DoseValue.DoseUnit.Gy; } // For version 15, we must handle all doses in the unit they are supposed to be presented in. double dose_value = double.Parse(DVHEvalPt); if (du.ToString() == "Gy" && doseunit == "cGy") { dose_value = dose_value * 100; du = DoseValue.DoseUnit.cGy; } else if (du.ToString() == "cGy" && doseunit == "Gy") { dose_value = dose_value / 100; du = DoseValue.DoseUnit.Gy; } // Calculate results DoseValue dv = new DoseValue(dose_value, du); VolumePresentation vpFinal = (DVHEvalUnit.CompareTo("%") == 0) ? VolumePresentation.Relative : VolumePresentation.AbsoluteCm3; double volumeAchieved = plan.GetVolumeAtDose(evalStructure, dv, vpFinal); // Check if dose is undefined if (double.IsNaN(volumeAchieved)) { // Check for sufficient sampling and dose coverage DVHData dvh = plan.GetDVHCumulativeData(evalStructure, DoseValuePresentation.Absolute, VolumePresentation.Relative, 0.1); if (dvh.SamplingCoverage < 0.9) { warnings.Add("Insufficient sampling coverage."); } if (dvh.Coverage < 1.0) { warnings.Add("Insufficient dose coverage."); } if (warnings.Count == 0) { warnings.Add("Dose value undefined."); } return(""); } achieved = string.Format("{0:0.00} {1}", volumeAchieved, DVHEvalUnit); return(achieved); }
///////////////////////////////// // Evaluation helper functions // ///////////////////////////////// // Calculate the dose at volume private string EvaluateDoseAtVolume(Structure evalStructure, PlanningItem plan, ref List <string> warnings) { string achieved; // Calculate results VolumePresentation vp = (DVHUnit == "%") ? VolumePresentation.Relative : VolumePresentation.AbsoluteCm3; double volume = double.Parse(DVHEvalPt); DoseValuePresentation dvpFinal = (DVHEvalUnit == "%" && plan.GetType().Name != "PlanSum") ? DoseValuePresentation.Relative : DoseValuePresentation.Absolute; DoseValue dvAchieved = plan.GetDoseAtVolume(evalStructure, volume, vp, dvpFinal); // Check if dose is undefined if (dvAchieved.IsUndefined()) { // Check for sufficient sampling and dose coverage DVHData dvh = plan.GetDVHCumulativeData(evalStructure, DoseValuePresentation.Absolute, VolumePresentation.Relative, 0.1); if (dvh.SamplingCoverage < 0.9) { warnings.Add("Insufficient sampling coverage."); } if (dvh.Coverage < 1.0) { warnings.Add("Insufficient dose coverage."); } if (warnings.Count == 0) { warnings.Add("Dose value undefined."); } return(""); } // Check dose output unit and adapting to template if (dvAchieved.UnitAsString.CompareTo(DVHEvalUnit.ToString()) != 0) { // Convert the acheived dose value to Gy because it wants Gy units. if ((DVHEvalUnit.CompareTo("Gy") == 0) && (dvAchieved.Unit.CompareTo(DoseValue.DoseUnit.cGy) == 0)) { //this is valid for V15 because we should return Gy if the user wants the value in Gy. dvAchieved = new DoseValue(dvAchieved.Dose / 100, DoseValue.DoseUnit.Gy); } else { if (plan.GetType().Name == "PlanSum" && DVHEvalUnit.CompareTo("%") == 0) { if ((DVHEvalUnit.CompareTo("%") == 0) && (dvAchieved.Unit.CompareTo(DoseValue.DoseUnit.cGy) == 0)) { //this is valid for V15 because we should return Gy if the user wants the value in Gy. dvAchieved = new DoseValue(dvAchieved.Dose / 100, DoseValue.DoseUnit.Gy); } } else { throw new ApplicationException("Internal error: Inside else loop"); } } } // Return result achieved = !dvAchieved.IsUndefined() ? dvAchieved.ToString() : ""; if (plan is PlanSum && DVHEvalUnit.CompareTo("%") == 0) { warnings.Add("Relative dose changed to Gy."); } return(achieved); }