Пример #1
0
        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();
            }
        }
Пример #2
0
        /// <summary>
        /// Create a copy of an existing beam (beams are unique to plans).
        /// </summary>
        public static void CopyStaticMlcBeam(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 jawPositions        = originalBeam.ControlPoints.First().JawPositions;
            var leafPositions       = originalBeam.ControlPoints.First().LeafPositions;
            var isocenter           = originalBeam.IsocenterPosition;

            var beam = plan.AddMLCBeam(MachineParameters, leafPositions, jawPositions, collimatorAngle, gantryAngle,
                                       PatientSupportAngle, isocenter);

            if (plan.Beams.Where(b => b.Id == originalBeam.Id).Count() > 0)
            {
                throw new InvalidOperationException($"{originalBeam.Id} already exists");
            }

            beam.Id = originalBeam.Id;

            // Copy control points from the original beam.
            var editableParams = beam.GetEditableParameters();

            editableParams.WeightFactor = originalBeam.WeightFactor;
            beam.ApplyParameters(editableParams);
        }
Пример #3
0
        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);
        }
Пример #4
0
        private void createMlcField(float[,] flncMtx, float rotAng)
        {
            int    height = flncMtx.GetLength(0);
            int    width  = flncMtx.GetLength(1);
            double xOrg   = -0.5 * ((double)width * flncRes - flncRes);
            double yOrg   = 0.5 * ((double)height * flncRes - flncRes);
            // Create fluence
            Fluence mlcFlnc = new Fluence(flncMtx, xOrg, yOrg);
            // Add beam
            Beam currBm = currPln.AddMLCBeam(currMachParam, new float[2, 60], new VRect <double>(-50.0, -50.0, 50.0, 50.0), rotAng, 0.0, 0.0, currIsoCtr);

            currBm.SetOptimalFluence(mlcFlnc);
            currPln.CalculateLeafMotions(vlmcOpt);
        }
 // 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);
         }
     }
 }
Пример #6
0
        public bool CopyAndCreate(Application app, string ptId_Tgt, string crsId_Tgt, string plnId_Tgt, string structId_Tgt, PlanParameters plnParam_Ref)
        {
            //Open patient//
            PatientSummary ptSumm = app.PatientSummaries.FirstOrDefault(ps => ps.Id == ptId_Tgt);

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

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

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

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

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

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

                    default:
                        Console.WriteLine("--At least one of the beams is unidentified, plan is not created.\n");
                        app.ClosePatient();
                        return(false);
                    }
                }
                //Set the plan normalization value//
                pln.PlanNormalizationValue = plnParam_Ref.PlnNormFactr;
                //Set the plan calculation model//
                pln.SetCalculationModel(CalculationType.PhotonVolumeDose, plnParam_Ref.CalcModel);
                //If one of the beams is static IMRT, compute dose to enforce MUs to beams//
                if (plnParam_Ref.BmParamLs.Any(bm => bm.MLCBmTechnique == "StaticSegWin" || bm.MLCBmTechnique == "StaticSlidingWin"))
                {
                    Console.WriteLine("--Start computing static beam IMRT plan.");
                    pln.CalculateDoseWithPresetValues(muValues);
                }
                Console.WriteLine("-Finish plan creation.\n");
                app.SaveModifications();
                app.ClosePatient();
                return(true);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                app.ClosePatient();
                return(false);
            }
        }
Пример #7
0
        private void set_beams(List <VVector> isoLocations)
        {
            //DRR parameters (dummy parameters to generate DRRs for each field)
            DRRCalculationParameters DRR = new DRRCalculationParameters();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                //}
            }
            MessageBox.Show("Beams placed successfully!\nPlease proceed to the optimization setup tab!");
        }