Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        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));
        }
Пример #6
0
        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));
        }
Пример #7
0
        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));
        }