Пример #1
0
        /// <summary>
        /// Run IMRT optimization for a given plan.
        /// </summary>
        public static void Optimize(ExternalPlanSetup plan)
        {
            plan.SetCalculationModel(CalculationType.PhotonIMRTOptimization, OptimizationAlgorithm);
            var opt = new OptimizationOptionsIMRT(NumberOfIterationsForIMRTOptimization,
                                                  OptimizationOption.RestartOptimization, OptimizationConvergenceOption.TerminateIfConverged, MlcId);

            Trace.WriteLine("\nOptimizing...\n");
            var res = plan.Optimize(opt);

            if (!res.Success)
            {
                var message = string.Format("Optimization failed for plan '{0}'", plan.Id);
                throw new Exception(message);
            }

            plan.SetCalculationModel(CalculationType.PhotonVolumeDose, DoseCalculationAlgorithm);
            plan.SetCalculationModel(CalculationType.PhotonLeafMotions, LeafMotionCalculator);

            Trace.WriteLine("\nCalculating leaf motions...\n");

            var calcRes = plan.CalculateLeafMotions();

            if (!res.Success)
            {
                var message = string.Format("Leaf motion calculation failed for plan '{0}'. Output:\n{1}", plan.Id, calcRes);
                throw new Exception(message);
            }
        }
        // Compute dose
        public void ComputeDose()
        {
            // Set normalization value
            verifPln.PlanNormalizationValue = currPln.PlanNormalizationValue;
            // Set the plan calculation model
            verifPln.SetCalculationModel(CalculationType.PhotonVolumeDose, currPln.PhotonCalculationModel);
            Dictionary <String, String> currPlnCalcModels = currPln.GetCalculationOptions(currPln.PhotonCalculationModel);

            foreach (KeyValuePair <String, String> calcModel in currPlnCalcModels)
            {
                verifPln.SetCalculationOption(currPln.PhotonCalculationModel, calcModel.Key, calcModel.Value);
            }
            // Compute dose
            // For plan containing non-IMRT beams
            if (verifPln.Beams.Any(b => b.MLCPlanType == MLCPlanType.ArcDynamic || b.MLCPlanType == MLCPlanType.Static))
            {
                verifPln.CalculateDose();  // Compute dose for non-IMRT type beams
                // Correct for MU by changing beam weighting
                foreach (Beam verifBm in verifPln.Beams)
                {
                    BeamParameters verifBmParam = verifBm.GetEditableParameters();
                    verifBmParam.WeightFactor = muValues.First(mv => mv.Key == verifBm.Id).Value.Value / verifBm.Meterset.Value;
                    verifBm.ApplyParameters(verifBmParam);
                }
            }
            // For all other IMRT plans
            else
            {
                verifPln.CalculateDoseWithPresetValues(muValues);  // Compute dose for IMRT type beams
            }
        }
Пример #3
0
        public static string calcularMovimientoLaminas(ExternalPlanSetup plan)
        {
            var watch = Stopwatch.StartNew();

            plan.SetCalculationModel(CalculationType.PhotonVolumeDose, Configuracion.DoseCalculationAlgorithm);
            plan.SetCalculationModel(CalculationType.PhotonLeafMotions, Configuracion.LeafMotionCalculator);
            var res = plan.CalculateLeafMotions();

            if (!res.Success)
            {
                return(string.Format("Falló el cálculo de movimiento de láminas para el plan '{0}'. Output:\n{1}", plan.Id, res));
            }
            else
            {
                watch.Stop();
                var elapsedMs = watch.ElapsedMilliseconds;
                return(string.Format("Finalizó el cálculo de movimiento de láminas para el plan '{0}'. Demoró " + elapsedMs.ToString() + "ms", plan.Id));
            }
        }
Пример #4
0
        /// <summary>
        /// Calculate dose for a given plan.
        /// </summary>
        public static void CalculateDose(ExternalPlanSetup plan)
        {
            plan.SetCalculationModel(CalculationType.PhotonVolumeDose, DoseCalculationAlgorithm);
            Trace.WriteLine("\nCalculating dose...\n");
            var res = plan.CalculateDose();

            if (!res.Success)
            {
                var message = string.Format("Dose calculation failed for plan '{0}'. Output:\n{1}", plan.Id, res);
                Trace.WriteLine(message);
            }
        }
Пример #5
0
        /// <summary>
        /// Calculate DVH estimates for a given plan and structure matches.
        /// </summary>
        public static void CalculateDVHEstimates(ExternalPlanSetup plan, Dictionary <string, ModelStructure> structureMatches)
        {
            var prescribedDose            = plan.TotalPrescribedDose;
            var matchedStructures         = structureMatches.ToDictionary(x => x.Key, x => x.Value.ModelId);
            var targetStructureDoseLevels = structureMatches.Where(x => x.Value.StructureType == ModelStructureType.Target).ToDictionary(x => x.Key, x => prescribedDose);

            Trace.WriteLine("\nCalculating DVH estimates...\n");
            plan.SetCalculationModel(CalculationType.DVHEstimation, DVHEstimationAlgorithm);
            var res = plan.CalculateDVHEstimates(DVHEstimationModel, targetStructureDoseLevels, matchedStructures);

            if (!res.Success)
            {
                throw new Exception("DVH estimation failed.");
            }

            Trace.WriteLine("\nDVH estimation succeeded!\n");
        }
Пример #6
0
        public static string calcularDosis(ExternalPlanSetup plan)
        {
            var watch = Stopwatch.StartNew();

            plan.SetCalculationModel(CalculationType.PhotonVolumeDose, Configuracion.DoseCalculationAlgorithm);
            var res = plan.CalculateDose();

            if (!res.Success)
            {
                return(string.Format("Falló el cálculo de dosis para el plan '{0}'. Output:\n{1}", plan.Id, res));
                //throw new Exception(message);
            }
            else
            {
                watch.Stop();
                var elapsedMs = watch.ElapsedMilliseconds;
                return(string.Format("Finalizó el cálculo de dosis para el plan '{0}'. Demoró " + elapsedMs.ToString() + "ms", plan.Id));
            }
        }
Пример #7
0
        public static string optimizarIMRT(ExternalPlanSetup plan)
        {
            var watch = Stopwatch.StartNew();

            plan.SetCalculationModel(CalculationType.PhotonIMRTOptimization, Configuracion.OptimizationAlgorithm);
            var opt = new OptimizationOptionsIMRT(2500, OptimizationOption.RestartOptimization, OptimizationConvergenceOption.TerminateIfConverged, Configuracion.MlcId);
            var res = plan.Optimize(opt);

            if (!res.Success)
            {
                return(string.Format("Falló la optimización para el plan '{0}'", plan.Id));
            }
            else
            {
                watch.Stop();
                var elapsedMs = watch.ElapsedMilliseconds;
                return(string.Format("Finalizó la optimización para el plan '{0}'. Demoró " + elapsedMs.ToString() + "ms", plan.Id));
            }
        }
Пример #8
0
        public bool CopyAndCreate(Application app, string ptId_Tgt, string crsId_Tgt, string plnId_Tgt, string structId_Tgt, PlanParameters plnParam_Ref)
        {
            //Open patient//
            PatientSummary ptSumm = app.PatientSummaries.FirstOrDefault(ps => ps.Id == ptId_Tgt);

            if (ptSumm == null)
            {
                Console.WriteLine("--Cannot find patient" + ptId_Tgt + ".");
                return(false);
            }
            Patient pt = app.OpenPatient(ptSumm);

            try
            {
                pt.BeginModifications();
                //Open or create course//
                Course crs = pt.Courses.FirstOrDefault(c => c.Id == crsId_Tgt);
                if (crs == null)
                {
                    Console.WriteLine("-Create course " + crsId_Tgt + ".");
                    crs    = pt.AddCourse();
                    crs.Id = crsId_Tgt;
                }
                //Create plan//
                ExternalPlanSetup pln = crs.ExternalPlanSetups.FirstOrDefault(p => p.Id == plnId_Tgt);
                if (pln == null)
                {
                    StructureSet structSet = pt.StructureSets.FirstOrDefault(ss => ss.Id == structId_Tgt);
                    if (structSet == null)
                    {
                        Console.WriteLine("--Cannot find structure set " + structId_Tgt + ". Plan is not created\n");
                        app.ClosePatient();
                        return(false);
                    }
                    pln    = crs.AddExternalPlanSetup(structSet);
                    pln.Id = plnId_Tgt;
                }
                //Return if there is already a plan with the same name//
                else
                {
                    Console.WriteLine("--A plan with name " + plnId_Tgt + " already exists. Plan is not created\n");
                    app.ClosePatient();
                    return(false);
                }
                Console.WriteLine("-Start creating plan " + plnId_Tgt + ".");
                //Set plan prescription properties//
                pln.SetPrescription(plnParam_Ref.N_Fx, plnParam_Ref.DoseperFx, plnParam_Ref.TrtPct);
                ///////////Create beam by copying from the beams in reference plan parameters////////////
                //Create empty list of MU values for each beam//
                List <KeyValuePair <string, MetersetValue> > muValues = new List <KeyValuePair <string, MetersetValue> >();
                foreach (PlanParameters.BmParam bmParam in plnParam_Ref.BmParamLs)
                {
                    //Add beam, type based on reference MLC beam technique//
                    IEnumerable <double> muSet = bmParam.CtrPtParam.ControlPoints.Select(cp => cp.MetersetWeight).ToList();
                    switch (bmParam.MLCBmTechnique)
                    {
                    case "StaticMLC":
                        Beam bm =
                            pln.AddMLCBeam(bmParam.MachParam, new float[2, 60],
                                           new VRect <double>(-10.0, -10.0, 10.0, 10.0), 0.0, 0.0, 0.0, bmParam.CtrPtParam.Isocenter);
                        bm.Id = bmParam.bmId;
                        bm.ApplyParameters(bmParam.CtrPtParam);
                        break;

                    case "StaticSegWin":
                        bm =
                            pln.AddMultipleStaticSegmentBeam(bmParam.MachParam, muSet, 0.0, 0.0, 0.0, bmParam.CtrPtParam.Isocenter);
                        bm.Id = bmParam.bmId;
                        muValues.Add(new KeyValuePair <string, MetersetValue>(bmParam.bmId, bmParam.mu));
                        bm.ApplyParameters(bmParam.CtrPtParam);
                        break;

                    case "StaticSlidingWin":
                        bm =
                            pln.AddSlidingWindowBeam(bmParam.MachParam, muSet, 0.0, 0.0, 0.0, bmParam.CtrPtParam.Isocenter);
                        bm.Id = bmParam.bmId;
                        muValues.Add(new KeyValuePair <string, MetersetValue>(bmParam.bmId, bmParam.mu));
                        bm.ApplyParameters(bmParam.CtrPtParam);
                        break;

                    case "ConformalArc":
                        bm =
                            pln.AddConformalArcBeam(bmParam.MachParam, 0.0, bmParam.CtrPtParam.ControlPoints.Count(),
                                                    bmParam.CtrPtParam.ControlPoints.First().GantryAngle, bmParam.CtrPtParam.ControlPoints.Last().GantryAngle,
                                                    bmParam.CtrPtParam.GantryDirection, 0.0, bmParam.CtrPtParam.Isocenter);
                        bm.Id = bmParam.bmId;
                        bm.ApplyParameters(bmParam.CtrPtParam);
                        break;

                    case "VMAT":
                        bm =
                            pln.AddVMATBeam(bmParam.MachParam, muSet, 0.0,
                                            bmParam.CtrPtParam.ControlPoints.First().GantryAngle, bmParam.CtrPtParam.ControlPoints.Last().GantryAngle,
                                            bmParam.CtrPtParam.GantryDirection, 0.0, bmParam.CtrPtParam.Isocenter);
                        bm.Id = bmParam.bmId;
                        bm.ApplyParameters(bmParam.CtrPtParam);
                        break;

                    default:
                        Console.WriteLine("--At least one of the beams is unidentified, plan is not created.\n");
                        app.ClosePatient();
                        return(false);
                    }
                }
                //Set the plan normalization value//
                pln.PlanNormalizationValue = plnParam_Ref.PlnNormFactr;
                //Set the plan calculation model//
                pln.SetCalculationModel(CalculationType.PhotonVolumeDose, plnParam_Ref.CalcModel);
                //If one of the beams is static IMRT, compute dose to enforce MUs to beams//
                if (plnParam_Ref.BmParamLs.Any(bm => bm.MLCBmTechnique == "StaticSegWin" || bm.MLCBmTechnique == "StaticSlidingWin"))
                {
                    Console.WriteLine("--Start computing static beam IMRT plan.");
                    pln.CalculateDoseWithPresetValues(muValues);
                }
                Console.WriteLine("-Finish plan creation.\n");
                app.SaveModifications();
                app.ClosePatient();
                return(true);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                app.ClosePatient();
                return(false);
            }
        }
Пример #9
0
        private bool removeFlashStr()
        {
            //remove the structures used to generate flash in the plan
            StructureSet ss = vmatPlan.StructureSet;
            //check to see if this structure set is used in any other calculated plans that are NOT the _VMAT TBI plan or any of the AP/PA legs plans
            string message = "";
            List <ExternalPlanSetup> otherPlans = new List <ExternalPlanSetup> {
            };

            foreach (Course c in vmatPlan.Course.Patient.Courses)
            {
                foreach (ExternalPlanSetup p in c.ExternalPlanSetups)
                {
                    if ((p != vmatPlan && !appaPlan.Where(x => x == p).Any()) && p.IsDoseValid && p.StructureSet == ss)
                    {
                        message += String.Format("Course: {0}, Plan: {1}", c.Id, p.Id) + System.Environment.NewLine;
                        otherPlans.Add(p);
                    }
                }
            }
            //photon dose calculation model type
            string calcModel = vmatPlan.GetCalculationModel(CalculationType.PhotonVolumeDose);

            if (otherPlans.Count > 0)
            {
                //if some plans were found that use this structure set and have dose calculated, inform the user and ask if they want to continue WITHOUT removing flash.
                message  = "The following plans have dose calculated and use the same structure set:" + System.Environment.NewLine + message + System.Environment.NewLine;
                message += "I need to remove the calculated dose from these plans before removing the flash structures." + System.Environment.NewLine;
                message += "Continue?";
                confirmUI CUI = new VMATTBIautoPlan.confirmUI();
                CUI.message.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                CUI.message.Text = message;
                CUI.ShowDialog();
                //need to return from this function regardless of what the user decides
                if (!CUI.confirm)
                {
                    return(true);
                }
                foreach (ExternalPlanSetup p in otherPlans)
                {
                    p.ClearCalculationModel(CalculationType.PhotonVolumeDose);
                    p.SetCalculationModel(CalculationType.PhotonVolumeDose, calcModel);
                }
            }
            //dumbass way around the issue of modifying structures in a plan that already has dose calculated... reset the calculation model, make the changes you need, then reset the calculation model
            vmatPlan.ClearCalculationModel(CalculationType.PhotonVolumeDose);
            vmatPlan.SetCalculationModel(CalculationType.PhotonVolumeDose, calcModel);
            foreach (ExternalPlanSetup p in appaPlan)
            {
                p.ClearCalculationModel(CalculationType.PhotonVolumeDose);
                p.SetCalculationModel(CalculationType.PhotonVolumeDose, calcModel);
            }
            IEnumerable <Structure> flashStr = ss.Structures.Where(x => x.Id.ToLower().Contains("flash"));
            List <Structure>        removeMe = new List <Structure> {
            };

            //can't remove directly from flashStr because the vector size would change on each loop iteration
            foreach (Structure s in flashStr)
            {
                if (!s.IsEmpty)
                {
                    if (ss.CanRemoveStructure(s))
                    {
                        removeMe.Add(s);
                    }
                }
            }
            foreach (Structure s in removeMe)
            {
                ss.RemoveStructure(s);
            }

            //from the generateTS class, the human_body structure was a copy of the body structure BEFORE flash was added. Therefore, if this structure still exists, we can just copy it back onto the body
            Structure bodyCopy = ss.Structures.FirstOrDefault(x => x.Id.ToLower() == "human_body");

            if (bodyCopy != null && !bodyCopy.IsEmpty)
            {
                Structure body = ss.Structures.First(x => x.Id.ToLower() == "body");
                body.SegmentVolume = bodyCopy.Margin(0.0);
                if (ss.CanRemoveStructure(bodyCopy))
                {
                    ss.RemoveStructure(bodyCopy);
                }
            }
            else
            {
                MessageBox.Show("WARNING 'HUMAN_BODY' STRUCTURE NOT FOUND! BE SURE TO RE-CONTOUR THE BODY STRUCTURE!");
            }
            flashRemoved = true;

            return(false);
        }
Пример #10
0
        static void Planning(Application curapp, Patient curpat, StructureSet curstructset, List <Tuple <string, string, float, string> > TargetStructures, List <string> AllowedNonTargetStructures, float RxDose, int NFractions)
        {
            curpat.BeginModifications();

            string IDofptv_low  = string.Empty;
            string IDofptv_high = string.Empty; //

            StringBuilder sb = new StringBuilder();

            //Check structure nameing
            sb.AppendLine("Check Structure Naming");
            sb.AppendLine("Structure ID        \tIs Standard Name?");
            foreach (Structure curstruct in curstructset.Structures.OrderBy(x => x.Id))
            {
                if (curstruct.DicomType == "PTV" | curstruct.DicomType == "CTV" | curstruct.DicomType == "GTV")
                {
                    if (TargetStructures.Where(x => x.Item1 == curstruct.Id).Any() || TargetStructures.Where(x => curstruct.DicomType.ToString() + "_" + x.Item3 + (x.Item4 == "Gy" ? "00" : string.Empty) == curstruct.Id).Any())
                    {
                        sb.AppendLine(curstruct.Id.PadRight(curstruct.Id.Length < 20 ? 20 - curstruct.Id.Length : 0) + "\tYes");
                    }
                    else
                    {
                        sb.AppendLine(curstruct.Id.PadRight(curstruct.Id.Length < 20 ? 20 - curstruct.Id.Length : 0) + "\tNo");
                    }
                }
                else
                {
                    if (AllowedNonTargetStructures.Where(x => x == curstruct.Id).Any() || curstruct.Id.ToString().StartsWith("z"))
                    {
                        sb.AppendLine(curstruct.Id.PadRight(curstruct.Id.Length < 20 ? 20 - curstruct.Id.Length : 0) + "\tYes");
                    }
                    else
                    {
                        sb.AppendLine(curstruct.Id.PadRight(curstruct.Id.Length < 20 ? 20 - curstruct.Id.Length : 0) + "\tNo");
                    }
                }
            }
            sb.AppendLine();
            sb.AppendLine("Press OK to continue with creating optimization structures");
            System.Windows.MessageBox.Show(sb.ToString());



            //Create optimization structures
            if (TargetStructures.Where(x => x.Item1 == "PTV_Low").Any())
            {
                IDofptv_low = TargetStructures.Where(x => x.Item1 == "PTV_Low").Select(x => x.Item2).First();                                                      //Get the ID of the structure identified as PTV_Low
            }
            if (TargetStructures.Where(x => x.Item1 == "PTV_High").Any())
            {
                IDofptv_high = TargetStructures.Where(x => x.Item1 == "PTV_High").Select(x => x.Item2).First();                                                      //Get the ID of the structure identified as PTV_High
            }
            Structure ptv_low  = null;
            Structure ptv_high = null;


            //Check that PT_High structure exists, issue warning if it does not.
            if (curstructset.Structures.Where(x => x.Id == IDofptv_low).Any())
            {
                ptv_low = curstructset.Structures.Where(x => x.Id == IDofptv_low).First();
            }
            else
            {
                System.Windows.MessageBox.Show("Did not find a PTV_High Structure. Fix before proceeding");
            }

            //Check that PT_Low structure exists, issue warning if it does not.
            if (curstructset.Structures.Where(x => x.Id == IDofptv_high).Any())
            {
                ptv_high = curstructset.Structures.Where(x => x.Id == IDofptv_high).First();
            }
            else
            {
                System.Windows.MessageBox.Show("Did not find a PTV_Low Structure. Fix before proceeding");
            }


            //Creation of optimization structures. If a copy already exitst delete it first.

            //Optimization structure for the PTV_Low volume is named zPTV_Low^Opt
            if (curstructset.Structures.Where(x => x.Id.Contains("zPTV_Low^Opt")).Any())
            {
                curstructset.RemoveStructure(curstructset.Structures.Where(x => x.Id.Contains("zPTV_Low^Opt")).First());
            }
            Structure zptvlowopt = curstructset.AddStructure("ORGAN", "zPTV_Low^Opt");

            //Dose limiting annulus (DLA) structure is used to make the prescribed dose conformal. DLA for PTV_Low is named zDLA_Low
            if (curstructset.Structures.Where(x => x.Id.Contains("zDLA__Low")).Any())
            {
                curstructset.RemoveStructure(curstructset.Structures.Where(x => x.Id.Contains("zDLA__Low")).First());
            }
            Structure zdlalow = curstructset.AddStructure("ORGAN", "zDLA__Low");

            //Optimization structure for the PTV_High volume is named zPTV_High^Opt
            if (curstructset.Structures.Where(x => x.Id.Contains("zPTV_High^Opt")).Any())
            {
                curstructset.RemoveStructure(curstructset.Structures.Where(x => x.Id.Contains("zPTV_High^Opt")).First());
            }
            Structure zptvhighopt = curstructset.AddStructure("ORGAN", "zPTV_High^Opt");


            //Dose limiting annulus (DLA) structure is used to make the prescribed dose conformal. DLA for PTV_High is named zDLA_High
            if (curstructset.Structures.Where(x => x.Id.Contains("zDLA__High")).Any())
            {
                curstructset.RemoveStructure(curstructset.Structures.Where(x => x.Id.Contains("zDLA__High")).First());
            }
            Structure zdlahigh = curstructset.AddStructure("ORGAN", "zDLA__High");

            //Make zPTV_High^Opt from PTV_High and boolean out the rectum
            zptvhighopt.SegmentVolume = ptv_high.Margin(0.0f);
            zptvhighopt.SegmentVolume = zptvhighopt.Sub(curstructset.Structures.Where(x => x.Id.Contains("Rectum")).Single());//Boolean the Rectum out of the high dose ptv optimization structure


            //Make zPTV_Low^Opt from PTV_Low and boolean out the PTV_High structure
            zptvlowopt.SegmentVolume = ptv_low.Margin(0.0f);
            zptvlowopt.SegmentVolume = zptvlowopt.Sub(ptv_high.Margin(1.0f));//Boolean the ptv_high out of ptv_low optimization structure


            //Make a dose limiting annulus arround the low dose ptv optimization structure
            zdlalow.SegmentVolume = zptvlowopt.SegmentVolume;
            zdlalow.SegmentVolume = zdlalow.Margin(10.0f);
            zdlalow.SegmentVolume = zdlalow.Sub(zptvlowopt.Margin(1.0f));
            zdlalow.SegmentVolume = zdlalow.Sub(zptvhighopt.Margin(5.0f));

            //Make a dose limiting annulus arround the high dose ptv optimization structure
            zdlahigh.SegmentVolume = zptvhighopt.SegmentVolume;
            zdlahigh.SegmentVolume = zdlahigh.Margin(10.0f);
            zdlahigh.SegmentVolume = zdlahigh.Sub(zptvhighopt.Margin(1.0f));

            sb = new StringBuilder();
            sb.AppendLine("Done with creating optimization strutures");
            sb.AppendLine("Click OK to proceed with setting up course and VMAT plan");
            System.Windows.MessageBox.Show(sb.ToString());

            //Add course
            Course curcourse;

            if (curpat.Courses.Where(x => x.Id == "AutoPlan").Any())
            {
                curcourse = curpat.Courses.Where(x => x.Id == "AutoPlan").Single();
            }
            else
            {
                curcourse    = curpat.AddCourse();
                curcourse.Id = "AutoPlan";
            }

            //Remove PlanSetup if it exists then create new plan setup

            if (curcourse.PlanSetups.Where(x => x.Id == "AutoPlanVMAT").Any())
            {
                curcourse.RemovePlanSetup(curcourse.PlanSetups.Where(x => x.Id == "AutoPlanVMAT").Single());
            }
            ExternalPlanSetup cureps = curcourse.AddExternalPlanSetup(curstructset);

            cureps.Id = "AutoPlanVMAT";



            //Add VMAT Beams
            VVector isocenter = new VVector(Math.Round(ptv_high.CenterPoint.x / 10.0f) * 10.0f, Math.Round(ptv_high.CenterPoint.y / 10.0f) * 10.0f, Math.Round(ptv_high.CenterPoint.z / 10.0f) * 10.0f);
            ExternalBeamMachineParameters ebmp = new ExternalBeamMachineParameters("Truebeam", "6X", 600, "ARC", null);
            Beam VMAT1 = cureps.AddArcBeam(ebmp, new VRect <double>(-100, -100, 100, 100), 30, 181, 179, GantryDirection.Clockwise, 0, isocenter);
            Beam VMAT2 = cureps.AddArcBeam(ebmp, new VRect <double>(-100, -100, 100, 100), 330, 179, 181, GantryDirection.CounterClockwise, 0, isocenter);

            VMAT1.Id = "CW";
            VMAT2.Id = "CCW";

            VMAT1.FitCollimatorToStructure(new FitToStructureMargins(10), ptv_low, true, true, false);
            VMAT2.FitCollimatorToStructure(new FitToStructureMargins(10), ptv_low, true, true, false);



            cureps.SetCalculationModel(CalculationType.PhotonVMATOptimization, "PO_15014");
            cureps.SetPrescription(NFractions, new DoseValue(RxDose / NFractions, "Gy"), 1);

            curapp.SaveModifications();

            sb = new StringBuilder();
            sb.AppendLine("Done with setting up course and VMAT plan");
            sb.AppendLine("Click OK to proceed with plan optimization");
            System.Windows.MessageBox.Show(sb.ToString());

            float doseobjectivevalue_low  = TargetStructures.Where(x => x.Item1 == "PTV_Low").Select(x => x.Item3).First();
            float doseobjectivevalue_high = TargetStructures.Where(x => x.Item1 == "PTV_High").Select(x => x.Item3).First();


            cureps.OptimizationSetup.AddPointObjective(zptvlowopt, OptimizationObjectiveOperator.Lower, new DoseValue(doseobjectivevalue_low, "Gy"), 100, 100);
            cureps.OptimizationSetup.AddPointObjective(zptvlowopt, OptimizationObjectiveOperator.Upper, new DoseValue(doseobjectivevalue_low + 3.0f, "Gy"), 30, 50);
            cureps.OptimizationSetup.AddPointObjective(zdlalow, OptimizationObjectiveOperator.Upper, new DoseValue(doseobjectivevalue_low, "Gy"), 0, 50);

            cureps.OptimizationSetup.AddPointObjective(zptvhighopt, OptimizationObjectiveOperator.Lower, new DoseValue(doseobjectivevalue_high, "Gy"), 100, 120);
            cureps.OptimizationSetup.AddPointObjective(zptvhighopt, OptimizationObjectiveOperator.Upper, new DoseValue(doseobjectivevalue_high + 2.0f, "Gy"), 0, 100);
            cureps.OptimizationSetup.AddPointObjective(zdlahigh, OptimizationObjectiveOperator.Upper, new DoseValue(doseobjectivevalue_high, "Gy"), 0, 50);

            cureps.OptimizationSetup.AddNormalTissueObjective(80.0f, 0.0f, 100.0f, 40.0f, 0.05f);
            OptimizerResult optresult = cureps.OptimizeVMAT(new OptimizationOptionsVMAT(OptimizationIntermediateDoseOption.NoIntermediateDose, string.Empty));



            sb = new StringBuilder();
            sb.AppendLine("VMAT optimization is done");
            sb.AppendLine("NIterattions:" + optresult.NumberOfIMRTOptimizerIterations.ToString() + " , ObjectiveFunctionValue: " + optresult.TotalObjectiveFunctionValue.ToString());
            sb.AppendLine("Click OK to proceed with optimization");

            cureps.OptimizeVMAT();

            curapp.SaveModifications();

            sb = new StringBuilder();
            sb.AppendLine("Done with optimization");
            sb.AppendLine("Click OK to proceed with dose calculation");
            System.Windows.MessageBox.Show(sb.ToString());

            cureps.CalculateDose();
            //cureps.PlanNormalizationValue = 99.0f;

            curapp.SaveModifications();
            sb = new StringBuilder();
            sb.AppendLine("Done with dose calculation");

            if (cureps.StructureSet.Structures.Where(x => x.Id == "Rectum").Any())
            {
                Structure reportstructure = cureps.StructureSet.Structures.Where(x => x.Id == "Rectum").First();
                sb.AppendLine("Rectum:V65Gy[%]:" + cureps.GetVolumeAtDose(reportstructure, new DoseValue(65.0f, DoseValue.DoseUnit.Gy), VolumePresentation.Relative).ToString());
            }

            sb.AppendLine("PTV_High:D95%[Gy]:" + cureps.GetDoseAtVolume(ptv_high, 95.0f, VolumePresentation.Relative, DoseValuePresentation.Absolute).ToString());


            sb.AppendLine("Click OK to finish script");
            System.Windows.MessageBox.Show(sb.ToString());
        }
Пример #11
0
        private void set_beams(List <VVector> isoLocations)
        {
            //DRR parameters (dummy parameters to generate DRRs for each field)
            DRRCalculationParameters DRR = new DRRCalculationParameters();

            DRR.DRRSize           = 500.0;
            DRR.FieldOutlines     = true;
            DRR.StructureOutlines = true;
            DRR.SetLayerParameters(1, 1.0, 100.0, 1000.0);

            //place the beams for the VMAT plan
            //unfortunately, all of Nataliya's requirements for beam placement meant that this process couldn't simply draw from beam placement templates. Some of the beam placements for specific isocenters
            //and under certain conditions needed to be hard-coded into the script. I'm not really a fan of this, but it was the only way to satisify Nataliya's requirements.
            int            count = 0;
            string         beamName;
            VRect <double> jp;

            for (int i = 0; i < numVMATIsos; i++)
            {
                for (int j = 0; j < numBeams[i]; j++)
                {
                    //second isocenter and third beam requires the x-jaw positions to be mirrored about the y-axis (these jaw positions are in the fourth element of the jawPos list)
                    //this is generally the isocenter located in the pelvis and we want the beam aimed at the kidneys-area
                    if (i == 1 && j == 2)
                    {
                        jp = jawPos.ElementAt(j + 1);
                    }
                    else if (i == 1 && j == 3)
                    {
                        jp = jawPos.ElementAt(j - 1);
                    }
                    else
                    {
                        jp = jawPos.ElementAt(j);
                    }
                    Beam b;
                    beamName  = "";
                    beamName += String.Format("{0} ", count + 1);
                    //zero collimator rotations of two main fields for beams in isocenter immediately superior to matchline. Adjust the third beam such that collimator rotation is 90 degrees. Do not adjust 4th beam
                    double coll = collRot[j];
                    if ((numIsos > numVMATIsos) && (i == (numVMATIsos - 1)))
                    {
                        if (j < 2)
                        {
                            coll = 0.0;
                        }
                        else if (j == 2)
                        {
                            coll = 90.0;
                        }
                    }
                    //all even beams (e.g., 2, 4, etc.) will be CCW and all odd beams will be CW
                    if (count % 2 == 0)
                    {
                        b = plan.AddArcBeam(ebmpArc, jp, coll, CCW[0], CCW[1], GantryDirection.CounterClockwise, 0, isoLocations.ElementAt(i));
                        if (j >= 2)
                        {
                            beamName += String.Format("CCW {0}{1}", isoNames.ElementAt(i), 90);
                        }
                        else
                        {
                            beamName += String.Format("CCW {0}{1}", isoNames.ElementAt(i), "");
                        }
                    }
                    else
                    {
                        b = plan.AddArcBeam(ebmpArc, jp, coll, CW[0], CW[1], GantryDirection.Clockwise, 0, isoLocations.ElementAt(i));
                        if (j >= 2)
                        {
                            beamName += String.Format("CW {0}{1}", isoNames.ElementAt(i), 90);
                        }
                        else
                        {
                            beamName += String.Format("CW {0}{1}", isoNames.ElementAt(i), "");
                        }
                    }
                    b.Id = beamName;
                    b.CreateOrReplaceDRR(DRR);
                    count++;
                }
            }

            //add additional plan for ap/pa legs fields (all ap/pa isocenter fields will be contained within this plan)
            if (numIsos > numVMATIsos)
            {
                //6-10-2020 EAS, checked if exisiting _Legs plan is present in createPlan method
                legs_planUpper = tbi.AddExternalPlanSetup(selectedSS);
                if (singleAPPAplan)
                {
                    legs_planUpper.Id = String.Format("_Legs");
                }
                else
                {
                    legs_planUpper.Id = String.Format("{0} Upper Legs", numVMATIsos + 1);
                }
                //100% dose prescribed in plan
                legs_planUpper.SetPrescription(prescription.Item1, prescription.Item2, 1.0);
                legs_planUpper.SetCalculationModel(CalculationType.PhotonVolumeDose, calculationModel);

                Structure target;
                if (useFlash)
                {
                    target = selectedSS.Structures.FirstOrDefault(x => x.Id.ToLower() == "ts_flash_target");
                }
                else
                {
                    target = selectedSS.Structures.FirstOrDefault(x => x.Id.ToLower() == "ptv_body");
                }

                //adjust x2 jaw (furthest from matchline) so that it covers edge of target volume
                double x2 = isoLocations.ElementAt(numVMATIsos).z - (target.MeshGeometry.Positions.Min(p => p.Z) - 20.0);
                if (x2 > 200.0)
                {
                    x2 = 200.0;
                }
                else if (x2 < 10.0)
                {
                    x2 = 10.0;
                }

                //AP field
                //set MLC positions. First row is bank number 0 (X1 leaves) and second row is bank number 1 (X2).
                float[,] MLCpos = new float[2, 60];
                for (int i = 0; i < 60; i++)
                {
                    MLCpos[0, i] = (float)-200.0;
                    MLCpos[1, i] = (float)(x2);
                }
                Beam b = legs_planUpper.AddMLCBeam(ebmpStatic, MLCpos, new VRect <double>(-200.0, -200.0, x2, 200.0), 90.0, 0.0, 0.0, isoLocations.ElementAt(numVMATIsos));
                b.Id = String.Format("{0} AP Upper Legs", ++count);
                b.CreateOrReplaceDRR(DRR);

                //PA field
                b    = legs_planUpper.AddMLCBeam(ebmpStatic, MLCpos, new VRect <double>(-200.0, -200.0, x2, 200.0), 90.0, 180.0, 0.0, isoLocations.ElementAt(numVMATIsos));
                b.Id = String.Format("{0} PA Upper Legs", ++count);
                b.CreateOrReplaceDRR(DRR);

                if ((numIsos - numVMATIsos) == 2)
                {
                    VVector infIso = new VVector();
                    //the element at numVMATIsos in isoLocations vector is the first AP/PA isocenter
                    infIso.x = isoLocations.ElementAt(numVMATIsos).x;
                    infIso.y = isoLocations.ElementAt(numVMATIsos).y;

                    double x1 = -200.0;
                    //if the distance between the matchline and the inferior edge of the target is < 600 mm, set the beams in the second isocenter (inferior-most) to be half-beam blocks
                    if (selectedSS.Structures.First(x => x.Id.ToLower() == "matchline").CenterPoint.z - target.MeshGeometry.Positions.Min(p => p.Z) < 600.0)
                    {
                        infIso.z = isoLocations.ElementAt(numVMATIsos).z - 200.0;
                        x1       = 0.0;
                    }
                    else
                    {
                        infIso.z = isoLocations.ElementAt(numVMATIsos).z - 390.0;
                    }
                    //fit x1 jaw to extend of patient
                    x2 = infIso.z - (target.MeshGeometry.Positions.Min(p => p.Z) - 20.0);
                    if (x2 > 200.0)
                    {
                        x2 = 200.0;
                    }
                    else if (x2 < 10.0)
                    {
                        x2 = 10.0;
                    }

                    //set MLC positions
                    MLCpos = new float[2, 60];
                    for (int i = 0; i < 60; i++)
                    {
                        MLCpos[0, i] = (float)(x1);
                        MLCpos[1, i] = (float)(x2);
                    }
                    //AP field
                    if (singleAPPAplan)
                    {
                        b    = legs_planUpper.AddMLCBeam(ebmpStatic, MLCpos, new VRect <double>(x1, -200.0, x2, 200.0), 90.0, 0.0, 0.0, infIso);
                        b.Id = String.Format("{0} AP Lower Legs", ++count);
                        b.CreateOrReplaceDRR(DRR);

                        //PA field
                        b    = legs_planUpper.AddMLCBeam(ebmpStatic, MLCpos, new VRect <double>(x1, -200.0, x2, 200.0), 90.0, 180.0, 0.0, infIso);
                        b.Id = String.Format("{0} PA Lower Legs", ++count);
                        b.CreateOrReplaceDRR(DRR);
                    }
                    else
                    {
                        //create a new legs plan if the user wants to separate the two APPA isocenters into separate plans
                        ExternalPlanSetup legs_planLower = tbi.AddExternalPlanSetup(selectedSS);
                        legs_planLower.Id = String.Format("{0} Lower Legs", numIsos);
                        legs_planLower.SetPrescription(prescription.Item1, prescription.Item2, 1.0);
                        legs_planLower.SetCalculationModel(CalculationType.PhotonVolumeDose, calculationModel);

                        b    = legs_planLower.AddMLCBeam(ebmpStatic, MLCpos, new VRect <double>(x1, -200.0, x2, 200.0), 90.0, 0.0, 0.0, infIso);
                        b.Id = String.Format("{0} AP Lower Legs", ++count);
                        b.CreateOrReplaceDRR(DRR);

                        //PA field
                        b    = legs_planLower.AddMLCBeam(ebmpStatic, MLCpos, new VRect <double>(x1, -200.0, x2, 200.0), 90.0, 180.0, 0.0, infIso);
                        b.Id = String.Format("{0} PA Lower Legs", ++count);
                        b.CreateOrReplaceDRR(DRR);
                    }
                }
                //MessageBox.Show("calculating dose");
                //legs_planUpper.CalculateDose();
                //const int nChars = 256;
                //StringBuilder Buff = new StringBuilder(nChars);
                //IntPtr handle = GetForegroundWindow();

                //if (GetWindowText(handle, Buff, nChars) > 0)
                //{
                //    MessageBox.Show(Buff.ToString());

                //}
            }
            MessageBox.Show("Beams placed successfully!\nPlease proceed to the optimization setup tab!");
        }
Пример #12
0
        private bool createPlan()
        {
            //look for a course name VMAT TBI. If it does not exit, create it, otherwise load it into memory
            if (!selectedSS.Patient.Courses.Where(x => x.Id == "VMAT TBI").Any())
            {
                if (selectedSS.Patient.CanAddCourse())
                {
                    tbi    = selectedSS.Patient.AddCourse();
                    tbi.Id = "VMAT TBI";
                }
                else
                {
                    MessageBox.Show("Error! \nCan't add a treatment course to the patient!");
                    return(true);
                }
            }
            else
            {
                tbi = selectedSS.Patient.Courses.FirstOrDefault(x => x.Id == "VMAT TBI");
            }

            //6-10-2020 EAS, research system only!
            //if (tbi.ExternalPlanSetups.Where(x => x.Id == "_VMAT TBI").Any()) if (tbi.CanRemovePlanSetup((tbi.ExternalPlanSetups.First(x => x.Id == "_VMAT TBI")))) tbi.RemovePlanSetup(tbi.ExternalPlanSetups.First(x => x.Id == "_VMAT TBI"));
            if (tbi.ExternalPlanSetups.Where(x => x.Id == "_VMAT TBI").Any())
            {
                MessageBox.Show("A plan named '_VMAT TBI' Already exists! \nESAPI can't remove plans in the clinical environment! \nPlease manually remove this plan and try again.");
                return(true);
            }
            plan = tbi.AddExternalPlanSetup(selectedSS);
            //100% dose prescribed in plan and plan ID is _VMAT TBI
            plan.SetPrescription(prescription.Item1, prescription.Item2, 1.0);
            plan.Id = "_VMAT TBI";
            //ask the user to set the calculation model if not calculation model was set in UI.xaml.cs (up near the top with the global parameters)
            if (calculationModel == "")
            {
                IEnumerable <string> models = plan.GetModelsForCalculationType(CalculationType.PhotonVolumeDose);
                selectItem           SUI    = new VMATTBIautoPlan.selectItem();
                SUI.title.Text = "No calculation model set!" + Environment.NewLine + "Please select a calculation model!";
                foreach (string s in plan.GetModelsForCalculationType(CalculationType.PhotonVolumeDose))
                {
                    SUI.itemCombo.Items.Add(s);
                }
                SUI.ShowDialog();
                if (!SUI.confirm)
                {
                    return(true);
                }
                //get the plan the user chose from the combobox
                calculationModel = SUI.itemCombo.SelectedItem.ToString();

                //just an FYI that the calculation will likely run out of memory and crash the optimization when Acuros is used
                if (calculationModel.ToLower().Contains("acuros"))
                {
                    confirmUI CUI = new VMATTBIautoPlan.confirmUI();
                    CUI.message.Text = "Warning!" + Environment.NewLine + "The optimization will likely crash (i.e., run out of memory) if Acuros is used!" + Environment.NewLine + "Continue?!";
                    CUI.ShowDialog();
                    if (!CUI.confirm)
                    {
                        return(true);
                    }
                }
            }
            plan.SetCalculationModel(CalculationType.PhotonVolumeDose, calculationModel);

            //reference point can only be added for a plan that IS CURRENTLY OPEN
            //plan.AddReferencePoint(selectedSS.Structures.First(x => x.Id == "TS_PTV_VMAT"), null, "VMAT TBI", "VMAT TBI");

            //6-10-2020 EAS, research system only!
            if ((numIsos > numVMATIsos) && tbi.ExternalPlanSetups.Where(x => x.Id.ToLower().Contains("legs")).Any())
            {
                MessageBox.Show("Plan(s) with the string 'legs' already exists! \nESAPI can't remove plans in the clinical environment! \nPlease manually remove this plan and try again.");
                return(true);
            }

            //these needs to be fixed
            //v16 of Eclipse allows for the creation of a plan with a named target structure and named primary reference point. Neither of these options are available in v15
            //plan.TargetVolumeID = selectedSS.Structures.First(x => x.Id == "TS_PTV_VMAT");
            //plan.PrimaryReferencePoint = plan.ReferencePoints.Fisrt(x => x.Id == "VMAT TBI");

            return(false);
        }
Пример #13
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));
        }