public static List <List <double> > Get_ROI_Distances(HNPlan plan, List <string> roi_list, List <string> ptv_list, ScriptContext context) { List <List <double> > distance_list = new List <List <double> >(); //This list is to contain a list for each roi, each having a distance value from each ptv in ptv_list. (minimum distance) ROI roi; ROI ptv; for (int r = 0; r < roi_list.Count; r++) { distance_list.Add(new List <double>()); for (int p = 0; p < ptv_list.Count; p++) { string roi_name = roi_list[r]; string ptv_name = ptv_list[p]; roi = plan.ROI_Dict[roi_name]; ptv = plan.ROI_Dict[ptv_name]; if ((roi.MatchingStructures.Count == 0) || (ptv.MatchingStructures.Count == 0)) //If the plan doesn't have either one of the roi or ptv { distance_list[r].Add((double)1000); continue; } //Now get distance between the roi and ptv (minimum) and add this value to the list double distance = Structure_Distance(roi, ptv, context); distance_list[r].Add(distance); } } return(distance_list); }
public static List <double> Predict_Score(HNPlan plan, ScriptContext context) { List <string> roi_list = new List <string>() { "Brain Stem", "Laryngo-pharynx", "Mandible", "Oral Cavity", "Left Parotid", "Right Parotid", "Spinal Cord", "Right Submandibular", "Left Submandibular" }; List <string> ptv_list = new List <string>() { "PTV 70", "PTV 63", "PTV 56" }; List <double> scores = new List <double>(); List <List <double> > distances = ROI_Distances.Get_ROI_Distances(plan, roi_list, ptv_list, context); return(scores); }
public static List <string> UpdateConstraints(ref ExternalPlanSetup plan, ref StructureSet ss, ref HNPlan hnPlan, ScriptContext context, List <List <Structure> > optimizedStructures, List <List <Structure> > matchingStructures, int numCycles) { List <string> log = new List <string>(); log.Add("<p>"); if (numCycles == 1) { log.Add("Preliminary Optimization Iteration Update Log: <br>"); } else { log.Add("Full VMAT Optimization Update: <br>"); } //Go through all plan types and check all constraints. PlanSetup p = context.PlanSetup; p.DoseValuePresentation = DoseValuePresentation.Absolute; double prescriptionDose = p.TotalDose.Dose; List <ROI> ROIs = hnPlan.ROIs; for (int s = 0; s < hnPlan.ROIs.Count; s++) //Gothrough all the different constrained structures { for (int match = 0; match < matchingStructures[s].Count; match++) //FOr each structure in ss that matches the hnplan structure { for (int i = 0; i < ROIs[s].Constraints.Count; i++) //first go one by one through the constraints. { //Get DVH data for structure: DVHData dvhData = p.GetDVHCumulativeData(matchingStructures[s][match], DoseValuePresentation.Absolute, VolumePresentation.AbsoluteCm3, 0.01); //Get type of constraint string type = ROIs[s].Constraints[i].Type; string subscript = ROIs[s].Constraints[i].Subscript; string relation = ROIs[s].Constraints[i].EqualityType; double value = ROIs[s].Constraints[i].Value; string format = ROIs[s].Constraints[i].Format; int priority = ROIs[s].Constraints[i].Priority; int priorityLower = ROIs[s].Constraints[i].PriorityRange[0]; int priorityUpper = ROIs[s].Constraints[i].PriorityRange[1]; if (type.ToLower() == "d")//now subscript can be mean, max, min, median? { try { double sub = Convert.ToInt32(subscript); //need to analyze DVH data if a number. VolumePresentation vp = VolumePresentation.AbsoluteCm3; DoseValuePresentation dp = new DoseValuePresentation(); dp = DoseValuePresentation.Absolute; double volume = matchingStructures[s][match].Volume; if (format.ToLower() == "rel") { sub = volume * sub / 100; value *= prescriptionDose / 100; } double doseQuant = p.GetDoseAtVolume(matchingStructures[s][match], sub, vp, dp).Dose; if (p.GetDoseAtVolume(matchingStructures[s][match], sub, vp, dp).Unit == DoseValue.DoseUnit.Gy) //convert to cGy if necessary { doseQuant *= 100; } //now check the inequality: if (relation == "<") { if (doseQuant < value) { //If an OAR, loosen priority if its satisfied by over 7Gy if ((ROIs[s].Type == "OAR") && (value - doseQuant > 1000)) { priority = (int)(priority * 0.8); //Make sure the priority is within the priority range: priority = Math.Min(priorityUpper, priority); priority = Math.Max(priorityLower, priority); hnPlan.ROIs[s].Constraints[i].Priority = priority; log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + " SATISFIED. Dose (" + doseQuant.ToString() + "cGy) not within 10Gy of constraint - adjusted priority from " + string.Format("{0}", priority) + " to " + ((int)(priority * 0.8)).ToString() + "."); } else { log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + " SATISFIED. Dose (" + doseQuant.ToString() + "cGy). Unadjusted."); } } else { //By what percentage is the constraint being missed by (as ratio)? double percentageOff = 1 + (doseQuant - value) / value; int newPriority = Math.Max((int)(priority * percentageOff), priority + 10); newPriority = Math.Min(priorityUpper, newPriority); newPriority = Math.Max(priorityLower, newPriority); hnPlan.ROIs[s].Constraints[i].Priority = newPriority; log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + " FAILED- Updating priority from " + string.Format("{0}", priority) + " to " + string.Format("{0}", (int)(newPriority))); } } else if (relation == ">") { if (doseQuant > value) { log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + " SATISFIED Dose (" + doseQuant.ToString() + "cGy). Unadjusted."); } else { //By what percentage is the constraint being missed by (as ratio)? double percentageOff = 1 - (doseQuant - value) / value; //minus because its negative numerator int newPriority = Math.Max((int)(priority * percentageOff), priority + 10); newPriority = Math.Min(priorityUpper, newPriority); newPriority = Math.Max(priorityLower, newPriority); hnPlan.ROIs[s].Constraints[i].Priority = newPriority; log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + " FAILED. Updating priority from " + string.Format("{0}", priority) + " to " + string.Format("{0}", newPriority)); } } else { log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + "- Could not understand the relation given in the constraint."); } } catch //mean median... { double dose = 0; if (subscript.ToLower() == "mean") { dose = dvhData.MeanDose.Dose; } else if (subscript.ToLower() == "max") { dose = dvhData.MaxDose.Dose; } else if (subscript.ToLower() == "median") { dose = dvhData.MedianDose.Dose; } else if (subscript.ToLower() == "min") { dose = dvhData.MinDose.Dose; } else { log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + "- Could not understand the relation given in the constraint. "); break; } if (dvhData.MeanDose.Unit == DoseValue.DoseUnit.Gy) //convert to gy if necessary { dose *= 100; } if (format.ToLower() == "rel") { value *= prescriptionDose / 100; } //Now check the relation if (relation == "<") { if (dose < value) { if ((ROIs[s].Type == "OAR") && (value - dose > 1000)) { log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + " SATISFIED by over 10Gy. Decreasing priority to " + string.Format("{0}", (int)(priority * 0.8))); priority = (int)(priority * 0.8); priority = Math.Min(priorityUpper, priority); priority = Math.Max(priorityLower, priority); hnPlan.ROIs[s].Constraints[i].Priority = priority; } else { log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + " SATISFIED. Unadjusted"); } } else { //By what percentage is the constraint being missed by (as ratio)? double percentageOff = 1 + (dose - value) / value; int newPriority = Math.Max((int)(priority * percentageOff), priority + 10); //Also don't want to increase priority by more than 20 at a time: newPriority = Math.Min(newPriority, priority + 20); if ((ROIs[s].Type == "OAR") && (ROIs[s].Critical == false)) { newPriority = Math.Min(newPriority, 70); } if (dose - value > 2000) //if constraint is failing miserably, stop trying { newPriority = 0; log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + " Failed by more than 20Gy. Deleting constraint."); hnPlan.ROIs[s].Constraints[i].Priority = newPriority; } else { log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + " Failed. Updating priority from " + string.Format("{0}", priority) + " to " + string.Format("{0}", (int)(priority * 1.1))); newPriority = Math.Min(priorityUpper, newPriority); newPriority = Math.Max(priorityLower, newPriority); hnPlan.ROIs[s].Constraints[i].Priority = newPriority; } } } else if (relation == ">") { if (dose > value) { log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + " SATISFIED. Unadjusted."); } else { //By what percentage is the constraint being missed by (as ratio)? double percentageOff = 1 - (dose - value) / value; //negative because negative numerator int newPriority = Math.Max((int)(priority * percentageOff), priority + 10); newPriority = Math.Min(priorityUpper, newPriority); newPriority = Math.Max(priorityLower, newPriority); log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + " Failed. Updating priority from " + string.Format("{0}", priority) + " to " + string.Format("{0}", newPriority)); hnPlan.ROIs[s].Constraints[i].Priority = newPriority; } } else { log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + "-Could not understand the relation given in the constraint."); } } } else if (type == "V") { try { double sub = Convert.ToDouble(subscript); //need to analyze DVH data if a number. double frac = prescriptionDose; //ad hoc fix for ptv string output VolumePresentation vp = VolumePresentation.Relative; double volume = matchingStructures[s][match].Volume; if (format.ToLower() == "abs") { value = (value / volume) * 100; sub = Convert.ToDouble(subscript); } //But if PTV, then this is not relative to the prescription dose. if (ROIs[s].Name.ToLower().Contains("ptv")) { frac = StringOperations.FindPTVNumber(ROIs[s].Name.ToLower()); sub = Convert.ToDouble(subscript) * frac / 100; //frac in Gy and subscript percentage, so factor of 100 cancels out vp = VolumePresentation.Relative; } DoseValue dose = new DoseValue(sub, "cGy"); //Need dose in cGy for calculation: double volumeQuant = p.GetVolumeAtDose(matchingStructures[s][match], dose, vp); //Now check the inequality: if (relation == "<") { if (volumeQuant < value) { log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + " SATISFIED."); } else { //By what percentage is the constraint being missed by (as ratio)? double percentageOff = 1 + (volumeQuant - value) / value; int newPriority = Math.Max((int)(priority * percentageOff), priority + 10); //Also don't want to adjust any constraint by more than 20 at a time: newPriority = Math.Min(newPriority, priority + 20); newPriority = Math.Min(priorityUpper, newPriority); newPriority = Math.Max(priorityLower, newPriority); hnPlan.ROIs[s].Constraints[i].Priority = newPriority; log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + " Failed. Updating priority from" + string.Format("{0}", priority) + " to " + string.Format("{0}", newPriority)); } } else if (relation == ">") { if (volumeQuant > value) { log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + " SATISFIED."); } else { double percentageOff = 1 - (volumeQuant - value) / value; int newPriority = Math.Max((int)(priority * percentageOff), priority + 10); newPriority = Math.Min(priorityUpper, newPriority); newPriority = Math.Max(priorityLower, newPriority); hnPlan.ROIs[s].Constraints[i].Priority = newPriority; log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + " Failed. Updating priority from" + string.Format("{0}", priority) + " to " + string.Format("{0}", newPriority)); } } else { log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + "-Could not understand the relation given in the constraint."); } } catch { log.Add(ROIs[s].Name + ": Constraint " + (i + 1).ToString() + "-Could not understand the relation given in the constraint."); } } } } log.Add("</p>"); } //Now need to delete and reset all constraints OptObjectivesEditing.SetConstraints(ref plan, hnPlan, optimizedStructures); return(log); }
public static List <List <Structure> > SetConstraints(ref ExternalPlanSetup plan, HNPlan hnPlan, List <List <Structure> > matchingStructures, bool checkOptis = false) { StructureSet ss = plan.StructureSet; //Will be checking if opti structures need to be made. If so, they will be created and used for optimization. So we need a new matching list //which contains structures (opti or not) that are actually used during optimization. List <List <Structure> > optimizedStructures = new List <List <Structure> >(); if (!checkOptis) { optimizedStructures = new List <List <Structure> >(matchingStructures); for (int i = 0; i < hnPlan.ROIs.Count; i++) { hnPlan.ROIs[i].OptimizationStructures = new List <Structure>(hnPlan.ROIs[i].MatchingStructures); } return(optimizedStructures); } //Need to set all optimization constraints now. First clear all the current constraints foreach (var objective in plan.OptimizationSetup.Objectives.OfType <OptimizationPointObjective>()) { plan.OptimizationSetup.RemoveObjective(objective); } foreach (var objective in plan.OptimizationSetup.Objectives.OfType <OptimizationMeanDoseObjective>()) { plan.OptimizationSetup.RemoveObjective(objective); } //Now loop over all constraints and set them for (int i = 0; i < hnPlan.ROIs.Count; i++) //Loop over all structures { if (checkOptis) { hnPlan.ROIs[i].OptimizationStructures = new List <Structure>(); optimizedStructures.Add(new List <Structure>()); } for (int match = 0; match < matchingStructures[i].Count; match++) { //Here I want to make sure that the matched structure does not overlap with PTVs, and if it does I want to make an opti structure. if (checkOptis) { if (!hnPlan.ROIs[i].Critical) { Structure opti = CheckOverlap_OptiMaker(matchingStructures[i][match], ref ss, false); optimizedStructures[i].Add(opti); hnPlan.ROIs[i].OptimizationStructures.Add(opti); } else { Structure opti = CheckOverlap_OptiMaker(matchingStructures[i][match], ref ss, true); optimizedStructures[i].Add(opti); hnPlan.ROIs[i].OptimizationStructures.Add(opti); } } if (hnPlan.ROIs[i].OptimizationStructures[match].Volume < 0.5) { continue; } for (int j = 0; j < hnPlan.ROIs[i].Constraints.Count; j++) //Loop over all constraints for the current structure { plan.OptimizationSetup.AddNormalTissueObjective(80.0f, 0.0f, 100.0f, 40.0f, 0.05f); string type = hnPlan.ROIs[i].Constraints[j].Type; string subscript = hnPlan.ROIs[i].Constraints[j].Subscript; string relation = hnPlan.ROIs[i].Constraints[j].EqualityType; double value = hnPlan.ROIs[i].Constraints[j].Value; string format = hnPlan.ROIs[i].Constraints[j].Format; double volume = hnPlan.ROIs[i].OptimizationStructures[match].Volume; OptimizationObjectiveOperator constraintType; if (relation == "<") { constraintType = OptimizationObjectiveOperator.Upper; } else { constraintType = OptimizationObjectiveOperator.Lower; } if (type.ToLower() == "d") //if a dose constraint { try //subscript is a number { volume = Convert.ToInt32(subscript); //need to analyze DVH data if a number. //convert to cGy (90% of maximum for optimization) plan.OptimizationSetup.AddPointObjective(hnPlan.ROIs[i].OptimizationStructures[match], constraintType, new DoseValue(value, "cGy"), volume, hnPlan.ROIs[i].Constraints[j].Priority); } catch //is a mean or max restriction { if (subscript.ToLower() == "mean") { double dose = value * 0.9; //take 90 percent of dose constraint dose to start OptimizationObjective objective = plan.OptimizationSetup.AddMeanDoseObjective(hnPlan.ROIs[i].OptimizationStructures[match], new DoseValue(dose, "cGy"), hnPlan.ROIs[i].Constraints[j].Priority); //update subsegment constraints if organ is subsegmented if (hnPlan.ROIs[i].HasSubsegments) { //replace whole organ constraint with subsegment constraints //plan.OptimizationSetup.RemoveObjective(objective); //uncomment if don't also want the whole organ constraint foreach (Structure structure in ss.Structures) { if ((structure.Name.Contains(hnPlan.ROIs[i].OptimizationStructures[match].Name.Substring(0, 5))) && (structure.Name.ToLower().Contains("subseg"))) { plan.OptimizationSetup.AddMeanDoseObjective(structure, new DoseValue(dose, "cGy"), hnPlan.ROIs[i].Constraints[j].Priority); } } } } else if (subscript.ToLower() == "max") { double dose = value * 0.9; //take 90 percent of constraint dose to start if (hnPlan.ROIs[i].IsPTV) //if ptv, go halfway between the max dose and prescription dose { dose = (value + (double)hnPlan.ROIs[i].PTVDose) * 0.5; } OptimizationObjective objective = plan.OptimizationSetup.AddPointObjective(hnPlan.ROIs[i].OptimizationStructures[match], constraintType, new DoseValue(dose, "cGy"), 0, hnPlan.ROIs[i].Constraints[j].Priority); if (hnPlan.ROIs[i].HasSubsegments) { //replace whole organ constraint with subsegment constraints //plan.OptimizationSetup.RemoveObjective(objective); //uncomment if don't also want the whole organ constraint foreach (Structure structure in ss.Structures) { if ((structure.Name.Contains(hnPlan.ROIs[i].OptimizationStructures[match].Name.Substring(0, 5))) && (structure.Name.Contains("subseg"))) { plan.OptimizationSetup.AddPointObjective(hnPlan.ROIs[i].OptimizationStructures[match], constraintType, new DoseValue(dose, "cGy"), 0, hnPlan.ROIs[i].Constraints[j].Priority); } } } } else if (subscript.ToLower() == "min") { double dose = value * 1.05; //take 110% percent of constraint dose to start OptimizationObjective objective = plan.OptimizationSetup.AddPointObjective(hnPlan.ROIs[i].OptimizationStructures[match], constraintType, new DoseValue(dose, "cGy"), 100, hnPlan.ROIs[i].Constraints[j].Priority); if (hnPlan.ROIs[i].HasSubsegments) { //replace whole organ constraint with subsegment constraints //plan.OptimizationSetup.RemoveObjective(objective); //uncomment if don't also want the whole organ constraint foreach (Structure structure in ss.Structures) { if ((structure.Name.Contains(hnPlan.ROIs[i].OptimizationStructures[match].Name.Substring(0, 5))) && (structure.Name.Contains("subseg"))) { plan.OptimizationSetup.AddPointObjective(hnPlan.ROIs[i].OptimizationStructures[match], constraintType, new DoseValue(dose, "cGy"), 100, hnPlan.ROIs[i].Constraints[j].Priority); } } } } } } else if (type.ToLower() == "v") { try //in case can't parse the subscript into Int32 { if (format.ToLower() == "abs") //I assume here that an absolute volume constraint will always be an upper bound OAR consatraint { double dose = Convert.ToInt32(subscript); //convert to cGy //Need to convert to relative volume. volume = value / volume * 100; volume *= 0.9; //Make it an even harsher constraint if (volume <= 0.2) { volume = 0; } plan.OptimizationSetup.AddPointObjective(hnPlan.ROIs[i].OptimizationStructures[match], constraintType, new DoseValue(dose * 0.95, "cGy"), volume, hnPlan.ROIs[i].Constraints[j].Priority); } else //if relative, will belong to a PTV { double dose = StringOperations.FindPTVNumber(hnPlan.ROIs[i].OptimizationStructures[match].Name.ToLower()) * 100; volume = value; volume = 100; //set to 100 to push the optimizer plan.OptimizationSetup.AddPointObjective(hnPlan.ROIs[i].OptimizationStructures[match], constraintType, new DoseValue(dose, "cGy"), volume, hnPlan.ROIs[i].Constraints[j].Priority); } } catch { } } } } } return(optimizedStructures); }
public static Tuple <List <List <Structure> >, List <List <Structure> >, List <List <string> >, bool> StartOptimizer(ScriptContext context, HNPlan hnPlan, List <List <Structure> > matchingStructures, int numIterations, List <Tuple <bool, double[], string> > features, Tuple <string, string, bool> beamParams) //Returns list of matching structures { // Check for patient plan loaded ExternalPlanSetup plan = context.ExternalPlanSetup; Patient patient = context.Patient; StructureSet ss = context.StructureSet; Course course = context.Course; Image image3d = context.Image; //Create two VMAT beams BeamMaker(ref plan, ss, plan.TotalDose.Dose, beamParams); //set prescriptions dose int numFractions = hnPlan.Fractions; int dosePerFraction = (int)hnPlan.PrescriptionDose / numFractions; plan.SetPrescription(numFractions, new DoseValue(dosePerFraction, "cGy"), 1); //matchingStructures is the same length as hnPlan.ROIs.count //Now set optimization constraints List <List <Structure> > optimizedStructures = OptObjectivesEditing.SetConstraints(ref plan, hnPlan, matchingStructures, true); //true to check for opti structures, returns new matching list of structures List <List <double[, ]> > choppedContours; List <double[]> planes; string contraParName; if (features[0].Item1 == true) //parotid segmentation feature { Tuple <List <List <double[, ]> >, string, List <double[]> > choppedAndName = ParotidChop(ref plan, hnPlan, matchingStructures, ss, context); choppedContours = choppedAndName.Item1; contraParName = choppedAndName.Item2; planes = choppedAndName.Item3; } else { choppedContours = new List <List <double[, ]> >(); contraParName = ""; planes = new List <double[]>(); } Tuple <bool, List <List <string> > > optimData = Optimize(choppedContours, planes, ref plan, ref ss, hnPlan, context, optimizedStructures, matchingStructures, contraParName, numIterations, features, beamParams); bool isPassed = optimData.Item1; List <List <string> > updatesLog = optimData.Item2; return(Tuple.Create(optimizedStructures, matchingStructures, updatesLog, isPassed)); }
public static Tuple <bool, List <List <string> > > Optimize(List <List <double[, ]> > choppedContours, List <double[]> planes, ref ExternalPlanSetup plan, ref StructureSet ss, HNPlan hnPlan, ScriptContext context, List <List <Structure> > optimizedStructures, List <List <Structure> > matchingStructures, string contraName, int numIterations, List <Tuple <bool, double[], string> > features, Tuple <string, string, bool> beamParams) //return a list of strings which is the log of constraint updates during optimization. { //Only make parotid structures if that feature has been selected if (features[0].Item1 == true) { double priorityRatio = features[0].Item2[0]; Segmentation.MakeParotidStructures(choppedContours, planes, ref plan, ref ss, hnPlan, context, matchingStructures, contraName, priorityRatio); } else { //remove previously segmented structures if there foreach (Structure structure in ss.Structures.ToList()) { if (structure.Name.ToLower().Contains("cpg_subseg")) { ss.RemoveStructure(structure); } } } //Now run the first VMAT optimization. plan.SetCalculationModel(CalculationType.PhotonVMATOptimization, "PO_13623"); plan.SetCalculationModel(CalculationType.DVHEstimation, "DVH Estimation Algorithm [15.6.06]"); plan.SetCalculationModel(CalculationType.PhotonVolumeDose, "AAA_13623"); plan.OptimizationSetup.AddNormalTissueObjective(100, 3, 95, 50, 0.2); bool jawTracking = beamParams.Item3; //use jaw tracking if (jawTracking) { try { plan.OptimizationSetup.UseJawTracking = true; } catch { System.Windows.MessageBox.Show("Could not use jaw tracking. Proceeding without."); } } // plan.OptimizeVMAT(); plan.CalculateDose(); string treatmentCenter = beamParams.Item1; string treatmentArea = beamParams.Item2; string mlcId = ""; int areaNum = Int32.Parse(Regex.Match(treatmentArea, @"\d+").Value); if (treatmentCenter == "BC Cancer - Surrey") { switch (areaNum) { case 2: mlcId = ""; break; case 3: mlcId = ""; break; case 4: mlcId = ""; break; case 5: mlcId = ""; break; case 6: mlcId = ""; break; } } else if (treatmentCenter == "BC Cancer - Vancouver") { switch (areaNum) { case 1: mlcId = "1"; break; case 2: mlcId = "HHM0767"; break; case 3: mlcId = ""; break; case 4: mlcId = ""; break; case 5: mlcId = ""; break; case 6: mlcId = "HML0990"; break; case 7: mlcId = "MLC0987"; break; } } string mlcID = "HML0990"; int numCycles = 1; OptimizationOptionsVMAT oov; ; bool isPassed = false; List <List <string> > updateLog = new List <List <string> >(); for (int iter = 0; iter < numIterations; iter++) { //mlcID = plan.Beams.FirstOrDefault<Beam>().MLC.Id; oov = new OptimizationOptionsVMAT(numCycles, mlcID); plan.OptimizeVMAT(oov); plan.CalculateDose(); //Now need to perform a plan check and iteratively adjust constraints based on whether they passed or failed, and whether they passed with flying colours or failed miserably. //Going to find the percentage by which the constraint failed or passed, and adjust both the priority and dose constraint based on this. updateLog.Add(OptObjectivesEditing.UpdateConstraints(ref plan, ref ss, ref hnPlan, context, optimizedStructures, matchingStructures, numCycles)); if (features[0].Item1 == true) { Segmentation.MakeParotidStructures(choppedContours, planes, ref plan, ref ss, hnPlan, context, matchingStructures, contraName, features[0].Item2[0]); } } numCycles = 4; oov = new OptimizationOptionsVMAT(numCycles, mlcID); //Now for a maximum of 3 tries, perform 4-cycle vmat optimization followed by constraint updating until a plan is passed for (int i = 0; i < 3; i++) { plan.OptimizeVMAT(oov); plan.CalculateDose(); updateLog.Add(OptObjectivesEditing.UpdateConstraints(ref plan, ref ss, ref hnPlan, context, optimizedStructures, matchingStructures, numCycles)); if (features[0].Item1 == true) { Segmentation.MakeParotidStructures(choppedContours, planes, ref plan, ref ss, hnPlan, context, matchingStructures, contraName, features[0].Item2[0]); } isPassed = Check.EvaluatePlan(context, hnPlan, matchingStructures, optimizedStructures).Item1; if (isPassed) { break; } } return(Tuple.Create(isPassed, updateLog)); }
public static Tuple <List <List <double[, ]> >, string, List <double[]> > ParotidChop(ref ExternalPlanSetup plan, HNPlan hnPlan, List <List <Structure> > matchingStructures, StructureSet ss, ScriptContext context) { /* * 1. Find contralateral parotid (one with least overlap, largest sum of distance from PTVs), get contours * 2.) split this up into its separate contours * 3. make new structure for each * 4. make constraint for each based on importance */ //1. Structure contraPar = Segmentation.FindContraPar(plan, ss, hnPlan, matchingStructures, context); //Now get contours for it // GetContours function will return the list of contours, as well as a list of all z-planes which contours were taken from, in a tuple var tuple = Segmentation.GetContours(contraPar, context); List <double[, ]> contours = tuple.Item1; List <double[]> planes = tuple.Item2; //2. Now the parotid segmentation! int numCutsZ = 2; int numCutsX = 2; int numCutsY = 1; List <List <double[, ]> > choppedContours = Segmentation.Chop(contours, numCutsX, numCutsY, numCutsZ, contraPar.Name); return(Tuple.Create(choppedContours, contraPar.Name, planes)); }