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); }
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; }
static void Execute(Application app) { Patient pat = app.OpenPatientById("exercise5-0"); try { pat.BeginModifications(); const string courseId = "AutoPlanned"; Course course = pat.Courses.Where(o => o.Id == courseId).SingleOrDefault(); if (course == null) { if (course == null) { course = pat.AddCourse(); course.Id = courseId; } } StructureSet ss = pat.StructureSets.First(x => x.Id == "CT_1"); if (course.CanAddPlanSetup(ss)) { // find the PTV Structure ptv = ss.Structures.First(x => x.Id == "PTV"); // Put isocenter to the center of the ptv. var isocenter = ptv.CenterPoint; //add plan and beams ExternalPlanSetup plan = course.AddExternalPlanSetup(ss); plan.SetPrescription(5, new DoseValue(2, DoseValue.DoseUnit.Gy), 1.0); Beam g0 = plan.AddMLCBeam(MachineParameters, null, new VRect <double>(-10, -10, 10, 10), 0, 0, 0, isocenter); Beam g180 = plan.AddMLCBeam(MachineParameters, null, new VRect <double>(-10, -10, 10, 10), 0, 180.0, 0, isocenter); // fit beam jaws and MLC bool useAsymmetricXJaw = true, useAsymmetricYJaws = true, optimizeCollimatorRotation = true; g0.FitCollimatorToStructure(new FitToStructureMargins(0), ptv, useAsymmetricXJaw, useAsymmetricYJaws, optimizeCollimatorRotation); FitToStructureMargins margins = new FitToStructureMargins(1); JawFitting jawFit = JawFitting.FitToRecommended; OpenLeavesMeetingPoint olmp = OpenLeavesMeetingPoint.OpenLeavesMeetingPoint_Middle; ClosedLeavesMeetingPoint clmp = ClosedLeavesMeetingPoint.ClosedLeavesMeetingPoint_BankOne; g0.FitMLCToStructure(margins, ptv, optimizeCollimatorRotation, jawFit, olmp, clmp); g180.FitMLCToStructure(margins, ptv, optimizeCollimatorRotation, jawFit, olmp, clmp); // format the field ids g0.Id = string.Format("g{0}c{1}", g0.GantryAngleToUser(g0.ControlPoints[0].GantryAngle), g0.CollimatorAngleToUser(g0.ControlPoints[0].CollimatorAngle) ); g180.Id = string.Format("g{0}c{1}", g180.GantryAngleToUser(g180.ControlPoints[0].GantryAngle), g180.CollimatorAngleToUser(g180.ControlPoints[0].CollimatorAngle) ); app.SaveModifications(); } } finally { app.ClosePatient(); } }
// Create verification plan public ExternalPlanSetup CreateVerificationPlan(StructureSet pStructSt, Course verifCrs, String verifPlnID) { verifPln = verifCrs.AddExternalPlanSetupAsVerificationPlan(pStructSt, currPln); verifPln.Id = verifPlnID; // Copy and set prescription info// verifPln.SetPrescription(1, currPln.DosePerFraction, currPln.TreatmentPercentage); // Remove target structure if available (needed for v 16) verifPln.SetTargetStructureIfNoDose(null, null); return(verifPln); }
public static Tuple <List <List <Structure> >, List <List <Structure> >, List <List <string> >, bool> StartOptimizer(ScriptContext context, HNPlan hnPlan, List <List <Structure> > matchingStructures, int numIterations, List <Tuple <bool, double[], string> > features, Tuple <string, string, bool> beamParams) //Returns list of matching structures { // Check for patient plan loaded ExternalPlanSetup plan = context.ExternalPlanSetup; Patient patient = context.Patient; StructureSet ss = context.StructureSet; Course course = context.Course; Image image3d = context.Image; //Create two VMAT beams BeamMaker(ref plan, ss, plan.TotalDose.Dose, beamParams); //set prescriptions dose int numFractions = hnPlan.Fractions; int dosePerFraction = (int)hnPlan.PrescriptionDose / numFractions; plan.SetPrescription(numFractions, new DoseValue(dosePerFraction, "cGy"), 1); //matchingStructures is the same length as hnPlan.ROIs.count //Now set optimization constraints List <List <Structure> > optimizedStructures = OptObjectivesEditing.SetConstraints(ref plan, hnPlan, matchingStructures, true); //true to check for opti structures, returns new matching list of structures List <List <double[, ]> > choppedContours; List <double[]> planes; string contraParName; if (features[0].Item1 == true) //parotid segmentation feature { Tuple <List <List <double[, ]> >, string, List <double[]> > choppedAndName = ParotidChop(ref plan, hnPlan, matchingStructures, ss, context); choppedContours = choppedAndName.Item1; contraParName = choppedAndName.Item2; planes = choppedAndName.Item3; } else { choppedContours = new List <List <double[, ]> >(); contraParName = ""; planes = new List <double[]>(); } Tuple <bool, List <List <string> > > optimData = Optimize(choppedContours, planes, ref plan, ref ss, hnPlan, context, optimizedStructures, matchingStructures, contraParName, numIterations, features, beamParams); bool isPassed = optimData.Item1; List <List <string> > updatesLog = optimData.Item2; return(Tuple.Create(optimizedStructures, matchingStructures, updatesLog, isPassed)); }
/// <summary> /// Create PTV from CTV and fit collimator jaws to the target. /// </summary> public static void GenerateBeamGeometry(ExternalPlanSetup plan, double dosePerFraction, int numberOfFractions, double ptvMargin, string ctvId) { // Prescription const double prescribedPercentage = 1.0; // Note: 100% corresponds to 1.0 var dose = new DoseValue(dosePerFraction, DoseValue.DoseUnit.Gy); plan.SetPrescription(numberOfFractions, dose, prescribedPercentage); Trace.WriteLine("\nCreating PTV from CTV..."); CreatePTVFromCTV(plan, ptvMargin, ctvId); // Match plan structures to model structures var structureMatches = GetStructureMatches(plan); if (!structureMatches.Any()) { MessageBox.Show("Structure match could not be found", "No model structures found", MessageBoxButton.OK, MessageBoxImage.Error); return; } // Generate PTV that does not overlap with OARs. // Identify the structures to be spared by their IDs in the RapidPlan model. Trace.WriteLine("Subtracting OARs from PTV..."); var sparedOrgans = new List <string> { "Rectum" }; structureMatches = SubtractOARsFromPTV(plan, structureMatches, sparedOrgans); var ptvId = structureMatches.Single(x => x.Value.StructureType == ModelStructureType.Target).Key; var ptv = plan.StructureSet.Structures.Single(x => x.Id == ptvId); Trace.WriteLine("PTV successfully generated.\n"); // Fit jaws to target and add treatment fields. const double collRtn = 0.0; var jawPositions = GantryAngles.ToDictionary(angle => angle, angle => FitJawsToTarget(plan, ptv, angle, collRtn, MarginForJawFittingInMM)); var isocenter = ptv.CenterPoint; foreach (var item in jawPositions) { plan.AddStaticBeam(MachineParameters, item.Value, CollimatorAngle, item.Key, PatientSupportAngle, isocenter); } Trace.WriteLine("\nJaws successfully fitted to target.\n"); }
/// <summary> /// Copies a already created verification plan to: /// 1. The same structure set if one is not inpput /// 2. A new phantom structure set if one is input /// </summary> /// <param name="planToCopy"></param> /// <param name="course"></param> /// <param name="phantomStructureSetId"></param> /// <param name="phantomPatientId"></param> /// <param name="phantomStudyId"></param> /// <returns></returns> public static ExternalPlanSetup CopyVerificationPlan(ExternalPlanSetup planToCopy, Course course, string phantomStructureSetId, string phantomPatientId, string phantomStudyId) { if (course.PlanSetups.Any(p => p.Id == planToCopy.Id)) { GlobalLogger.Instance.Trace($"A plan with ID {planToCopy.Id} already exists in course {course.Id}."); throw new Exception("A plan with the same ID as the source plan already exists in the destination course."); } if (String.IsNullOrWhiteSpace(phantomStructureSetId)) { return((ExternalPlanSetup)course.CopyPlanSetup(planToCopy)); } else { StructureSet structureSet; if (String.IsNullOrWhiteSpace(phantomPatientId)) { structureSet = planToCopy.Course.Patient.StructureSets.Where(s => s.Id == phantomStructureSetId).Single(); } else { structureSet = planToCopy.Course.Patient.CopyImageFromOtherPatient(phantomPatientId, phantomStudyId, phantomStructureSetId); GlobalLogger.Instance.Trace($"New phantom structure set {structureSet.Id} created from structure set {phantomStructureSetId} in patient ID {phantomPatientId}"); } ExternalPlanSetup verifiedPlan = (ExternalPlanSetup)planToCopy.VerifiedPlan; ExternalPlanSetup copyPlan = course.AddExternalPlanSetupAsVerificationPlan(structureSet, verifiedPlan); copyPlan.Id = planToCopy.Id; copyPlan.SetPrescription((int)planToCopy.NumberOfFractions, planToCopy.DosePerFraction, planToCopy.TreatmentPercentage); GlobalLogger.Instance.Trace($"Added verification plan created from {verifiedPlan.Id} (Course {verifiedPlan.Course.Id}) using phantom structure set {structureSet.Id}"); foreach (Beam b in planToCopy.Beams) { VVector iso = b.IsocenterPosition - planToCopy.StructureSet.Image.UserOrigin; iso += structureSet.Image.UserOrigin; BeamCopier.CopyBeamToPlan(b, copyPlan, iso);// setup beam isocenters to user origin of the QA device GlobalLogger.Instance.Trace($"Copied {b.Id} to verification plan"); } return(copyPlan); } }
private void newPlan_btn_Click(object sender, RoutedEventArgs e) { Course c2 = null; if (p.Courses.Where(x => x.Id == course_txt.Text).Count() == 0) { c2 = p.AddCourse(); c2.Id = course_txt.Text; } else { c2 = p.Courses.First(x => x.Id == course_txt.Text); } ExternalPlanSetup ps2 = c2.AddExternalPlanSetup(ps.StructureSet); //doses should all be the same.t //ps2.DosePerFraction = ps.DosePerFraction; //read only //ps2.TotalDose = ps.TotalDose;//read only ps2.SetPrescription( (int)ps.NumberOfFractions, ps.DosePerFraction, ps.TreatmentPercentage); //I've chnaged this down below. Currently, the calculation will take place with preset monitor units //making it the same as the plan its copied from but then I scale the normaliztation factor by 1.3% because the discover is not in the beam. ps2.PlanNormalizationValue = val * ps.PlanNormalizationValue; //val = (double)Convert.ToDouble(Input.Text); bool valid = double.TryParse(Input.Text.ToString(), out val); ps2.PlanNormalizationValue = val + no_norm; //ps2.TreatmentPercentage = ps.TreatmentPercentage;//read only //ps2.AddMLCBeam() ps2.Id = plan_txt.Text; List <KeyValuePair <string, MetersetValue> > mu_list = new List <KeyValuePair <string, MetersetValue> >(); /*foreach (FieldInfo fi in fields)########################*/ for (int t = 0; t < fields.Count(); t++) { FieldInfo fi = fields[t]; Beam b2; if (fi.gantry_direction == 0) { b2 = ps2.AddSlidingWindowBeam(fi.Ebmp, fi.cpInfos.Select(x => x.meterSet), fi.collAngle, fi.gantry, fi.couch, fi.isocenter); } else { b2 = ps2.AddVMATBeam(fi.Ebmp, fi.cpInfos.Select(x => x.meterSet), fi.collAngle, fi.gantry, fi.gantry_stop, fi.gantry_direction, fi.couch, fi.isocenter); } int cploc = 0; //if (fi.applicator != null) { b2.Applicator = fi.applicator; } BeamParameters beamp = fi.bp; //b2.ApplyParameters(new BeamParameters(ControlPoint cp)) //int cploc = 0; //foreach (cpInfo cpi in fi.cpInfos) //double MU_old = 0; foreach (ControlPointParameters cpp in beamp.ControlPoints) //for(int xx=0; xx< beamp.ControlPoints.Count(); xx++) { /* ControlPointParameters cpp= beamp.ControlPoints[xx];*/ float[,] leafPos = new float[2, 60]; int leafloc = 0; double x1 = cpp.JawPositions.X1; double x2 = cpp.JawPositions.X2; cpInfo cpi = fi.cpInfos[cploc]; //foreach (cpDetail cpd in cpi.cpDetails)##################### for (int dd = 0; dd < cpi.cpDetails.Count(); dd++) { cpDetail cpd = cpi.cpDetails[dd]; //sometimes the errors show that the difference will overlap the leaves. //here we check for the overla[p and if there is n overlap, leaf B just gets set to 0.1 less than the leaf A position. //thus ignoring the deviation fort that leaf pair. if (cpd.leafB + Convert.ToSingle(cpd.deviationB) > cpd.leafA + Convert.ToSingle(cpd.deviationA)) { leafPos[1, leafloc] = cpd.leafA + (float)cpd.deviationA; leafPos[0, leafloc] = leafPos[1, leafloc] - (float)0.1; } else { /*if (cpd.leafA + (float)cpd.deviationA < x1) * { * * leafPos[1, leafloc] = (float)x1 + (float)0.5; * leafPos[0, leafloc] = (float)x1; * } * else if (cpd.leafA + (float)cpd.deviationA > x2) * { * leafPos[1, leafloc] = (float)x2; * if(cpd.leafB + (float)cpd.deviationB > x2) * { * leafPos[0, leafloc] = (float)x2 - (float)0.5; * } * else * { * leafPos[0, leafloc] = cpd.leafB + (float)cpd.deviationB; * } * } * else * { * leafPos[1, leafloc] = cpd.leafA + Convert.ToSingle(cpd.deviationA); * leafPos[0, leafloc] = cpd.leafB + (float)cpd.deviationB; * }*/ leafPos[1, leafloc] = cpd.leafA + (float)cpd.deviationA; leafPos[0, leafloc] = cpd.leafB + (float)cpd.deviationB; //leafPos[0, leafloc] = cpd.leafA + Convert.ToSingle(cpd.deviationA); //leafPos[1, leafloc] = cpd.leafB + Convert.ToSingle(cpd.deviationB); } leafloc++; } ////start with the first leaf position, and then interoplate all the rest. //float leaf_oldA = 0; //float leaf_oldB = 0; //for (int i = 0; i < cpi.cpDetails.Count(); i++) //{ // if (i == 0) // { // leafPos[0, i] = cpi.cpDetails[i].leafA; // leafPos[1, i] = cpi.cpDetails[i + 1].leafB; // leaf_oldA = leafPos[0, i]; // leaf_oldB = leafPos[1, i]; // //mU_old = cpi.meterSet[i]; // } // else // { // //let the interpolation begin. // //first the MU // } //} //beamp.SetAllLeafPositions(leafPos); //ControlPointParameters cpp = beamp.ControlPoints[cploc] cpp.LeafPositions = leafPos; //double check to see if this has to be applied every time. VMAT code is taking a long time. //********************************** b2.ApplyParameters(beamp); //********************************** cploc++; } //calculate the dose for each of the fields. mu_list.Add(new KeyValuePair <string, MetersetValue>(b2.Id, fi.MU)); } ps2.CalculateDoseWithPresetValues(mu_list); //ps2.PlanNormalizationMethod = ps.PlanNormalizationMethod;\ //need to renormalize by 1.3% in order to take into account the Discover that we cannot add to the newly calculated plan. //ps2.PlanNormalizationValue = val * ps2.PlanNormalizationValue; //val = (double)Convert.ToDouble(Input.Text); if (double.TryParse(Input.Text.ToString(), out val)) { ps2.PlanNormalizationValue = val + no_norm; } MessageBox.Show($"{plan_txt.Text} created successfully."); }
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); } }
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"); }
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!"); }
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); }