Varian-Code-Samples
Varian-Code-Samples copied to clipboard
Plan Quality Metrics Script; multiple PTV metrics within the same script
**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
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";
}
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)
{
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.
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(...)
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
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.