Varian-Code-Samples icon indicating copy to clipboard operation
Varian-Code-Samples copied to clipboard

Plan Quality Metrics Script; multiple PTV metrics within the same script

Open bilaljalal opened this issue 6 years ago • 6 comments

**I have a question related to Plan Quality Metrics Script, regarding multiple PTV metrics within the same script, if you have SIB case either IMRT or VMAT when you have 2 or more PTVs inside the plan. The script is designed to work with one target only. I tried to work around with the script as we do with other structures by adding the following; lets consider we have 3 PTVs 70Gy, 66 Gy and 60 Gy

This is what I added inside UserDefinedMetrics.cs

// quality metrics for the target
    public class Target
    {
      public static PlanQualityMetric[] getPQMs(DoseValue totalPrescribedDose)
      {
        PlanQualityMetric[] PQMs = 
          {
            new VolumeAtDose("V[100%(Rx) > 95%]", new DoseValue(totalPrescribedDose.Dose*1.0, totalPrescribedDose.Unit),   95.0, 0.9474, VolumePresentation.Relative, PQMUtilities.LimitType.lower),
            new VolumeAtDose("V[93%(Rx) > 99%]", new DoseValue(totalPrescribedDose.Dose*0.93, totalPrescribedDose.Unit),   99.0, 0.9596, VolumePresentation.Relative, PQMUtilities.LimitType.lower),
            new VolumeAtDose("V[110%(Rx) < 20%]", new DoseValue(totalPrescribedDose.Dose*1.10, totalPrescribedDose.Unit),   20.0, 1.25, VolumePresentation.Relative, PQMUtilities.LimitType.upper)
          };
        return PQMs;
      }
    }

        // quality metrics for the PTV70 structure

        public  static class PTV70
        {
            public static PlanQualityMetric[] PQMs =
      {
           new VolumeAtDose("V70Gy > 95%",new DoseValue(7000.0, DoseValue.DoseUnit.cGy), 95.0, 0.9474),
           new VolumeAtDose("V65.1Gy > 99%",new DoseValue(6510.0, DoseValue.DoseUnit.cGy), 99.0, 0.9596),
           new VolumeAtDose("V77Gy < 20%",new DoseValue(7700.0, DoseValue.DoseUnit.cGy), 20.0, 1.25)
          };
                 public static string[] searchIds = { "PTV70", "PTV_70", "PTV-70", "PTV-70Gy", "PTV_70Gy" };

        }

        // quality metrics for the PTV66 structure

        public static class PTV66
        {
            public static PlanQualityMetric[] PQMs =
      {
           new VolumeAtDose("V66Gy > 95%",new DoseValue(6600.0, DoseValue.DoseUnit.cGy), 95.0, 0.9474),
           new VolumeAtDose("V61.38Gy > 99%",new DoseValue(6138.0, DoseValue.DoseUnit.cGy), 99.0, 0.9596),
           new VolumeAtDose("V72.6Gy < 20%",new DoseValue(7260.0, DoseValue.DoseUnit.cGy), 20.0, 1.25)
          };
            public static string[] searchIds = { "PTV66", "PTV_66", "PTV-66","PTV-66Gy", "PTV_66Gy" };
        }

        // quality metrics for the PTV60 structure

        public static class PTV60
        {
            public static PlanQualityMetric[] PQMs =
      {
           new VolumeAtDose("V60Gy > 95%",new DoseValue(6000.0, DoseValue.DoseUnit.cGy), 95.0, 0.9474),
           new VolumeAtDose("V55.8Gy > 99%",new DoseValue(5580.0, DoseValue.DoseUnit.cGy), 99.0, 0.9596),
           new VolumeAtDose("V66Gy < 20%",new DoseValue(6600.0, DoseValue.DoseUnit.cGy), 20.0, 1.25)
          };
            public static string[] searchIds = { "PTV60", "PTV_60", "PTV-60","PTV-60Gy", "PTV_60Gy" };
        }

and also I added the following to PQMReporter.cs

// find stats for PTV structures
            addStructurePQM(plan, ss, PTV70.searchIds, PTV70.PQMs, writer);
            addStructurePQM(plan, ss, PTV66.searchIds, PTV66.PQMs, writer);
            addStructurePQM(plan, ss, PTV60.searchIds, PTV60.PQMs, writer);

But when I run the script and I get the report The analysis for PTVs are not correct; for example first criteria ( new VolumeAtDose("V60Gy > 95%",new DoseValue(6000.0, DoseValue.DoseUnit.cGy), 95.0, 0.9474), even if I am covering more than 95% , the evaluation result is FAIL rather than PASS

bilaljalal avatar Sep 14 '18 18:09 bilaljalal

I'm not too familiar with that code... but short answer is upperLimitTol should probably be > 1.0 since it gets multiplied by volConstraint value to set the max (failure) volume value.

If you take a look here you can see how VolumeAtDose is evaluated and how upperLimitTol is used.

So, when you think about evaluating your upper limit constraint with volumeConstraint=95 and upperLimitTol=0.9474, you get limitMax=90 which will always result in pfw = "FAIL" since no value is both greater than 95 and less than 90 (and volume>95 in your case):

        upperLimit = upperLimitTol;
        //...
        double limitMax = (volumeConstraint * upperLimit);
        writer.WriteElementString("MaxLimit", limitMax.ToString("0.000"));
        if (lt == PQMUtilities.LimitType.upper)
        {
          if (volume > volumeConstraint && volume <= limitMax)
            pfw = "WARN";
          else if (volume > limitMax)
            pfw = "FAIL";
        }

fizxmike avatar Sep 15 '18 20:09 fizxmike

Also, notice there are some defaults set in the VolumeAtDose constructor which dictate the type of limit (upper or lower):

      public VolumeAtDose(string name_, DoseValue doseValue, double volConstraint, double upperLimitTol,
              VolumePresentation vpp = VolumePresentation.Relative, PQMUtilities.LimitType lt_ = PQMUtilities.LimitType.upper)
      {

fizxmike avatar Sep 15 '18 20:09 fizxmike

Thank you for your reply, actually the script works perfect if you have multiple plans and the evaluation for the plan sum is fine, I have this issue only when I run the script for multiple PTVs inside the same plan.

bilaljalal avatar Sep 19 '18 19:09 bilaljalal

For your lower limits, you need to explicitly pass PQMUtilities.LimitType.lower to VolumeAtDose(...), I think this is why your >60Gy test fails. In this case (lower bound) it's okay to have tolerance <1.

Note how the single PTV checks (Target class) have both VolumePresentation, and PQMUtilities.LimitType explicitly set in VolumeAtDose(...)

fizxmike avatar Sep 20 '18 03:09 fizxmike

this is the H&N script I am using for plan evaluation, can you please have a look at it, I deeply appreciate all your support H&N.zip

if you could please guide me how to modify the criteria , thank you in advance

bilaljalal avatar Sep 23 '18 20:09 bilaljalal

new VolumeAtDose("V60Gy > 95%",new DoseValue(6000.0, DoseValue.DoseUnit.cGy), 95.0, 0.9474)

I think the problem here is your mandatory criteria 0.97474. Pass,warn and fail works when minimum your mandatory criteria achieved. Try 90.0 instead of 95 and then 1.05556 in the end.This should pass because then your optimal coverage required is 95% but mandatory dose to cover is 90%.You did other way round so it Fails in your script.

mayurmunshi avatar Jul 16 '20 08:07 mayurmunshi