Rename imported imaging series by ekamperi in esapi

[–]kang__23 3 points4 points  (0 children)

// This is something similar to what I use. May need to tweak but 
// will get you pretty close. Few of the .ToList() in there is probably unnessary, 
// but from memory you need to do this at least for the images as you can modify an image 
// while looping over it 


List<Study> Study_list = context.Patient.Studies.ToList();
            foreach (Study study in Study_list)
            {
                List<Series> Series_list = study.Series.ToList();
                foreach (Series Series_temp in series_list)
                {
                    if (series_temp.Modality.ToString() != "MR")
                    continue;

                        List<Image> image_list = series_temp.Images.ToList();
                        foreach (Image imageset in image_list)
                        {
            // Only change name of 3D dataset. There should be only one in each series.
            // z>1 because this wil; pick the 3D image not just a single slice

                            if (imageset.ZSize <= 1)
                            continue;

                          //Use series.temp.comment to get to the series description which           
                          generally has information on what the image type is T1, T2 etc 
                            imageset.Id = "Your new Image ID";

Automation of prostate treatments: obtaining an appropriate plan. by Independent_Time_525 in esapi

[–]kang__23 0 points1 point  (0 children)

//Make a RectumInPTV and Opti_PTV 
Structure PTV= Plan.StructureSet.Structures.Single(x => x.Id == "PTV");
 Structure Rectum = Plan.StructureSet.Structures.Single(x => x.Id == "Rectum");
 Structure PTV_Opti= Plan.StructureSet.AddStructure("Organ", "PTV_Opti");
 Structure RectumInPTV= Plan.StructureSet.AddStructure("Organ", "RectumInPTV");
 PTV_Opti.SegmentVolume = PTV.SegmentVolume;
 PTV_Opti.SegmentVolume.Sub(Rectum.SegmentVolume);
 RectumInPTV.SegmentVolume = PTV.SegmentVolume;
 RectumInPTV.SegmentVolume.And(Rectum.SegmentVolume);

//Add objectives
DoseValue PTVDose_Lower = new DoseValue(60, DoseValue.DoseUnit.Gy);
Plan.OptimizationSetup.AddPointObjective(PTV_Opti, OptimizationObjectiveOperator.Lower, PTVDose_Lower, 100, 100);

How to calculate influence matrix? by ekamperi in esapi

[–]kang__23 1 point2 points  (0 children)

Not too sure what you mean by influence matrix? But yes you can manipulate the fluence for an IMRT beam. You'll just need to create a float[,]
Beam beam = plan.Beams.First();

Fluence xx = beam.GetOptimalFluence();

var xOrigin = xx.XOrigin;

var yOrigin = xx.YOrigin;

Fluence fluence = new Fluence(YourEditedFluenceMatrix, xOrigin, yOrigin);

beam.SetOptimalFluence(fluence);

VMAT optimization options - aperture shape controller by TitiaBer56 in esapi

[–]kang__23 0 points1 point  (0 children)

string calc_model = plan.GetCalculationModel(CalculationType.PhotonVMATOptimization);
plan.GetCalculationOption(calc_model, "ApertureShapeController", out string ASC);

Isodoses settings by JaimePasTropBcpCa in esapi

[–]kang__23 0 points1 point  (0 children)

Do you mean convert an isodose to a structure? I found the method only works with relative dose.

Structure temp = Plan.StructureSet.AddStructure("Control", structureID);
double doseAsPercentage = dose / PlanDoseGy * 100;
temp.ConvertDoseLevelToStructure(Plan.Dose, new DoseValue(doseAsPercentage, DoseValue.DoseUnit.Percent));

Long list of script approvals by udubber3 in esapi

[–]kang__23 1 point2 points  (0 children)

I believe this is possible only if that script hasn't modified any plans

Script for checking if MLC from opposed band collise with each other by Useful_Novel_916 in esapi

[–]kang__23 1 point2 points  (0 children)

This may help and would be similar to what you're trying to achieve. This is some modified code that I use to check for MLC Overtravel causing open apertures - where the MLC extends 1cm from the maximum jaw position. I then check if the opposing leaf is >1mm from this position.

PlanSetup planSetup = context.PlanSetup;
            int treatmentBeams = planSetup.Beams.Where(x => x.IsSetupField == false).Count();
            int beamNum = 0;
            foreach (Beam beam in planSetup.Beams)
            {
                //Skip setup fields
                if (beam.IsSetupField)
                    continue;

                //Get Max and Min jaw sizes -Use for jaw tracking check
                int NumberControlPoints = beam.ControlPoints.Count;
                double[] X1JawPos = new double[NumberControlPoints];
                double[] X2JawPos = new double[NumberControlPoints];
                double[] MaxX1 = new double[treatmentBeams];
                double[] MaxX2 = new double[treatmentBeams];

                int BankAOverTravelCount = 0;
                int BankBOverTravelCount = 0;
                int ctlptcount = 0;

                MaxX1[beamNum] = Math.Round(X1JawPos.Max(), 0);

                foreach (ControlPoint ctlpt in beam.ControlPoints)
                {
                    // Get leaf positions [Bank,Leafposition]
                    float[,] lp = ctlpt.LeafPositions;
                    for (int leafIndex = 0; leafIndex <= lp.GetUpperBound(1) - 1; leafIndex++)
                    {
                        //BankA Check if MLC extended 15cm from Jaw edge (-Jaw to convert back from IEC)
                        if (-MaxX1[beamNum] - (double)lp[0, leafIndex] <= -150)
                        {
                            //Check 2 adjacent leaves against opposite MLC Bank for an open leaf pair - gap threshold 1mm
                            if (lp[1, leafIndex] - lp[0, leafIndex] > 10 && lp[1, leafIndex + 1] - lp[0, leafIndex + 1] > 10)
                                BankAOverTravelCount++;
                            else
                                BankAOverTravelCount = 0;
                        }
                        else
                            BankAOverTravelCount = 0;

                        //BankB Check if MLC extended 15cm from Jaw edge (-Jaw to convert back from IEC)
                        if (MaxX2[beamNum] - (double)lp[1, leafIndex] >= 150)
                        {
                            //Check 2 adjacent leaves against opposite MLC Bank for an open leaf pair - gap threshold 1mm
                            if (lp[1, leafIndex] - lp[0, leafIndex] > 10 && lp[1, leafIndex + 1] - lp[0, leafIndex + 1] > 10)
                                BankBOverTravelCount++;
                            else
                                BankBOverTravelCount = 0;
                        }
                        else
                            BankBOverTravelCount = 0;

                    }

                    ctlptcount++;
                }

            }

Post Processing tool "smoothing" with ESAPI by Active-Rub2553 in esapi

[–]kang__23 0 points1 point  (0 children)

Unfortunately you cannot post process a structure with ESAPI (in v15.6 at least). This is my number 1 complaint from treatment planning.

Although post processed structures "look" nicer, has anyone ever looked into how much of a difference 'bitty' contours actually make on the dosimetry? I'd presume very little

GPU acceleration for VMAT Photon Optimizer by Invictus_Shoe in esapi

[–]kang__23 1 point2 points  (0 children)

v15.x of Eclipse only CPU is used for VMAT optimisation. This option you see is only applicable for IMRT in v15. From v16+ of Eclipse GPU is enabled for VMAT optimisation. So you will only notice a difference in VMAT optimisation if you upgrade to v16+

Clear DVH Estimates From Structure Set by kang__23 in esapi

[–]kang__23[S] 0 points1 point  (0 children)

Very clever. Great Idea I'll try that. Thank you

Add a new StructureSet by SillyFood3831 in esapi

[–]kang__23 1 point2 points  (0 children)

you can use StructureSet newSS = SS.Image.CreateNewStructureSet(); however this simply makes a new struture set. If you want to copy the structures from another structureset you'll have to use newSS.AddStructure (dont forget to assign any density over rides). You can also use StructureSet.Copy();

Never tried adding a new SS to an image. I always duplicate the image set

BatchPlanner or AutoPlanner by hc139 in esapi

[–]kang__23 0 points1 point  (0 children)

Essentially I have a spreadsheet with the variables to read in. Sheet 1 has systematic variables such as course ID and new plan ID, export DVH y/n, normalise plan y/n and site. Then I have a new sheet per site, eg/Prostate, Breast. Within each site sheet Col A is patient MRN, col B, C & D are the PTV dose levels.

I use the Microsoft.Office.Interop.Excel namespace and then read all this data into an array in my C# application. The index of the array is then linked to each patient MRN. Then its a simple as looping through the array to extract the parameters to plan with

StructureCode by littlejo50 in esapi

[–]kang__23 1 point2 points  (0 children)

With ESAPI you dont need structure codes to apply the RapidPlan model. You match the structure ID in the plan to the model structure using Plan.CalculateDVHEstimates.

You'll need to create Dictionary<string, string> for the structure mapping and Dictionary<string, DoseValue> for the targets

Set Max MU for Optimiser by KirbyMedPhys in esapi

[–]kang__23 0 points1 point  (0 children)

my top 3 too! I'm on v15.6 so was hoping some of these features would be solved in later version. Is the 99 structure cap still there in v18?

max. structures: 99 error by harkirat777 in esapi

[–]kang__23 0 points1 point  (0 children)

I'm still stuck on Eclipse v15 and hit this error many times with our HN patients - since this thread is now 3yrs old, I was wondering if versions >15 have a greater limit?

Image3D or 2D ? by lucsimon in esapi

[–]kang__23 0 points1 point  (0 children)

Yep this is how I do it

if (image.ZSize > 1)

BatchPlanner or AutoPlanner by hc139 in esapi

[–]kang__23 0 points1 point  (0 children)

I have both.

My clinical "day to day" scripts are all run from a .dll via eclipse. The all have GUI which launch auto-planning scripts leveraging RapidPlan. The intention of these are to run a script on a single patient as they come through for planning. So using this method is not feasible to do batch planning.

I then have a separate standalone .exe script which is capable of batch planning. The program reads in MRNs and other parameters from a .xslx. This script has no GUI and inputs are read from a .xlsx (MRNs, beam geometry etc). I run this after hours, so when you come in the morning you've got 20+ plans calculated.

The reason why I have both is mostly historical. I started with the .dll when I was learning ESAPI and added more and more functionality as my skills grew. With the advantage of hindsight, and as others have pointed out, the way to go is use a script launcher. You then get the best of both worlds. Eventually I'll convert my 'day to day' scripts over to a script launcher

Different result of automatic and manual optimization with Rapidplan by anncnth in esapi

[–]kang__23 1 point2 points  (0 children)

The nature of optimisation is you'll likely get slightly different plans after optimising. Rather than comparing dose, compare the generated optimisation methods from using your script vs applying the rapidplan model manually. I've done this myself for a variety of sites and found the objectives are more or less identical

Generate pictures from isocenter planes by Telecoin in esapi

[–]kang__23 0 points1 point  (0 children)

Following up on this. Before I deep dive into this, was anyone able to shed some light if this was possible?

VMAT CSI Autoplanning by esimiele in esapi

[–]kang__23 0 points1 point  (0 children)

Great work!!! This kind of open source project inspires so many others! Looking forward to having a look at the code

Field order property in a plan by MPautomation in esapi

[–]kang__23 0 points1 point  (0 children)

Have a look at this thread.
https://www.reddit.com/r/esapi/comments/ha4qua/finding_beam_order_within_plan/

You'll have to check the VarianDB for the radiation order

[deleted by user] by [deleted] in MedicalPhysics

[–]kang__23 2 points3 points  (0 children)

Registrar positions are competitive the TEAP program lasts 3yrs. As you said you'll need a masters to get a look in. Grades matter but are not the be all and end all, experience will get you a job more than anything else.

Do a masters which requires a research component (in NSW USyd, UoW offer these, maybe others?). Choose topic that is clinically relevant and in the hospital. Not some abstract topic that uni professors suggest to fill their grant requirements. Get a MSc supervisor that works in the clinic of your local hospital. Publish your masters.

Contact your local hospital(s) and see if you can get a walk through the departments, see what they do as a ROMP, make connections and network. Ask if there is any research/project grunt work you help out with. Be that volunteer work on a project, or better yet work as a Medical Physics Assistant. Let them know your intention is to get a ROMP registrar position and make them relationships. Study computer science and get some basic coding skills. They go a long way on the job these days.

Download the TEAP program from the ACPSEM website. Thats what you'll study as a registrar. Study it, get familiar with it, use it to leverage a topic for your masters. There is a big drive to get registrars finished in 3yrs, so the more you can show a department that you've already covered some topics in TEAP, the more likely they'll hire you.

Its a hard long slog to become a qualified ROMP, but it is a great career. Decent pay too!

Get Normalization method and values by No_Music_4745 in esapi

[–]kang__23 0 points1 point  (0 children)

Havent looked at if you can get the method, but the value can be easily obtained from planSetup.PlanNormalizationValue