public void Execute(ScriptContext context /*, System.Windows.Window window, ScriptEnvironment environment*/) { // TODO : Add here the code that is called when the script is launched from Eclipse. Patient p = context.Patient; p.BeginModifications();//this line for scripting automation. //find the ctv in the structures. Structure ctv = context.StructureSet.Structures.First(o => o.DicomType == "CTV"); //create on the structureset a PTV from the ctv. Structure ptv = context.StructureSet.AddStructure("PTV", "PTVAuto"); ptv.SegmentVolume = ctv.Margin(8); //create a new plan. Course c_auto = p.AddCourse(); c_auto.Id = "Course_Auto"; ExternalPlanSetup plan = c_auto.AddExternalPlanSetup(context.StructureSet); plan.Id = "Plan_Auto"; //create the fields. //define the externalBeam Parameters ExternalBeamMachineParameters ebmp = new ExternalBeamMachineParameters( "TrueBeam", "6X", 600, "STATIC", null); //set gantry angles double[] g_angles = new double[] { 270, 0, 90, 180 }; foreach (double ga in g_angles) { //add a new beam with intial parametres Beam b = plan.AddMLCBeam( ebmp, new float[2, 60], new VRect <double>(-10, -10, 10, 10), 0, ga, 0, ptv.CenterPoint); //fit the MLC to the structure outline of the PTV. b.FitMLCToStructure(new FitToStructureMargins(10), ptv, false, JawFitting.FitToRecommended, OpenLeavesMeetingPoint.OpenLeavesMeetingPoint_Middle, ClosedLeavesMeetingPoint.ClosedLeavesMeetingPoint_Center); } //Calculate Dose plan.CalculateDose(); //Set Normalization plan.PlanNormalizationValue = plan.Beams.Count() * 100; //Set Prescription. plan.SetPrescription(30, new DoseValue(180, DoseValue.DoseUnit.cGy), 1); }
// 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 } }
public void computeDose() { // Create prescription // currPln.SetPrescription(1, new DoseValue(800.0, DoseValue.DoseUnit.cGy), 1.0); // Compute dose // currPln.CalculateDose(); }
private void OnCalculatePlan() { patient.BeginModifications(); Course course_temp = patient.AddCourse(); ExternalPlanSetup plan_temp = course_temp. AddExternalPlanSetup(patient.StructureSets.FirstOrDefault()); ExternalBeamMachineParameters exBeamParams = new ExternalBeamMachineParameters( "HESN10", "6X", 600, "STATIC", null); foreach (string fs in FieldSizes.Split(';')) { double fsd = Convert.ToDouble(fs); plan_temp.AddStaticBeam(exBeamParams, new VRect <double>(-fsd / 2 * 10, -fsd / 2 * 10, fsd / 2 * 10, fsd / 2 * 10), 0, 0, 0, new VVector(0, -200, 0)); } plan_temp.SetPrescription(1, new DoseValue(100, DoseValue.DoseUnit.cGy), 1); plan_temp.CalculateDose(); _app.SaveModifications(); AddCourses(patient); SelectedCourse = course_temp.Id; SelectedPlan = plan_temp.Id; }
/// <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); } }
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)); } }
public bool runCoverageCheck(List <Tuple <string, string, double, double, int> > optParams, ExternalPlanSetup plan, int percentCompletion, double relativeDose, double targetVolCoverage, bool useFlash) { //zero all optimization objectives except those in the target List <Tuple <string, string, double, double, int> > targetOnlyObj = new List <Tuple <string, string, double, double, int> > { }; int priority; string message = optObjHeader; foreach (Tuple <string, string, double, double, int> opt in optParams) { if (opt.Item1.ToLower().Contains("ptv") || opt.Item1.ToLower().Contains("ts_jnx")) { priority = opt.Item5; } else { priority = 0; } targetOnlyObj.Add(Tuple.Create(opt.Item1, opt.Item2, opt.Item3, opt.Item4, priority)); //record the optimization constraints for each structure after zero-ing the priorities. This information will be reported to the user in a progress update message += String.Format(" {0, -15} | {1, -16} | {2,-10:N1} | {3,-10:N1} | {4,-8} |" + System.Environment.NewLine, opt.Item1, opt.Item2, opt.Item3, opt.Item4, priority); } //update the constraints and provide an update to the user op.updateConstraints(targetOnlyObj, plan); Dispatcher.BeginInvoke((Action)(() => { provideUpdate((int)(100 * (++percentCompletion) / calcItems), message); })); //run one optimization with NO intermediate dose. plan.OptimizeVMAT(new OptimizationOptionsVMAT(OptimizationIntermediateDoseOption.NoIntermediateDose, MLCmodel)); if (abortOpt) { return(false); } //provide update Dispatcher.BeginInvoke((Action)(() => { provideUpdate((int)(100 * (++percentCompletion) / calcItems), " Optimization finished on coverage check! Calculating dose!"); })); Dispatcher.BeginInvoke((Action)(() => { provideUpdate(String.Format(" Elapsed time: {0}", currentTime)); })); //calculate dose (using AAA algorithm) plan.CalculateDose(); if (abortOpt) { return(false); } Dispatcher.BeginInvoke((Action)(() => { provideUpdate((int)(100 * (++percentCompletion) / calcItems), " Dose calculated for coverage check, normalizing plan!"); })); //normalize plan op.normalizePlan(plan, relativeDose, targetVolCoverage, useFlash); if (abortOpt) { return(false); } Dispatcher.BeginInvoke((Action)(() => { provideUpdate((int)(100 * (++percentCompletion) / calcItems), " Plan normalized!"); })); //print useful info about target coverage and global dmax Structure target; if (useFlash) { target = plan.StructureSet.Structures.First(x => x.Id.ToLower() == "ts_ptv_flash"); } else { target = plan.StructureSet.Structures.First(x => x.Id.ToLower() == "ts_ptv_vmat"); } message = " Additional plan infomation: " + System.Environment.NewLine + String.Format(" Plan global Dmax = {0:0.0}%", 100 * (plan.Dose.DoseMax3D.Dose / plan.TotalDose.Dose)) + System.Environment.NewLine + String.Format(" {0} Dmax = {1:0.0}%", target.Id, plan.GetDoseAtVolume(target, 0.0, VolumePresentation.Relative, DoseValuePresentation.Relative).Dose) + System.Environment.NewLine + String.Format(" {0} Dmin = {1:0.0}%", target.Id, plan.GetDoseAtVolume(target, 100.0, VolumePresentation.Relative, DoseValuePresentation.Relative).Dose) + System.Environment.NewLine + String.Format(" {0} V90% = {1:0.0}%", target.Id, plan.GetVolumeAtDose(target, new DoseValue(90.0, DoseValue.DoseUnit.Percent), VolumePresentation.Relative)) + System.Environment.NewLine + String.Format(" {0} V110% = {1:0.0}%", target.Id, plan.GetVolumeAtDose(target, new DoseValue(110.0, DoseValue.DoseUnit.Percent), VolumePresentation.Relative)) + System.Environment.NewLine + String.Format(" {0} V120% = {1:0.0}%", target.Id, plan.GetVolumeAtDose(target, new DoseValue(120.0, DoseValue.DoseUnit.Percent), VolumePresentation.Relative)); Dispatcher.BeginInvoke((Action)(() => { provideUpdate(message); })); //calculate global Dmax expressed as a percent of the prescription dose (if dose has been calculated) if (plan.IsDoseValid && ((plan.Dose.DoseMax3D.Dose / plan.TotalDose.Dose) > 1.40)) { return(true); } //else MessageBox.Show(String.Format("max dose: {0}%", 100 * (plan.Dose.DoseMax3D.Dose / plan.TotalDose.Dose))); return(false); }
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()); }
public void Execute(ScriptContext context /*, System.Windows.Window window, ScriptEnvironment environment*/) { //USER INPUT double s_ssd = 100; // SSD string cmach = "HESN5"; // MACHINE string[] erg = new string[] { "6X", "10X" }; // ENERGY LIST double[] jaw_sizes = new double[] { 4, 8, 10, 20 }; // FIELD SIZE LIST // Define local _patient, could be pointed to UI Patient _patient = context.Patient; _patient.BeginModifications(); // SET STRUCTURE SET StructureSet _structureSet = _patient.StructureSets.FirstOrDefault(); // DETERMINE EXTERNAL STRUCTURE var bst = _structureSet.Structures.First(x => x.DicomType == "EXTERNAL"); var bst_mgb = bst.MeshGeometry.Bounds; // CREATE NEW COURSE AND NAME IT Course C_Auto = _patient.AddCourse(); C_Auto.Id = string.Format("C_{0}_{1}SSD", cmach, s_ssd.ToString()); // LOOP THROUGH ENERGIES PROVIDED BY USER, CREATE A PLAN FOR EACH ENERGY foreach (var evar in erg) { // CREATE PLAN ExternalPlanSetup eps = C_Auto.AddExternalPlanSetup(_structureSet); // SET PRESCRIPTION eps.SetPrescription(1, new DoseValue(100, "cGy"), 1); eps.Id = evar.ToString(); // SET FIELD PARAMETERS ExternalBeamMachineParameters ebmp = new ExternalBeamMachineParameters(cmach, evar, 600, "STATIC", null); // LOOP THROUGH FIELD SIZES, CREATE A BEAM FOR EACH FIELD SIZE foreach (double js in jaw_sizes) { // SET JAW POSITION BASED ON USER FIELD SIZES - (ASSUMES ALL FIELDS ARE SYMMETRIC) double xjaw = js * 10; double yjaw = js * 10; // DEFINE BEAM PARAMETERS - (ASSUMES NO ANGLES) double coll = 0; double gant_a = 0; double couch_a = 0; // SET ISOCENTER BASED ON USER SSD double iso_x = 0; double iso_y = -10 * (Math.Round(bst_mgb.SizeY / 10) + Math.Round(bst_mgb.Location.Y / 10) + (s_ssd - 100)); double iso_z = 0; VVector isovec = new VVector(iso_x, iso_y, iso_z); // CREATE BEAM Beam b = eps.AddStaticBeam( ebmp, new VRect <double>(-0.5 * xjaw, -0.5 * yjaw, 0.5 * xjaw, 0.5 * yjaw), coll, gant_a, couch_a, isovec); // SET BEAM ID b.Id = String.Format("{0}_{1:F1}x{2:F1}", evar, xjaw / 10, yjaw / 10); } // CALCULATE DOSE eps.CalculateDose(); } MessageBox.Show("DONE"); }
public static Tuple <bool, List <List <string> > > Optimize(List <List <double[, ]> > choppedContours, List <double[]> planes, ref ExternalPlanSetup plan, ref StructureSet ss, HNPlan hnPlan, ScriptContext context, List <List <Structure> > optimizedStructures, List <List <Structure> > matchingStructures, string contraName, int numIterations, List <Tuple <bool, double[], string> > features, Tuple <string, string, bool> beamParams) //return a list of strings which is the log of constraint updates during optimization. { //Only make parotid structures if that feature has been selected if (features[0].Item1 == true) { double priorityRatio = features[0].Item2[0]; Segmentation.MakeParotidStructures(choppedContours, planes, ref plan, ref ss, hnPlan, context, matchingStructures, contraName, priorityRatio); } else { //remove previously segmented structures if there foreach (Structure structure in ss.Structures.ToList()) { if (structure.Name.ToLower().Contains("cpg_subseg")) { ss.RemoveStructure(structure); } } } //Now run the first VMAT optimization. plan.SetCalculationModel(CalculationType.PhotonVMATOptimization, "PO_13623"); plan.SetCalculationModel(CalculationType.DVHEstimation, "DVH Estimation Algorithm [15.6.06]"); plan.SetCalculationModel(CalculationType.PhotonVolumeDose, "AAA_13623"); plan.OptimizationSetup.AddNormalTissueObjective(100, 3, 95, 50, 0.2); bool jawTracking = beamParams.Item3; //use jaw tracking if (jawTracking) { try { plan.OptimizationSetup.UseJawTracking = true; } catch { System.Windows.MessageBox.Show("Could not use jaw tracking. Proceeding without."); } } // plan.OptimizeVMAT(); plan.CalculateDose(); string treatmentCenter = beamParams.Item1; string treatmentArea = beamParams.Item2; string mlcId = ""; int areaNum = Int32.Parse(Regex.Match(treatmentArea, @"\d+").Value); if (treatmentCenter == "BC Cancer - Surrey") { switch (areaNum) { case 2: mlcId = ""; break; case 3: mlcId = ""; break; case 4: mlcId = ""; break; case 5: mlcId = ""; break; case 6: mlcId = ""; break; } } else if (treatmentCenter == "BC Cancer - Vancouver") { switch (areaNum) { case 1: mlcId = "1"; break; case 2: mlcId = "HHM0767"; break; case 3: mlcId = ""; break; case 4: mlcId = ""; break; case 5: mlcId = ""; break; case 6: mlcId = "HML0990"; break; case 7: mlcId = "MLC0987"; break; } } string mlcID = "HML0990"; int numCycles = 1; OptimizationOptionsVMAT oov; ; bool isPassed = false; List <List <string> > updateLog = new List <List <string> >(); for (int iter = 0; iter < numIterations; iter++) { //mlcID = plan.Beams.FirstOrDefault<Beam>().MLC.Id; oov = new OptimizationOptionsVMAT(numCycles, mlcID); plan.OptimizeVMAT(oov); plan.CalculateDose(); //Now need to perform a plan check and iteratively adjust constraints based on whether they passed or failed, and whether they passed with flying colours or failed miserably. //Going to find the percentage by which the constraint failed or passed, and adjust both the priority and dose constraint based on this. updateLog.Add(OptObjectivesEditing.UpdateConstraints(ref plan, ref ss, ref hnPlan, context, optimizedStructures, matchingStructures, numCycles)); if (features[0].Item1 == true) { Segmentation.MakeParotidStructures(choppedContours, planes, ref plan, ref ss, hnPlan, context, matchingStructures, contraName, features[0].Item2[0]); } } numCycles = 4; oov = new OptimizationOptionsVMAT(numCycles, mlcID); //Now for a maximum of 3 tries, perform 4-cycle vmat optimization followed by constraint updating until a plan is passed for (int i = 0; i < 3; i++) { plan.OptimizeVMAT(oov); plan.CalculateDose(); updateLog.Add(OptObjectivesEditing.UpdateConstraints(ref plan, ref ss, ref hnPlan, context, optimizedStructures, matchingStructures, numCycles)); if (features[0].Item1 == true) { Segmentation.MakeParotidStructures(choppedContours, planes, ref plan, ref ss, hnPlan, context, matchingStructures, contraName, features[0].Item2[0]); } isPassed = Check.EvaluatePlan(context, hnPlan, matchingStructures, optimizedStructures).Item1; if (isPassed) { break; } } return(Tuple.Create(isPassed, updateLog)); }
public void Execute(ScriptContext context /*, System.Windows.Window window*/) { Patient patient = context.Patient; if (patient == null) { throw new ApplicationException("Please load a patient."); } // Get active structureset StructureSet ss = context.StructureSet; if (ss == null) { throw new ApplicationException("Please load a structure set."); } // Check that unique body structure, PTV and Rectum structures exist Structure body = ss.Structures.Where(o => o.Id == "BODY").FirstOrDefault(); Structure ptv = ss.Structures.Where(o => o.Id == "PTV").FirstOrDefault(); Structure rectum = ss.Structures.Where(o => o.Id == "Rectum1").FirstOrDefault(); if (body == null || ptv == null || rectum == null) { throw new ApplicationException(string.Format("Cannot find required structures (BODY, PTV, Rectum) from Structureset '{0}'", ss.Id)); } // Enable modifications patient.BeginModifications(); // Get or create course with Id 'Superplan' const string courseId = "Superplan"; Course course = patient.Courses.Where(o => o.Id == courseId).SingleOrDefault(); if (course == null) { course = patient.AddCourse(); course.Id = courseId; } // Create a new plan ExternalPlanSetup plan = course.AddExternalPlanSetup(ss); int fractions = 20; double prescribedPercentage = 1.0; DoseValue fractiondose = new DoseValue(2.50, DoseValue.DoseUnit.Gy); // TODO: if needed change to cGy to match your system configuration plan.UniqueFractionation.SetPrescription(fractions, fractiondose, prescribedPercentage); // Add fields const int nfields = 5; ExternalBeamMachineParameters parameters = new ExternalBeamMachineParameters("Varian 23EX", "6X", 600, "STATIC", null); // TODO: change machine id to yours VVector isocenter = ptv.CenterPoint; for (int n = 0; n < nfields; n++) { // add a 10 cm x 10 cm field Beam beam = plan.AddStaticBeam(parameters, new VRect <double>(-50, -50, 50, 50), 0, Math.Round(360.0 / nfields * n, 0), 0, isocenter); } // end of first part. MessageBox.Show("Plan created, open course SuperPlan, Choose Plan1 to view results.", "Varian Developer"); // Set optimization constraints OptimizationSetup optimizationSetup = plan.OptimizationSetup; optimizationSetup.AddPointObjective(ptv, OptimizationObjectiveOperator.Lower, new DoseValue(49.50, DoseValue.DoseUnit.Gy), 100, 100.0); optimizationSetup.AddPointObjective(ptv, OptimizationObjectiveOperator.Upper, new DoseValue(52.00, DoseValue.DoseUnit.Gy), 0, 100.0); optimizationSetup.AddPointObjective(rectum, OptimizationObjectiveOperator.Upper, new DoseValue(20.00, DoseValue.DoseUnit.Gy), 40.0, 100.0); MessageBox.Show("Plan '" + plan.Id + "' in course '" + course.Id + "' for patient '" + patient.Id + "' has been created"); // optimize for 30 iterations if (!plan.Optimize(30).Success) { MessageBox.Show("Optimization failed", "Varian Developer", MessageBoxButton.OK, MessageBoxImage.Error); return; } // run LMC if (!plan.CalculateLeafMotions().Success) { MessageBox.Show("LMC failed", "Varian Developer", MessageBoxButton.OK, MessageBoxImage.Error); return; } // calculate final dose CalculationResult doseCalc = plan.CalculateDose(); if (!doseCalc.Success) { MessageBox.Show("Dose calculation failed, logs shown next.", "Varian Developer", MessageBoxButton.OK, MessageBoxImage.Error); // write calculate logs to a file and show them to the user. string filename = writeCalculationLogs(plan); // 'Start' generated TXT file to launch Notepad window System.Diagnostics.Process.Start(filename); // Sleep for a few seconds to let Excel window start System.Threading.Thread.Sleep(TimeSpan.FromSeconds(3)); return; } MessageBox.Show("Done"); }