public ObservableCollection <PQMSummaryViewModel> AddPQMSummary(ObservableCollection <PQMSummaryViewModel> PqmSummaries, ConstraintViewModel constraintPath, PlanningItemViewModel planningItem, Patient patient) { StructureSet structureSet = planningItem.PlanningItemStructureSet; Structure evalStructure; //ObservableCollection<PQMSummaryViewModel> pqmSummaries = new ObservableCollection<PQMSummaryViewModel>(); //ObservableCollection<StructureViewModel> foundStructureList = new ObservableCollection<StructureViewModel>(); var calculator = new PQMSummaryCalculator(); //var numCol = PqmSummaries[0] //Objectives = calculator.GetObjectives(constraintPath); if (planningItem.PlanningItemObject is PlanSum) { var waitWindowPQM = new WaitWindowPQM(); PlanSum plansum = (PlanSum)planningItem.PlanningItemObject; if (plansum.IsDoseValid() == true) { waitWindowPQM.Show(); foreach (PQMSummaryViewModel pqm in PqmSummaries) { evalStructure = calculator.FindStructureFromAlias(structureSet, pqm.TemplateId, pqm.TemplateAliases, pqm.TemplateCodes); if (evalStructure != null) { var pqmSummary = calculator.GetObjectiveProperties(pqm, planningItem, structureSet, new StructureViewModel(evalStructure)); //pqm.Achieved_Comparison = pqmSummary.Achieved; //pqm.AchievedColor_Comparison = pqmSummary.AchievedColor; //pqm.AchievedPercentageOfGoal_Comparison = pqmSummary.AchievedPercentageOfGoal; //pqm.Met_Comparison = pqmSummary.Met; //pqmSummaries.Add(pqmSummary); //foundStructureList.Add(new StructureViewModel(evalStructure)); } } //FoundStructureList = foundStructureList; waitWindowPQM.Close(); } //PqmSummaries = pqmSummaries; } else //is plansetup { var waitWindowPQM = new WaitWindowPQM(); PlanSetup planSetup = (PlanSetup)planningItem.PlanningItemObject; if (planSetup.IsDoseValid() == true) { waitWindowPQM.Show(); foreach (PQMSummaryViewModel pqm in PqmSummaries) { evalStructure = calculator.FindStructureFromAlias(structureSet, pqm.TemplateId, pqm.TemplateAliases, pqm.TemplateCodes); if (evalStructure != null) { if (evalStructure.Id.Contains("PTV") == true) { foreach (Structure s in structureSet.Structures) { if (s.Id == planSetup.TargetVolumeID) { evalStructure = s; } } } var pqmSummary = calculator.GetObjectiveProperties(pqm, planningItem, structureSet, new StructureViewModel(evalStructure)); //pqm.Achieved_Comparison = pqmSummary.Achieved; //foundStructureList.Add(new StructureViewModel(evalStructure)); } } //FoundStructureList = foundStructureList; waitWindowPQM.Close(); } //PqmSummaries = pqmSummaries; } return(PqmSummaries); }
protected override void RunTest(PlanSetup plan) { bool IMRT = false; DisplayName = "Jaw Tracking"; Result = ""; TestExplanation = "Checks to see if jaw tracking is enabled for IMRT/VMAT plans"; #region Macomb Group // use jaw tracking if (Department == Department.MAC || Department == Department.MPH) { //VMAT plan if ((from s in plan.Beams where s.MLCPlanType == MLCPlanType.VMAT select s).Count() > 0) { IMRT = true; foreach (Beam field in plan.Beams) { //ignore setup fields if (!field.IsSetupField) { //for VMAT fields, check that there are different jaw positions in the control points if (field.MLCPlanType == MLCPlanType.VMAT) { //get initial jaw positions double x1 = field.ControlPoints.First().JawPositions.X1; double x2 = field.ControlPoints.First().JawPositions.X2; double y1 = field.ControlPoints.First().JawPositions.Y1; double y2 = field.ControlPoints.First().JawPositions.Y2; //if they change at any of the control points, then jaw tracking must be on foreach (ControlPoint point in field.ControlPoints) { if (x1 != point.JawPositions.X1 || x2 != point.JawPositions.X2 || y1 != point.JawPositions.Y1 || y2 != point.JawPositions.Y2) { Result = "Pass"; DisplayColor = ResultColorChoices.Pass; break; } } } } } } //IMRT plan else if ((from s in plan.Beams where s.MLCPlanType == MLCPlanType.DoseDynamic select s).Count() > 0) { foreach (Beam field in plan.Beams) { //ignore setup fields if (!field.IsSetupField) { //for IMRT fields that have more control points than step and shoot, check that there are different jaw positions in the control points if (field.MLCPlanType == MLCPlanType.DoseDynamic && field.ControlPoints.Count > 18) { IMRT = true; //get initial jaw positions double x1 = field.ControlPoints.First().JawPositions.X1; double x2 = field.ControlPoints.First().JawPositions.X2; double y1 = field.ControlPoints.First().JawPositions.Y1; double y2 = field.ControlPoints.First().JawPositions.Y2; //if they change at any of the control points, then jaw tracking must be on foreach (ControlPoint point in field.ControlPoints) { if (x1 != point.JawPositions.X1 || x2 != point.JawPositions.X2 || y1 != point.JawPositions.Y1 || y2 != point.JawPositions.Y2) { Result = "Pass"; DisplayColor = ResultColorChoices.Pass; break; } } } } } } //Static fields if (!IMRT) { Result = "Pass"; DisplayColor = ResultColorChoices.Pass; } //No jaw tracking detected else if (Result == "") { Result = "Warning"; ResultDetails = "Please check that jaw tracking is enabled in the optimization window or leaf motion calculator"; DisplayColor = ResultColorChoices.Warn; } } #endregion #region Flint Group and Northern TrueBeam (for now) // do not use jaw tracking else if (Department == Department.FLT || Department == Department.NOR) { //VMAT plan if ((from s in plan.Beams where s.MLCPlanType == MLCPlanType.VMAT select s).Count() > 0) { IMRT = true; foreach (Beam field in plan.Beams) { //ignore setup fields if (!field.IsSetupField) { //for VMAT fields, check that there are different jaw positions in the control points if (field.MLCPlanType == MLCPlanType.VMAT) { //get initial jaw positions double x1 = field.ControlPoints.First().JawPositions.X1; double x2 = field.ControlPoints.First().JawPositions.X2; double y1 = field.ControlPoints.First().JawPositions.Y1; double y2 = field.ControlPoints.First().JawPositions.Y2; //if they change at any of the control points, then jaw tracking must be on foreach (ControlPoint point in field.ControlPoints) { if (x1 != point.JawPositions.X1 || x2 != point.JawPositions.X2 || y1 != point.JawPositions.Y1 || y2 != point.JawPositions.Y2) { Result = "Warning"; ResultDetails = "Please check that jaw tracking is disabled in the optimization window"; DisplayColor = ResultColorChoices.Warn; break; } } } } } } //IMRT plan else if ((from s in plan.Beams where s.MLCPlanType == MLCPlanType.DoseDynamic select s).Count() > 0) { foreach (Beam field in plan.Beams) { //ignore setup fields if (!field.IsSetupField) { //for IMRT fields that have more control points than step and shoot, check that there are different jaw positions in the control points if (field.MLCPlanType == MLCPlanType.DoseDynamic && field.ControlPoints.Count > 18) { IMRT = true; //get initial jaw positions double x1 = field.ControlPoints.First().JawPositions.X1; double x2 = field.ControlPoints.First().JawPositions.X2; double y1 = field.ControlPoints.First().JawPositions.Y1; double y2 = field.ControlPoints.First().JawPositions.Y2; //if they change at any of the control points, then jaw tracking must be on foreach (ControlPoint point in field.ControlPoints) { if (x1 != point.JawPositions.X1 || x2 != point.JawPositions.X2 || y1 != point.JawPositions.Y1 || y2 != point.JawPositions.Y2) { Result = "Warning"; ResultDetails = "Please check that jaw tracking is disabled in the leaf motion calculator"; DisplayColor = ResultColorChoices.Warn; break; } } } } } } //Static fields if (!IMRT) { Result = "Pass"; DisplayColor = ResultColorChoices.Pass; } //No jaw tracking detected else if (Result == "") { Result = "Pass"; DisplayColor = ResultColorChoices.Pass; } } #endregion else { TestNotImplemented(); } }
public PrecriptionChecks(PlanSetup plan) : base(plan) { }
/// <summary> /// calcDQP /// </summary> /// <param name="ps"></param> /// <param name="DQPList"></param> /// <returns></returns> static string calcDQP(PlanSetup ps, Collection <DQP> DQPList) { // Initialize variables. DVHData dvhStat = null; Structure targetStructure = null; string oText = ""; // Iterate over all DQP in list. foreach (var row in DQPList) { targetStructure = ps.StructureSet.Structures.Where(s => s.Id == row.structureName).FirstOrDefault(); // Execute if the structure name match. if (targetStructure != null) { //get string of dose unit [Gy] or [cGy]. dvhStat = ps.GetDVHCumulativeData(targetStructure, DoseValuePresentation.Absolute, VolumePresentation.AbsoluteCm3, 0.1); string doseUnitString = dvhStat.MaxDose.UnitAsString; // define prefix DQP name. if (row.DQPtype == DQPtype.Dose) { oText += row.structureName + "-D" + row.DQPvalue.ToString(); } else if (row.DQPtype == DQPtype.Volume) { oText += row.structureName + "-V" + row.DQPvalue.ToString(); } else if (row.DQPtype == DQPtype.DoseComplement) { oText += row.structureName + "-DC" + row.DQPvalue.ToString(); } else if (row.DQPtype == DQPtype.ComplementVolume) { oText += row.structureName + "-CV" + row.DQPvalue.ToString(); } // define input unit [Gy/cGy] or [cc] or [%] if (row.InputUnit == IOUnit.Absolute) { if (row.DQPtype == DQPtype.Dose) { oText += "cc"; } else if (row.DQPtype == DQPtype.Volume) { oText += doseUnitString; } else if (row.DQPtype == DQPtype.DoseComplement) { oText += "cc"; } else if (row.DQPtype == DQPtype.ComplementVolume) { oText += doseUnitString; } } else { oText += "%"; } // define output unit [Gy/cGy] or [cc] or [%] if (row.OutputUnit == IOUnit.Absolute) { if (row.DQPtype == DQPtype.Dose) { oText += "[" + doseUnitString + "]"; } else if (row.DQPtype == DQPtype.Volume) { oText += "[cc]"; } else if (row.DQPtype == DQPtype.DoseComplement) { oText += "[" + doseUnitString + "]"; } else if (row.DQPtype == DQPtype.ComplementVolume) { oText += "[cc]"; } } else { oText += "[%]"; } oText += ":"; // calculate dose quality parameters (VolumeAtDose,DoseAtVolume,DoseComplement,ComplementVolume). if (row.DQPtype == DQPtype.Dose) // calculate DoseAtVolume. { DoseValue doseValue = ps.GetDoseAtVolume(targetStructure, row.DQPvalue, row.InputUnit == IOUnit.Relative ? VolumePresentation.Relative : VolumePresentation.AbsoluteCm3, row.OutputUnit == IOUnit.Relative ? DoseValuePresentation.Relative : DoseValuePresentation.Absolute); oText += doseValue.Dose.ToString(); } else if (row.DQPtype == DQPtype.Volume) // calculate VolumeAtDose. { double volumeValue = ps.GetVolumeAtDose(targetStructure, row.InputUnit == IOUnit.Relative ? new DoseValue(ps.TotalDose.Dose * (row.DQPvalue * 0.01), dvhStat.MaxDose.Unit) : new DoseValue(row.DQPvalue, dvhStat.MaxDose.Unit), row.OutputUnit == IOUnit.Relative ? VolumePresentation.Relative : VolumePresentation.AbsoluteCm3); oText += volumeValue.ToString(); } else if (row.DQPtype == DQPtype.DoseComplement) // calculate DoseComplement. { double subVolume = 0.0; if (row.InputUnit == IOUnit.Relative) { subVolume = targetStructure.Volume - targetStructure.Volume * (row.DQPvalue * 0.01); subVolume = (subVolume / targetStructure.Volume * 100); } else { subVolume = targetStructure.Volume - row.DQPvalue; } DoseValue doseValue = ps.GetDoseAtVolume(targetStructure, subVolume, row.InputUnit == IOUnit.Relative ? VolumePresentation.Relative : VolumePresentation.AbsoluteCm3, row.OutputUnit == IOUnit.Relative ? DoseValuePresentation.Relative : DoseValuePresentation.Absolute); oText += doseValue.Dose.ToString(); } else if (row.DQPtype == DQPtype.ComplementVolume) // calculate ComplementVolume. { double volumeValue = ps.GetVolumeAtDose(targetStructure, row.InputUnit == IOUnit.Relative ? new DoseValue(ps.TotalDose.Dose * (row.DQPvalue * 0.01), dvhStat.MaxDose.Unit) : new DoseValue(row.DQPvalue, dvhStat.MaxDose.Unit), VolumePresentation.AbsoluteCm3); double CV = targetStructure.Volume - volumeValue; if (row.OutputUnit == IOUnit.Relative) { CV = (CV / targetStructure.Volume * 100); } oText += CV.ToString(); } else { oText += "DQP type not found"; } oText += "\t"; } } return(oText); }
public OrientationChecks(PlanSetup plan) : base(plan) { }
// Returns the unweighted metrics of a beam's apertures private double[] CalculateForBeamPerAperture(Patient patient, PlanSetup plan, Beam beam) { return(CalculatePerAperture(CreateApertures(patient, plan, beam))); }
public void Nothing(PlanSetup plan) { }
public BolusChecks(PlanSetup plan) : base(plan) { }
protected override void RunTest(PlanSetup plan) { DisplayName = "Bolus"; Result = ""; ResultDetails = ""; TestExplanation = "Checks that each field has a linked bolus if a bolus exists"; string bolus = ""; bool containsBolus = false; bool containsMultiple = false; string resultDetailsMultiPerFieldLine = ""; string resultDetailsMultiPerPlanLine = ""; //Check to see if plan contains a bolus foreach (Structure struc in plan.StructureSet.Structures) { if (struc.DicomType == "BOLUS") { //if it's already found one bolus, then there are multiple if (containsBolus) { containsMultiple = true; } containsBolus = true; } } //Check each field to make sure it has a bolus attached foreach (Beam field in plan.Beams) { if (!containsBolus) { break; } if (!field.IsSetupField) { //no bolus if (field.Boluses.Count() == 0) { //Set up "no bolus linked" string if (ResultDetails == "") { Result = "Warning"; ResultDetails = "Some fields do not have a linked bolus: "; DisplayColor = ResultColorChoices.Warn; } ResultDetails += field.Id + ", "; } //more than 1 bolus else if (field.Boluses.Count() > 1) { //set up "multiple boluses" string if (resultDetailsMultiPerFieldLine == "") { Result = "Warning"; resultDetailsMultiPerFieldLine = "Some fields have more than one bolus linked: "; DisplayColor = ResultColorChoices.Warn; } resultDetailsMultiPerFieldLine += field.Id + ", "; } //just one bolus else { //if this is the first bolus found, save it if (bolus == "") { bolus = field.Boluses.First().Id; } //if not make sure it's the same bolus used on other fields else if (field.Boluses.First().Id != bolus) { //set up "multiple boluses" string if (resultDetailsMultiPerPlanLine == "") { Result = "Warning"; resultDetailsMultiPerPlanLine = $"Multiple bolus structures linked in plan: {bolus}, "; DisplayColor = ResultColorChoices.Warn; } resultDetailsMultiPerPlanLine += field.Boluses.First().Id + ", "; } } } } //no bolus in plan so it's good if (!containsBolus) { Result = ""; ResultDetails = "No bolus in structure set"; DisplayColor = ResultColorChoices.Pass; } //no issues found else if (Result == "") { Result = ""; ResultDetails = $"{bolus} attached to all fields"; DisplayColor = ResultColorChoices.Pass; } //clean up strings ResultDetails = ResultDetails.TrimEnd(' '); ResultDetails = ResultDetails.TrimEnd(','); resultDetailsMultiPerFieldLine = resultDetailsMultiPerFieldLine.TrimEnd(' '); resultDetailsMultiPerFieldLine = resultDetailsMultiPerFieldLine.TrimEnd(','); resultDetailsMultiPerPlanLine = resultDetailsMultiPerPlanLine.TrimEnd(' '); resultDetailsMultiPerPlanLine = resultDetailsMultiPerPlanLine.TrimEnd(','); if (resultDetailsMultiPerFieldLine != "") { ResultDetails += '\n' + resultDetailsMultiPerFieldLine; } if (resultDetailsMultiPerPlanLine != "") { ResultDetails += '\n' + resultDetailsMultiPerPlanLine; } ResultDetails = ResultDetails.TrimStart('\n'); ResultDetails = ResultDetails.TrimStart('\n'); //multiple boluses in structure set, so put a warning at the end if (containsMultiple) { Result = "Warning"; ResultDetails += "\nMultiple bolus structures in the structure set, please ensure that the correct one is used"; DisplayColor = ResultColorChoices.Warn; } }
private static int GetFractions(PlanSetup planSetup) { return(planSetup.NumberOfFractions.Value); }
/// <summary> /// Return image profiles through plan isocenter in primary axis direction /// </summary> /// <param name="plan">TPS.NET.Plan</param> /// <param name="profileLengthInmm"> length of the profiles in mm</param> /// <returns></returns> public static (ImageProfile, ImageProfile, ImageProfile) getImageProfilesThroughIsocenter(PlanSetup plan) { var image = plan.StructureSet.Image; var dirVecs = new VVector[] { plan.StructureSet.Image.XDirection, plan.StructureSet.Image.YDirection, plan.StructureSet.Image.ZDirection }; var steps = new double[] { plan.StructureSet.Image.XRes, plan.StructureSet.Image.YRes, plan.StructureSet.Image.ZRes }; var planIso = plan.Beams.First().IsocenterPosition; var tmpRes = new ImageProfile[3]; // // Throws if plan does not have 'BODY' // var body = plan.StructureSet.Structures.Single(st => st.Id == "BODY"); for (int ind = 0; ind < 3; ind++) { (var startPoint, var endPoint) = Helpers.GetStructureEntryAndExit(body, dirVecs[ind], planIso, steps[ind]); var samples = (int)Math.Ceiling((endPoint - startPoint).Length / steps[ind]); tmpRes[ind] = image.GetImageProfile(startPoint, endPoint, new double[samples]); } return(tmpRes[0], tmpRes[1], tmpRes[2]); }
private static Structure GetStructure(PlanSetup planSetup, string structureId) { return(planSetup.StructureSet.Structures.First(s => s.Id == structureId)); }
public void OnPlanSetupChanged(PlanSetup ps) { PlanSetupChanged?.Invoke(ps); }
public Tuple <List <CollisionCheckViewModel>, Model3DGroup> GetCollisionSummary(PlanningItemViewModel planningItem) { var waitWindowCollision = new WaitWindowCollision(); waitWindowCollision.Show(); var calculator = new CollisionSummariesCalculator(); var collimatorModelGroup = new Model3DGroup(); var isoModelGroup = new Model3DGroup(); var modelGroup = new Model3DGroup(); upDir = new Vector3D(0, -1, 0); lookDir = new Vector3D(0, 0, 1); isoctr = new Point3D(0, 0, 0); //just to initalize cameraPosition = new Point3D(0, 0, -3500); var CollisionSummaries = new List <CollisionCheckViewModel>(); // Create some materials var redMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.Red)); var darkblueMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.DarkBlue)); var collimatorMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.Green)); Structure bodyStruct; var iso3DMesh = calculator.CalculateIsoMesh(isoctr); MeshGeometry3D bodyMesh = null; MeshGeometry3D couchMesh = null; if (planningItem.PlanningItemObject is PlanSetup) { PlanSetup planSetup = (PlanSetup)planningItem.PlanningItemObject; bodyStruct = planSetup.StructureSet.Structures.Where(x => x.Id.Contains("BODY")).First(); bodyMesh = bodyStruct.MeshGeometry; foreach (Structure structure in planSetup.StructureSet.Structures) { if (structure.StructureCodeInfos.FirstOrDefault().Code != null) { if (structure.StructureCodeInfos.FirstOrDefault().Code == "Support") { Structure couchStruct = structure; couchMesh = couchStruct.MeshGeometry; } } } foreach (Beam beam in planSetup.Beams) { isoctr = calculator.GetIsocenter(beam); iso3DMesh = calculator.CalculateIsoMesh(calculator.GetIsocenter(beam)); bool view = true; if (planSetup.TreatmentOrientation.ToString() == "HeadFirstProne") { upDir = new Vector3D(0, 1, 0); } bool isVMAT = false; bool isStatic = false; bool isElectron = false; bool isSRSArc = false; collimatorMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.Green)); if (beam.IsSetupField == true) { continue; } if (beam.Name.Contains("Subfield 2") || beam.Name.Contains("Subfield 3")) { continue; } if (beam.EnergyModeDisplayName.Contains("E")) { isElectron = true; } if (beam.EnergyModeDisplayName.Contains("SRS")) { isSRSArc = true; } if (beam.MLCPlanType.ToString() == "VMAT") { isVMAT = true; collimatorMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.GreenYellow)); } if (beam.Technique.ToString().Contains("STATIC")) { isStatic = true; collimatorMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.DarkGreen)); } foreach (Structure structure in planSetup.StructureSet.Structures) { if (structure.Id.Contains("CouchSurface") == true) { Structure couchStruct = planSetup.StructureSet.Structures.Where(x => x.Id.Contains("CouchSurface")).First(); couchMesh = couchStruct.MeshGeometry; } } MeshGeometry3D collimatorMesh = calculator.CalculateCollimatorMesh(planSetup, beam, isoctr, isVMAT, isStatic, isElectron, isSRSArc); string shortestDistanceBody = "2000000"; string shortestDistanceTable = "2000000"; string status = "Clear"; shortestDistanceBody = calculator.ShortestDistance(collimatorMesh, bodyMesh); if (couchMesh != null) { shortestDistanceTable = calculator.ShortestDistance(collimatorMesh, couchMesh); } else { shortestDistanceTable = " - "; status = " - "; } Console.WriteLine(beam.Id + " - gantry to body is " + shortestDistanceBody + " cm"); Console.WriteLine(beam.Id + " - gantry to table is " + shortestDistanceTable + " cm"); if (shortestDistanceTable != " - ") { if ((Convert.ToDouble(shortestDistanceBody) < 3.0) || (Convert.ToDouble(shortestDistanceTable) < 3.0)) { collimatorMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.Red)); status = "Collision"; } } collimatorModelGroup.Children.Add(new GeometryModel3D { Geometry = collimatorMesh, Material = collimatorMaterial, BackMaterial = darkblueMaterial }); isoModelGroup.Children.Add(new GeometryModel3D { Geometry = iso3DMesh, Material = redMaterial, BackMaterial = redMaterial }); var collisionSummary = calculator.GetFieldCollisionSummary(beam, view, shortestDistanceBody, shortestDistanceTable, status); CollisionSummaries.Add(collisionSummary); } } modelGroup = CreateModel(bodyMesh, couchMesh, isoModelGroup, collimatorModelGroup, collimatorMaterial); waitWindowCollision.Close(); return(Tuple.Create(CollisionSummaries, modelGroup)); }
// Returns the complexity metric of a beam, calculated as // the weighted sum of the individual metrics for each control point public double CalculateForBeam(Patient patient, PlanSetup plan, Beam beam) { return(WeightedSum(GetWeights(beam), GetMetrics(patient, plan, beam))); }
// Returns the weighted metrics of a beam's control points public double[] CalculatePerControlPointWeighted( Patient patient, PlanSetup plan, Beam beam) { return(WeightedValues(GetWeights(beam), GetMetrics(patient, plan, beam))); }
// Returns the unweighted metrics of a beam's control points protected virtual double[] GetMetrics(Patient patient, PlanSetup plan, Beam beam) { return(CalculateForBeamPerAperture(patient, plan, beam)); }
// Returns the unweighted metrics of a beam's control points public double[] CalculatePerControlPointUnweighted( Patient patient, PlanSetup plan, Beam beam) { return(GetMetrics(patient, plan, beam)); }
// Returns the apertures created from a beam private IEnumerable <Aperture> CreateApertures(Patient patient, PlanSetup plan, Beam beam) { return(new AperturesFromBeamCreator().Create(patient, plan, beam)); }
// Returns the complexity metric of a plan, calculated as // the weighted sum of the individual metrics for each beam public double CalculateForPlan(Patient patient, PlanSetup plan) { return(WeightedSum(GetWeights(plan), GetMetrics(patient, plan))); }
/// <summary> /// ReportOnePlan /// </summary> /// <param name="patient"></param> /// <param name="ps"></param> /// <param name="reportFile"></param> static void ReportOnePlan(Patient patient, PlanSetup ps, StreamWriter reportFile) { // Change type of presentation for dose value to absolute. ps.DoseValuePresentation = DoseValuePresentation.Absolute; // Initialize output text string msg = ""; msg += patient.Id + "\t"; // Add patient ID to output text. msg += ps.Course.Id + "\t"; // Add course ID to output text. msg += ps.Id + "\t"; // Add plan ID to output text. // TODO : Add here the code ///////////////////////////////////////////////////////////// // Get plan information. //////////////////////////////////////////////////////////////// // Get plan normalization method. msg += ps.PlanNormalizationMethod + "\t"; // Get calculation model & options. int countFieldX = 0; int countFieldE = 0; foreach (var b in ps.Beams) { if (!b.IsSetupField) { if (b.EnergyModeDisplayName.IndexOf("X") >= 0) { countFieldX++; } if (b.EnergyModeDisplayName.IndexOf("E") >= 0) { countFieldE++; } } } string CalculationModel = ""; if (countFieldX > 0) { CalculationModel += "(" + ps.PhotonCalculationModel.ToString(); foreach (KeyValuePair <string, string> kvp in ps.PhotonCalculationOptions) { CalculationModel += "/" + kvp.Key + ":" + kvp.Value; } CalculationModel += ")"; } if (countFieldE > 0) { CalculationModel += "(" + ps.ElectronCalculationModel.ToString(); foreach (KeyValuePair <string, string> kvp in ps.ElectronCalculationOptions) { CalculationModel += "/" + kvp.Key + ":" + kvp.Value; } CalculationModel += ")"; } msg += CalculationModel + "\t"; // Get field information. //////////////////////////////////////////////////////////////// var energy_List = new List <string>(); var mu_List = new List <string>(); int nBeam = 0; // Iterate over all beams foreach (var b in ps.Beams) { if (!b.IsSetupField) //exclude SetupField. { energy_List.Add(b.EnergyModeDisplayName); // beam energy. mu_List.Add(string.Format("{0:f1}", b.Meterset.Value)); // Get MU at 1st decimal place . nBeam++; //count number of beams. } } msg += "#beam:" + nBeam.ToString() + "\t"; //add number of beams to output text. msg += "Energy:" + string.Join("/", energy_List) + "\t"; // Combine all values with "/". msg += "MU:" + string.Join("/", mu_List) + "\t"; // Combine all values with "/". /////////////////////////////////////////////////////////////////////////////////////////// // Get DVH statistic information. /////////////////////////////////////////////////////////////////// // calculate Max/Mean/Min dose. // Initialize variables. DVHData dvhStat = null; Structure targetStructure = null; string[] s_targetIds = { "ITV", "PTV", "PTV-PROST", "PTV-SV", "GTV", "CTV", "BLADDER", "CORD", "BRAINSTEM", "LUNG", "LIVER", "KIDNEY","BREAST","OPTIC", "PAROTID", "SPINE", "RECTUM", "BOWEL", "BRAIN" }; // Iterate over all structures. foreach (var structure in ps.StructureSet.Structures) { if (ps.Dose != null && ps.StructureSet != null) { targetStructure = FindStructure(structure, s_targetIds); if (targetStructure != null) { dvhStat = ps.GetDVHCumulativeData(targetStructure, DoseValuePresentation.Absolute, VolumePresentation.AbsoluteCm3, 0.1); if (dvhStat != null) { string doseUnitString = dvhStat.MaxDose.UnitAsString; msg += targetStructure.Id + "[Max/Mean/Min," + doseUnitString + "]:" + dvhStat.MaxDose.Dose.ToString() + "/" + dvhStat.MeanDose.Dose.ToString() + "/" + dvhStat.MinDose.Dose.ToString() + "\t"; } } } } // Calculate Dose Quality Parameters (VolumeAtDose,DoseAtVolume,DoseComplement,ComplementVolume). var DQPList = new Collection <DQP>(); // define parameters DQPList.Add(new DQP { structureName = "Prostate", DQPtype = DQPtype.Dose, DQPvalue = 95.0, InputUnit = IOUnit.Relative, OutputUnit = IOUnit.Absolute }); DQPList.Add(new DQP { structureName = "Rectum", DQPtype = DQPtype.Volume, DQPvalue = 70, InputUnit = IOUnit.Relative, OutputUnit = IOUnit.Relative }); // calculate DQP. msg += calcDQP(ps, DQPList); /////////////////////////////////////////////////////////////////////////////////////////// reportFile.WriteLine(msg); }
// Returns the weights of a plan's beams; // by default, the weights are the meterset values per beam protected virtual double[] GetWeights(PlanSetup plan) { return(GetMetersets(plan)); }
public void Execute(ScriptContext context /*, System.Windows.Window window*/) { PlanSetup planSetup = context.PlanSetup; PlanSum psum = context.PlanSumsInScope.FirstOrDefault(); StructureSet structureSet; bool isPlanSum = false; string psumName = null; // If there's no selected plan with calculated dose throw an exception if (planSetup == null && psum == null) { throw new ApplicationException("Please open a calculated plan/planSum before using this script."); } else if (planSetup != null) { if (planSetup.Dose == null) { throw new ApplicationException("Please open a calculated plan before using this script."); } structureSet = planSetup.StructureSet; } else { if (psum.Dose == null) { throw new ApplicationException("Please open a calculated plansum before using this script."); } isPlanSum = true; if (context.PlanSumsInScope.Count() > 1) { List <String> psumList = new List <String>(); foreach (var sum in context.PlanSumsInScope) { foreach (var course in context.Patient.Courses) { if (course.PlanSums.FirstOrDefault(ps => ps.Id == sum.Id) != null) { if (sum.Equals(course.PlanSums.First(ps => ps.Id == sum.Id))) { psumList.Add(String.Format("{0}/{1}", course.Id, sum.Id)); } } } // v13以降はforeach (var course ~)の代わりにこれだけでいける // psumList.Add(String.Format("{0}/{1}", sum.Course.Id, sum.Id)); } psumName = Form5.ShowMiniForm(psumList); structureSet = context.Patient.Courses.First(c => c.Id == psumName.Split('/')[0]).PlanSums.First(ps => ps.Id == psumName.Split('/')[1]).StructureSet; } else { structureSet = psum.StructureSet; foreach (var course in context.Patient.Courses) { if (course.PlanSums.FirstOrDefault(ps => ps.Id == psum.Id) != null) { if (psum.Equals(course.PlanSums.First(ps => ps.Id == psum.Id))) { psumName = course.Id + '/' + psum.Id; } } } // v13以降は foreach(var course ~)の代わりにこれでいける // psumName = psum.Course.Id + '/' + psum.Id; } } // Retrieve StructureSet if (structureSet == null) { throw new ApplicationException("The selected plan does not reference a StructureSet."); } Form1 window; if (!isPlanSum) { window = new Form1(context); } else { window = new Form1(context, true, psumName); } window.ShowDialog(); }
// Returns the total metersets of a plan's beams protected double[] GetMetersets(PlanSetup plan) { return((from beam in plan.Beams where !beam.IsSetupField select beam.Meterset.Value).ToArray()); }
public JawTrackingChecks(PlanSetup plan) : base(plan) { }
// Returns the unweighted metrics of a plan's beams private double[] GetMetrics(Patient patient, PlanSetup plan) { return(CalculateForPlanPerBeam(patient, plan)); }
/// <summary> /// The PlanQualityMetrics script generates a report of plan quality, using evaluation metrics defined in UserDefinedMetrics.cs. /// The script first computes metrics for all found structures, evaluates whether the metrics are in or out of tolerance and /// generates an xml report of that information and saves it to %temp\<patientid>\PQMReport-<planid>.xml. The XML report is /// then transformed into an HTML report with an XSLT stylesheet, using either the gen_report.xsl stylesheet for Plans, or /// the gen_report_plansum.xsl stylesheet for PlanSums. The HTML report is then shown to the user. /// /// Metric evaluation and XML & HTML report generation is driven by PQMReporter. /// // Many of these metrics used in this script come from QUANTEC data. See // http://en.wikibooks.org/wiki/Radiation_Oncology/Toxicity/QUANTEC // /// Add your own evaluators and change structure ids to match those used in your clinic in UserDefinedMetrics.cs. /// If new evaluators are added, you need to also add a call to use those evaluators in /// PQMReporter.WriteDoseStatisticsXML_Prostate2GyOrLess, or WriteDoseStatisticsXML_HeadAndNeck2GyOrLess. /// /// This script currently supports metric reporting for normally fractionated Prostate and Head and Neck. /// </summary> /// <param name="context"></param> public void Execute(ScriptContext context /*, System.Windows.Window window*/) { string temp = System.Environment.GetEnvironmentVariable("TEMP"); string eclipseVersion = System.Reflection.Assembly.GetAssembly (typeof(VMS.TPS.Common.Model.API.Application)).GetName().Version.ToString(); string scriptVersion = "1.0.10"; if (context.PlanSumsInScope.Count() > 0) { foreach (PlanSum plansum in context.PlanSumsInScope) { if (plansum.StructureSet == null) { MessageBox.Show("Plansum has no structure set.", "Varian Developer", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (plansum.Dose == null) { MessageBox.Show("Loaded plansum has no dose: Please select an external beam plan or plansum with dose calculated that you would like evaluate.", "Varian Developer", MessageBoxButton.OK, MessageBoxImage.Error); return; } // Load the plansum stylesheet into memory, transform report XML into HTML, show that to the user. // gen_report_plansum.xsl is automatically compiled in when the build action for the VS project is set to // "Embedded Resource". See online help for Build Action. Read the embedded stylesheet file from the DLL. Stream stylesheet = Assembly.GetExecutingAssembly().GetManifestResourceStream("PlanQualityMetrics.gen_report_plansum.xsl"); XmlReader stylesheetReader = XmlReader.Create(new StreamReader(stylesheet)); VMS.TPS.PlanSumReporter reporter = new PlanSumReporter(temp, context.CurrentUser.Id, eclipseVersion, scriptVersion, stylesheetReader); Patient patient = context.Patient; string xmlReportPath; string htmlReportPath = reporter.generateReport(patient, plansum.StructureSet, plansum, out xmlReportPath); // 'Start' generated HTML file to launch browser window System.Diagnostics.Process.Start(htmlReportPath); // Sleep for a few seconds to let internet browser window to start System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2)); } } else { if (context.Patient == null || context.PlanSetup == null) { MessageBox.Show("Please select the external beam plan that you would like evaluate.", "Varian Developer", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (context.PlanSetup.StructureSet == null) { MessageBox.Show("Loaded plan does not have a structure set.", "Varian Developer", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (context.PlanSetup.Dose == null) { MessageBox.Show("Loaded plan has no dose: Please select an external beam plan with dose calculated that you would like evaluate.", "Varian Developer", MessageBoxButton.OK, MessageBoxImage.Error); return; } // gen_report.xsl is automatically compiled in when the build action for the VS project is set to // "Embedded Resource". See online help for Build Action. Read the embedded stylesheet file from the DLL. Stream stylesheet = Assembly.GetExecutingAssembly().GetManifestResourceStream("PlanQualityMetrics.gen_report.xsl"); XmlReader stylesheetReader = XmlReader.Create(new StreamReader(stylesheet)); VMS.TPS.PlanSetupReporter reporter = new PlanSetupReporter(temp, context.CurrentUser.Id, eclipseVersion, scriptVersion, stylesheetReader); Patient patient = context.Patient; PlanSetup plan = context.PlanSetup; StructureSet ss = context.StructureSet; string xmlReportPath; string htmlReportPath = reporter.generateReport(patient, plan.StructureSet, plan, out xmlReportPath); // 'Start' generated HTML file to launch browser window System.Diagnostics.Process.Start(htmlReportPath); // Sleep for a few seconds to let internet browser window to start System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2)); } }
// Returns the unweighted metrics of a plan's non-setup beams private double[] CalculateForPlanPerBeam(Patient patient, PlanSetup plan) { return((from beam in plan.Beams where !beam.IsSetupField select CalculateForBeam(patient, plan, beam)).ToArray()); }
private Structure GetStructure(PlanSetup plan, string structureId) => plan?.StructureSet?.Structures?.FirstOrDefault(x => x.Id == structureId);
public void GetPQMSummaries(ConstraintViewModel constraintPath, PlanningItemViewModel planningItem, Patient patient) { PqmSummaries = new ObservableCollection <PQMSummaryViewModel>(); StructureSet structureSet = planningItem.PlanningItemStructureSet; Structure evalStructure; ObservableCollection <PQMSummaryViewModel> pqmSummaries = new ObservableCollection <PQMSummaryViewModel>(); ObservableCollection <StructureViewModel> foundStructureList = new ObservableCollection <StructureViewModel>(); var calculator = new PQMSummaryCalculator(); Objectives = calculator.GetObjectives(constraintPath); if (planningItem.PlanningItemObject is PlanSum) { var waitWindowPQM = new WaitWindowPQM(); PlanSum plansum = (PlanSum)planningItem.PlanningItemObject; if (plansum.IsDoseValid() == true) { waitWindowPQM.Show(); foreach (PQMSummaryViewModel objective in Objectives) { evalStructure = calculator.FindStructureFromAlias(structureSet, objective.TemplateId, objective.TemplateAliases, objective.TemplateCodes); if (evalStructure != null) { var evalStructureVM = new StructureViewModel(evalStructure); var obj = calculator.GetObjectiveProperties(objective, planningItem, structureSet, evalStructureVM); PqmSummaries.Add(obj); NotifyPropertyChanged("Structure"); } } waitWindowPQM.Close(); } } if (planningItem.PlanningItemObject is PlanSetup) //is plansetup { var waitWindowPQM = new WaitWindowPQM(); PlanSetup planSetup = (PlanSetup)planningItem.PlanningItemObject; if (planSetup.IsDoseValid() == true) { waitWindowPQM.Show(); foreach (PQMSummaryViewModel objective in Objectives) { evalStructure = calculator.FindStructureFromAlias(structureSet, objective.TemplateId, objective.TemplateAliases, objective.TemplateCodes); if (evalStructure != null) { if (evalStructure.StructureCodeInfos.FirstOrDefault().Code != null) { if (evalStructure.StructureCodeInfos.FirstOrDefault().Code.Contains("PTV") == true) { foreach (Structure s in structureSet.Structures) { if (s.Id == planSetup.TargetVolumeID) { evalStructure = s; } } } } var evalStructureVM = new StructureViewModel(evalStructure); var obj = calculator.GetObjectiveProperties(objective, planningItem, structureSet, evalStructureVM); PqmSummaries.Add(obj); NotifyPropertyChanged("Structure"); } } waitWindowPQM.Close(); } } }