Exemplo n.º 1
0
        /// <summary>
        /// Create verifications plans for a given treatment plan.
        /// </summary>
        public static void CreateVerificationPlan(Course course, IEnumerable <Beam> beams, ExternalPlanSetup verifiedPlan, StructureSet verificationStructures,
                                                  string planId, bool calculateDose)
        {
            var verificationPlan = course.AddExternalPlanSetupAsVerificationPlan(verificationStructures, verifiedPlan);

            Helpers.RemoveOldPlan(course, planId);
            verificationPlan.Id = planId;

            // Put isocenter to the center of the body.
            var isocenter = verificationStructures.Structures.Single(st => st.Id.ToLower().StartsWith("body")).CenterPoint;

            // Copy the given beams to the verification plan and the meterset values.
            var getCollimatorAndGantryAngleFromBeam = beams.Count() > 1;
            var presetValues = (from beam in beams
                                let newBeamId = CopyBeam(beam, verificationPlan, isocenter, getCollimatorAndGantryAngleFromBeam)
                                                select new KeyValuePair <string, MetersetValue>(newBeamId, beam.Meterset)).ToList();

            // Set presciption
            const int numberOfFractions = 1;

            verificationPlan.UniqueFractionation.SetPrescription(numberOfFractions, verifiedPlan.UniqueFractionation.PrescribedDosePerFraction, prescribedPercentage: 1.0);

            if (calculateDose)
            {
                verificationPlan.SetCalculationModel(CalculationType.PhotonVolumeDose, DoseCalculationAlgorithm);
                Trace.WriteLine("\nCalculating dose for verification plan...\n");
                var res = verificationPlan.CalculateDoseWithPresetValues(presetValues);
                if (!res.Success)
                {
                    var message = string.Format("Dose calculation failed for verification plan. Output:\n{0}", res);
                    Trace.WriteLine(message);
                    throw new Exception(message);
                }
            }
        }
        private static void Execute(Common.Model.API.Application app, string patientId, string planId)
        {
            var patient = app.OpenPatientById(patientId);

            patient.BeginModifications();

            if (!Helpers.CheckStructures(patient))
            {
                return;
            }

            // The demo patient has structures in a set structure called "Prostate".
            var structures = patient.StructureSets.Single(st => st.Id == "Prostate");

            var course = Helpers.GetCourse(patient, CourseId);

            // If old courses exists, remove them. Remove also the structures generated by the script (in the previous run).
            Helpers.RemoveOldPlan(course, planId);
            Helpers.RemoveStructures(structures, new List <string> {
                "PTV", PlanGeneration.ExpandedCTVId, PlanGeneration.PTVSubOARSId
            });

            // Launch the prescription dialog.
            var prescriptionDialog = new PrescriptionDialog(patientId, DefaultDosePerFraction, DefaultNumberOfFractions, DefaultMarginForPTVInMM, structures.Structures)
            {
                Width  = 300,
                Height = 350
            };
            double?dosePerFraction   = null;
            int?   numberOfFractions = null;
            double?marginForPTV      = null;
            string ctvId             = string.Empty;

            prescriptionDialog.Closed += (s, e) =>
            {
                dosePerFraction   = prescriptionDialog.DosePerFraction;
                numberOfFractions = prescriptionDialog.NumberOfFractions;
                marginForPTV      = prescriptionDialog.PTVMargin;
                ctvId             = prescriptionDialog.SelectedStructure;
            };
            prescriptionDialog.ShowDialog();

            // If the user inputs are valid, proceed to plan creation.
            if (dosePerFraction.HasValue && numberOfFractions.HasValue && marginForPTV.HasValue && ctvId != string.Empty)
            {
                // Create new plan.
                var plan = course.AddExternalPlanSetup(structures);
                plan.Id = planId;

                // Re-direct output from trace to console.
                Trace.Listeners.Add(new ConsoleTraceListener());

                // Beam geometry generation.
                PlanGeneration.GenerateBeamGeometry(plan, dosePerFraction != null ? dosePerFraction.Value : 0,
                                                    numberOfFractions != null ? numberOfFractions.Value : 0,
                                                    marginForPTV != null ? marginForPTV.Value : 0,
                                                    ctvId);

                // DVH estimation.
                var structureMatches = PlanGeneration.GetStructureMatches(plan);
                structureMatches.Remove(PlanGeneration.ExpandedCTVId);
                structureMatches.Add(PlanGeneration.PTVSubOARSId, new ModelStructure("PTV", ModelStructureType.Target));
                PlanGeneration.CalculateDVHEstimates(plan, structureMatches);

                // Add normal tissue objectives.
                PlanGeneration.AddNTO(plan);

                // Save beam geometry and DVH estimation results.
                var message = "Beam geometry generation and DVH estimation completed.";
                SaveAndShowMessage(app, message);

                // Optimization.
                PlanGeneration.Optimize(plan);

                // Save optimization results.
                message = "Optimization completed.";
                SaveAndShowMessage(app, message);

                // Caluclate dose.
                PlanGeneration.CalculateDose(plan);
                Trace.WriteLine("\nPlan successfully generated.\n");

                // Normalize plan.
                PlanGeneration.Normalize(plan, structureMatches);
                app.SaveModifications();

                // Report DVHs.
                var          outputPath             = @"C:\Temp\dvh.svg";
                const string browser                = @"C:\Program Files (x86)\Mozilla Firefox\firefox.exe";
                var          structuresForReporting = plan.StructureSet.Structures.Where(st => structureMatches.ContainsKey(st.Id));
                const int    dvhWidth               = 512;
                const int    dvhHeight              = 256;
                SVGFromDVH.SaveSVGFromStructures(outputPath, plan, structuresForReporting, dvhWidth, dvhHeight);

                outputPath = @"C:\Temp";
                var reportLocation = PlanQualityReporter.CreateReport(plan, structureMatches, outputPath);

                Trace.WriteLine("\nReport successfully generated.\n");

                // Display the generated report in web browser.
                Process.Start(browser, reportLocation);
                Thread.Sleep(1000);

                // Ask user if we want to proceed to plan verification.
                const string title = "Quality assurance";
                message = "Proceed to creation of verification plan?";
                var res = MessageBox.Show(new Window {
                    Topmost = true
                }, message, title, MessageBoxButton.YesNo, MessageBoxImage.Question);

                if (res == MessageBoxResult.Yes)
                {
                    // Create verification plan.
                    Trace.Write("\nRetrieving CT image of the QA device...\n");
                    var qaStructures = patient.StructureSets.Where(set => set.Id == VerificationPatientImageId).ToList();

                    // If we have already loaded the structures for verification, do not load them again. Currently, ESAPI doesn't offer methods to remove them... (has to be done by hand in Eclipse).
                    var verificationStructures = qaStructures.Any() ? qaStructures.First() : plan.Course.Patient.CopyImageFromOtherPatient(VerificationPatientId, VerificationPatientStudyId, VerificationPatientImageId);
                    CreateVerificationPlan(app, plan, verificationStructures);
                    app.SaveModifications();

                    Trace.WriteLine("\nVerification plans succesfully created.\n");
                }

                Trace.WriteLine("\nScript successfully executed.\n");
            }
            else
            {
                const string message = "Please provide a valid prescription.";
                const string title   = "Invalid prescription";
                MessageBox.Show(message, title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Run MCO
        /// </summary>
        /// <param name="app"></param>
        /// <param name="patient"></param>
        /// <param name="courseId"></param>
        /// <param name="planSetupId"></param>
        public static void RunMCO(Patient patient, string courseId, string planSetupId)
        {
            string message;
            string m_mcoImrtPlanSetupId = planSetupId;

            message = string.Format("Patient {0} opened for MCO", patient.Id);
            Trace.WriteLine(message);

            var planSetupOrig = Helpers.FindPlanSetup(patient, courseId, m_mcoImrtPlanSetupId);
            var planSetup     = planSetupOrig.Course.CopyPlanSetup(planSetupOrig) as ExternalPlanSetup;

            Helpers.RemoveOldPlan(planSetupOrig.Course, "MyMCOPlanV1");
            planSetup.Id = "MyMCOPlanV1";

            message = string.Format("planSetupOrig {0} found", planSetupOrig.Id);
            Trace.WriteLine(message);
            message = string.Format("Copy planSetupOrig {0} found", planSetup.Id);
            Trace.WriteLine(message);
            message = string.Format("Calculation model for Photons {0} found", planSetup.GetCalculationModel(CalculationType.PhotonIMRTOptimization));
            Trace.WriteLine(message);

            //Create Plan Collection
            message = string.Format("Is trade-off ready? {0}", planSetup.TradeoffExplorationContext.HasPlanCollection.ToString());
            Trace.WriteLine(message);
            message = string.Format("Has Tradeoff objectives set? {0}", planSetup.TradeoffExplorationContext.TradeoffObjectives.Any().ToString());
            Trace.WriteLine(message);
            var       tradeoffCandidates = planSetup.TradeoffExplorationContext.TradeoffStructureCandidates;
            Structure structure          = tradeoffCandidates.First();

            message = string.Format("Add one structure ({0}) as Tradeoff objectives set? {1}", structure.Id, planSetup.TradeoffExplorationContext.AddTradeoffObjective(structure));
            Trace.WriteLine(message);
            message = string.Format("Can a plan collection be created? {0}", planSetup.TradeoffExplorationContext.CanCreatePlanCollection);
            Trace.WriteLine(message);
            message = string.Format("Create the plan collection, result={0}", planSetup.TradeoffExplorationContext.CreatePlanCollection(false, TradeoffPlanGenerationIntermediateDoseMode.NotUsed));
            Trace.WriteLine(message);
            message = string.Format("Is trade-off exploration ready? {0}", planSetup.TradeoffExplorationContext.HasPlanCollection.ToString());
            Trace.WriteLine(message);
            foreach (var tradeoffObjective in planSetup.TradeoffExplorationContext.TradeoffObjectives)
            {
                message = string.Format("Objective cost ({0}) = {1}", tradeoffObjective.Structure, planSetup.TradeoffExplorationContext.GetObjectiveCost(tradeoffObjective));
                Trace.WriteLine(message);
            }
            message = string.Format("CurrentDose = {0}", planSetup.TradeoffExplorationContext.CurrentDose.DoseMax3D);
            Trace.WriteLine(message);
            foreach (var structureItem in planSetup.TradeoffExplorationContext.TargetStructures)
            {
                var structureDvh = planSetup.TradeoffExplorationContext.GetStructureDvh(structureItem);
                message = string.Format("GetStructureDvh({0}).MaxDose = {1}, MeanDose = {2}", structureItem.Id, structureDvh.MaxDose, structureDvh.MeanDose);
                Trace.WriteLine(message);
            }

            // Navigate with the trade-off objectives
            var    tradeoffObjectiveToNavigate        = planSetup.TradeoffExplorationContext.TradeoffObjectives.First();
            double costForTradeoffObjectiveToNavigate = 0.0;
            var    cost       = planSetup.TradeoffExplorationContext.GetObjectiveCost(tradeoffObjectiveToNavigate);
            var    lowerLimit = planSetup.TradeoffExplorationContext.GetObjectiveLowerLimit(tradeoffObjectiveToNavigate);
            var    upperLimit = planSetup.TradeoffExplorationContext.GetObjectiveUpperLimit(tradeoffObjectiveToNavigate);
            // move restrictor halfway between current cost and upper limit
            var newRestrictorPos = cost + (upperLimit - cost) * 0.5;

            message = string.Format("TradeoffObjective = {0}, Lower limit = {1}, upper limit = {2}, cost = {3}.", tradeoffObjectiveToNavigate.Structure, lowerLimit, upperLimit, cost);
            Trace.WriteLine(message);
            message = string.Format("Set upper restrictor of halfway between cost and upper limit {0} to {1}", tradeoffObjectiveToNavigate.Structure, newRestrictorPos);
            Trace.WriteLine(message);
            planSetup.TradeoffExplorationContext.SetObjectiveUpperRestrictor(tradeoffObjectiveToNavigate, newRestrictorPos);
            message = string.Format("Set tradeoffObjective {0} to {1}", tradeoffObjectiveToNavigate.Structure, costForTradeoffObjectiveToNavigate);
            Trace.WriteLine(message);
            planSetup.TradeoffExplorationContext.SetObjectiveCost(tradeoffObjectiveToNavigate, costForTradeoffObjectiveToNavigate);

            message = string.Format("--------View again the results---------");
            Trace.WriteLine(message);
            foreach (var tradeoffObjective in planSetup.TradeoffExplorationContext.TradeoffObjectives)
            {
                message = string.Format("Objective cost ({0}) = {1}", tradeoffObjective.Structure, planSetup.TradeoffExplorationContext.GetObjectiveCost(tradeoffObjective));
                Trace.WriteLine(message);
            }
            message = string.Format("CurrentDose = {0}", planSetup.TradeoffExplorationContext.CurrentDose.DoseMax3D);
            Trace.WriteLine(message);
            foreach (var structureItem in planSetup.TradeoffExplorationContext.TargetStructures)
            {
                var structureDvh = planSetup.TradeoffExplorationContext.GetStructureDvh(structureItem);
                message = string.Format("GetStructureDvh({0}).MaxDose = {1}, MeanDose = {2}", structureItem.Id, structureDvh.MaxDose, structureDvh.MeanDose);
                Trace.WriteLine(message);
            }
            cost       = planSetup.TradeoffExplorationContext.GetObjectiveCost(tradeoffObjectiveToNavigate);
            lowerLimit = planSetup.TradeoffExplorationContext.GetObjectiveLowerLimit(tradeoffObjectiveToNavigate);
            upperLimit = planSetup.TradeoffExplorationContext.GetObjectiveUpperLimit(tradeoffObjectiveToNavigate);
            message    = string.Format("TradeoffObjective = {0}, Lower limit = {1}, upper limit = {2}, cost = {3}.", tradeoffObjectiveToNavigate.Structure, lowerLimit, upperLimit, cost);
            Trace.WriteLine(message);

            //apply MCO
            message = string.Format("Saving plan collection and in case of IMRT applying to the plan setup.");
            Trace.WriteLine(message);
            planSetup.TradeoffExplorationContext.ApplyTradeoffExplorationResult();
            message = string.Format("Is Applying plan to plan setup in case IMRT successful? {0}", planSetup.TradeoffExplorationContext.CreateDeliverableVmatPlan(false));
            Trace.WriteLine(message);
        }