/// <summary> /// Create a copy of an existing beam (beams are unique to plans). /// </summary> public static void CopyFluenceBeam(Beam originalBeam, ExternalPlanSetup plan) { var MachineParameters = new ExternalBeamMachineParameters(originalBeam.TreatmentUnit.Id, originalBeam.EnergyModeDisplayName, originalBeam.DoseRate, originalBeam.Technique.Id, string.Empty); // Create a new beam. var collimatorAngle = originalBeam.ControlPoints.First().CollimatorAngle; var gantryAngle = originalBeam.ControlPoints.First().GantryAngle; var PatientSupportAngle = originalBeam.ControlPoints.First().PatientSupportAngle; var isocenter = originalBeam.IsocenterPosition; var metersetWeights = originalBeam.ControlPoints.Select(cp => cp.MetersetWeight); var beam = plan.AddSlidingWindowBeam(MachineParameters, metersetWeights, collimatorAngle, gantryAngle, PatientSupportAngle, isocenter); beam.Id = originalBeam.Id; // Copy control points from the original beam. var editableParams = beam.GetEditableParameters(); for (var i = 0; i < editableParams.ControlPoints.Count(); i++) { editableParams.ControlPoints.ElementAt(i).LeafPositions = originalBeam.ControlPoints.ElementAt(i).LeafPositions; editableParams.ControlPoints.ElementAt(i).JawPositions = originalBeam.ControlPoints.ElementAt(i).JawPositions; } editableParams.WeightFactor = originalBeam.WeightFactor; beam.ApplyParameters(editableParams); var fluence = originalBeam.GetOptimalFluence(); beam.SetOptimalFluence(fluence); }
public static void CopyBeamToPlan(Beam beam, ExternalPlanSetup plansetup, VVector isocenter) { string energyModeDisp = beam.EnergyModeDisplayName; Char[] sep = { '-' }; string energyMode = energyModeDisp.Split(sep).First(); string pfm = energyModeDisp.Split(sep).Count() > 1 ? energyModeDisp.Split(sep).Last() : null; ExternalBeamMachineParameters extParams = new ExternalBeamMachineParameters(beam.TreatmentUnit.Id, energyMode, beam.DoseRate, beam.Technique.Id, pfm); List <double> metersetWeights = GetControlPointWeights(beam); Beam copyBeam = null; if (beam.MLCPlanType == MLCPlanType.VMAT) { copyBeam = plansetup.AddVMATBeam(extParams, metersetWeights, beam.ControlPoints[0].CollimatorAngle, beam.ControlPoints[0].GantryAngle, beam.ControlPoints[beam.ControlPoints.Count - 1].GantryAngle, beam.GantryDirection, beam.ControlPoints[0].PatientSupportAngle, isocenter); } else if (beam.MLCPlanType == MLCPlanType.ArcDynamic) { copyBeam = plansetup.AddConformalArcBeam(extParams, beam.ControlPoints[0].CollimatorAngle, beam.ControlPoints.Count, beam.ControlPoints[0].GantryAngle, beam.ControlPoints[beam.ControlPoints.Count - 1].GantryAngle, beam.GantryDirection, beam.ControlPoints[0].PatientSupportAngle, isocenter); } else if (beam.MLCPlanType == MLCPlanType.DoseDynamic) { var cppPairs = metersetWeights.Zip(metersetWeights.Skip(1), (a, b) => new Tuple <double, double>(a, b)).ToList(); var oddCppPairs = cppPairs.Where((p, i) => i % 2 == 1); if (metersetWeights.Count >= 4 && metersetWeights.Count % 2 == 0 && oddCppPairs.All(p => p.Item1 == p.Item2)) { copyBeam = plansetup.AddMultipleStaticSegmentBeam(extParams, metersetWeights, beam.ControlPoints[0].CollimatorAngle, beam.ControlPoints[0].GantryAngle, beam.ControlPoints[0].PatientSupportAngle, isocenter); } else { copyBeam = plansetup.AddSlidingWindowBeam(extParams, metersetWeights, beam.ControlPoints[0].CollimatorAngle, beam.ControlPoints[0].GantryAngle, beam.ControlPoints[0].PatientSupportAngle, isocenter); } } else { throw new NotImplementedException("Copying this type of beam not implemented"); } var beamParams = copyBeam.GetEditableParameters(); CopyJawAndLeafPositions(beam, beamParams); beamParams.WeightFactor = beam.WeightFactor; copyBeam.ApplyParameters(beamParams); copyBeam.Id = beam.Id; }
/// <summary> /// Create a copy of an existing beam (beams are unique to plans). /// </summary> private static string CopyBeam(Beam originalBeam, ExternalPlanSetup plan, VVector isocenter, bool getCollimatorAndGantryFromBeam) { // Create a new beam. var collimatorAngle = getCollimatorAndGantryFromBeam ? originalBeam.ControlPoints.First().CollimatorAngle : 0.0; var gantryAngle = getCollimatorAndGantryFromBeam ? originalBeam.ControlPoints.First().GantryAngle : 0.0; var metersetWeights = originalBeam.ControlPoints.Select(cp => cp.MetersetWeight); var beam = plan.AddSlidingWindowBeam(MachineParameters, metersetWeights, collimatorAngle, gantryAngle, PatientSupportAngle, isocenter); // Copy control points from the original beam. var editableParams = beam.GetEditableParameters(); for (var i = 0; i < editableParams.ControlPoints.Count(); i++) { editableParams.ControlPoints.ElementAt(i).LeafPositions = originalBeam.ControlPoints.ElementAt(i).LeafPositions; editableParams.ControlPoints.ElementAt(i).JawPositions = originalBeam.ControlPoints.ElementAt(i).JawPositions; } beam.ApplyParameters(editableParams); return(beam.Id); }
// Add beam to the plan public Beam AddBeamToVerifPlan(Beam currBm) { if (verifPln == null) { return(null); } else { bmTech = getMLCBmTechnique(currBm); // find beam technique // Create machine parameters String energy = currBm.EnergyModeDisplayName; String fluence = null; Match EMode = Regex.Match(currBm.EnergyModeDisplayName, @"^([0-9]+[A-Z]+)-?([A-Z]+)?", RegexOptions.IgnoreCase); //format is... e.g. 6X(-FFF) if (EMode.Success) { if (EMode.Groups[2].Length > 0) // fluence mode { energy = EMode.Groups[1].Value; fluence = EMode.Groups[2].Value; } // else normal modes uses default in decleration } ExternalBeamMachineParameters machParam = new ExternalBeamMachineParameters(currBm.TreatmentUnit.Id.ToString(), energy, currBm.DoseRate, currBm.Technique.Id.ToString(), fluence); // Define collimator, gantry and couch angles // Double gantryAng = currBm.ControlPoints.First().GantryAngle; Double collAng = currBm.ControlPoints.First().CollimatorAngle; Double couchAng = 0.0; // MU values for each control point // IEnumerable <double> muSet = currBm.ControlPoints.Select(cp => cp.MetersetWeight).ToList(); // Add beam MU to the list of MU values // muValues.Add(new KeyValuePair <string, MetersetValue>(currBm.Id, currBm.Meterset)); // Start adding beam based on beam technique // if (bmTech == "StaticMLC") { Beam verifBm = verifPln.AddMLCBeam(machParam, new float[2, 60], new VRect <double>(-10.0, -10.0, 10.0, 10.0), collAng, gantryAng, couchAng, verifPlnIso); verifBm.Id = currBm.Id; BeamParameters ctrPtParam = copyControlPoints(currBm, verifBm); verifBm.ApplyParameters(ctrPtParam); return(verifBm); } else if (bmTech == "StaticSegWin") { Beam verifBm = verifPln.AddMultipleStaticSegmentBeam(machParam, muSet, collAng, gantryAng, couchAng, verifPlnIso); verifBm.Id = currBm.Id; BeamParameters ctrPtParam = copyControlPoints(currBm, verifBm); verifBm.ApplyParameters(ctrPtParam); return(verifBm); } else if (bmTech == "StaticSlidingWin") { Beam verifBm = verifPln.AddSlidingWindowBeam(machParam, muSet, collAng, gantryAng, couchAng, verifPlnIso); verifBm.Id = currBm.Id; BeamParameters ctrPtParam = copyControlPoints(currBm, verifBm); verifBm.ApplyParameters(ctrPtParam); return(verifBm); } else if (bmTech == "ConformalArc") { Beam verifBm = verifPln.AddConformalArcBeam(machParam, collAng, currBm.ControlPoints.Count(), currBm.ControlPoints.First().GantryAngle, currBm.ControlPoints.Last().GantryAngle, currBm.GantryDirection, couchAng, verifPlnIso); verifBm.Id = currBm.Id; BeamParameters ctrPtParam = copyControlPoints(currBm, verifBm); verifBm.ApplyParameters(ctrPtParam); return(verifBm); } else if (bmTech == "VMAT") { Beam verifBm = verifPln.AddVMATBeam(machParam, muSet, collAng, currBm.ControlPoints.First().GantryAngle, currBm.ControlPoints.Last().GantryAngle, currBm.GantryDirection, couchAng, verifPlnIso); verifBm.Id = currBm.Id; BeamParameters ctrPtParam = copyControlPoints(currBm, verifBm); verifBm.ApplyParameters(ctrPtParam); return(verifBm); } else // null { return(null); } } }
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); } }