def adaptive_optimization(plan, objective_adaptations): for beam_set in plan.BeamSets: completed = False while (completed == False): # Get the plan optimization corresponding to the current beam set: po = RSU.plan_optimization(plan, beam_set) # Run a new optimization with the updated average dose criterias: #plan.PlanOptimizations[0].RunOptimization() po.RunOptimization() # Assume the goals are reached until proven otherwise: completed = True # Check each objective: for oa in objective_adaptations: # Continue adapting if target has not been reached, and the achieved dose is above 1 cGy: if oa.on_target( ) == False and oa.objective.DoseFunctionParameters.DoseLevel > 1: completed = False # Function value is either too high or too low: if oa.objective.FunctionValue.FunctionValue < oa.function_value_low: # Function value is too low: It is possible to reduce dose further: oa.nr_dose_reductions += 1 oa.nr_dose_increases = 0 oa.set_dose_high(0.5 * (oa.dose_low + oa.dose_high)) # After new high limit has been set, the target function value should be between low and high limit: oa.objective.DoseFunctionParameters.DoseLevel = 0.5 * ( oa.dose_low + oa.dose_high) elif oa.objective.FunctionValue.FunctionValue > oa.function_value_high: # Function value is too high: We were too aggressive, dose limit must be increased: oa.nr_dose_increases += 1 oa.nr_dose_reductions = 0 oa.set_dose_low( oa.objective.DoseFunctionParameters.DoseLevel) # After new low limit has been set, the target function value should be between low and high limit: oa.objective.DoseFunctionParameters.DoseLevel = 0.5 * ( oa.dose_low + oa.dose_high)
def isocenter_centered_long_test(self): t = TEST.Test( "Isosenter skal i utgangspunktet være mest mulig sentrert i long-retning, avstand mellom isosenter og senter av normeringsvolumet bør være mindre enn 1 cm", '<1 cm', self.isocenter) if self.beam_set.Modality == 'Photons': diff = 0 ss = self.ts_structure_set().structure_set target0 = None target1 = None for roi in ss.RoiGeometries: if roi.OfRoi.Type == 'Ptv' and roi.PrimaryShape: # Determine if this target volume is relevant for this beam set (by checking if it is used as an objective): po = RSU.plan_optimization(self.ts_plan.plan, self.beam_set) if po: for objective in po.Objective.ConstituentFunctions: if objective.ForRegionOfInterest.Name == roi.OfRoi.Name: current_target = roi.GetBoundingBox() if target0 == None or current_target[ 0].z < target0: target0 = current_target[0].z if target1 == None or current_target[ 1].z > target1: target1 = current_target[1].z if self.is_vmat(): if target0 and target1: target_center_z = target0 + 0.5 * abs(target0 - target1) for beam in self.beam_set.Beams: photon_iso = beam.Isocenter.Position diff = abs(photon_iso.z - target_center_z) elif not self.is_vmat(): if not self.ts_label.label.region in RC.conventional_and_vmat_site_codes: if self.beam_set.Modality == 'Photons': for beam in self.beam_set.Beams: photon_iso = beam.Isocenter.Position for rg in self.ts_structure_set( ).structure_set.RoiGeometries: if rg.OfRoi.Name == self.beam_set.Prescription.PrimaryDosePrescription.OnStructure.Name: target = rg.GetBoundingBox() target_center_z = target[0].z + 0.5 * abs( target[0].z - target[1].z) diff = abs(photon_iso.z - target_center_z) if diff: if diff > 1: return t.fail(round(diff, 2)) else: return t.succeed()
def target_volume_normalisation_for_sib_test(self): if self.ts_label.label.region in RC.prostate_codes + RC.breast_codes + RC.rectum_codes: ss = self.ts_structure_set().structure_set roi_dict = SSF.create_roi_dict(ss) potential_target_volumes = [ ROIS.ctv_47.name, ROIS.ctv_56.name, ROIS.ctv_70_sib.name, ROIS.ctv_57.name ] objective_target_volumes = {} # Create a dictionary of all CTVs defined as an objective. po = RSU.plan_optimization(self.ts_plan.plan, self.beam_set) if po: for objective in po.Objective.ConstituentFunctions: if objective.ForRegionOfInterest.Type == 'Ctv': objective_target_volumes[ objective.ForRegionOfInterest.Name] = True # Check in the list of potential SIB volumes if any exist in the structure set, define as target for i in range(len(potential_target_volumes)): if roi_dict.get(potential_target_volumes[i]): target = potential_target_volumes[i] t = TEST.Test( "Skal stemme overens (innenfor 0.5%) med aktuell dose for normeringsvolumet " + target + ".", True, self.norm_dose) # Check if the target was used as objective if objective_target_volumes.get(target): # Use the two last characters in the target-string to find the wanted median dose of that target volume if int(target[-2:]) > 30: prescription_dose = int(target[-2:]) low_dose = round(prescription_dose * 0.995, 2) high_dose = round(prescription_dose * 1.005, 2) real_dose_d50 = RSU.gy( self.beam_set.FractionDose. GetDoseAtRelativeVolumes( RoiName=target, RelativeVolumes=[0.50])[0] ) * self.beam_set.FractionationPattern.NumberOfFractions t.expected = ">" + str( low_dose) + " og " + "<" + str(high_dose) if real_dose_d50 < low_dose or real_dose_d50 > high_dose: t.fail(round(real_dose_d50, 2)) else: t.succeed()
def asymmetric_jaw_opening_long_test(self): t = TEST.Test( "Isosenter ser ut til å være asymmetrisk, det bør vurderes å flytte isosenter. Dette for å få målt hele målvolumet med ArcCheck-fantomet", '<10.5 cm', self.isocenter) ss = self.ts_structure_set().structure_set isocenter = None target0 = None target1 = None if self.is_vmat(): for roi in ss.RoiGeometries: if roi.OfRoi.Type == 'Ptv' and roi.PrimaryShape: # Determine if this target volume is relevant for this beam set (by checking if it is used as an objective): po = RSU.plan_optimization(self.ts_plan.plan, self.beam_set) if po: for objective in po.Objective.ConstituentFunctions: if objective.ForRegionOfInterest.Name == roi.OfRoi.Name: current_target = roi.GetBoundingBox() if target0 == None or current_target[ 0].z < target0: target0 = current_target[0].z if target1 == None or current_target[ 1].z > target1: target1 = current_target[1].z for beam in self.beam_set.Beams: photon_iso = beam.Isocenter.Position if target0 and target1: if abs(target0 - target1) <= 21: if abs(photon_iso.z - target0) > 10.5: return t.fail(round(abs(photon_iso.z - target0), 2)) elif abs(photon_iso.z - target1) > 10.5: return t.fail(round(abs(photon_iso.z - target1), 2)) else: return t.succeed() else: return t.succeed()
for poi_geometry in structure_set.PoiGeometries: ts_poi_geometry = TS_PG.TSPOIGeometry( poi_geometry, ts_structure_set=ts_structure_set) for roi_geometry in structure_set.RoiGeometries: ts_roi_geometry = TS_RG.TSROIGeometry( roi_geometry, ts_structure_set=ts_structure_set) ts_plan = TS_PLAN.TSPlan(plan, ts_case=ts_case) for beam_set in plan.BeamSets: ts_beam_set = TS_BS.TSBeamSet(beam_set, ts_plan=ts_plan) ts_label = TS_L.TSLabel(beam_set.DicomPlanLabel, ts_beam_set=ts_beam_set) if beam_set.Prescription.PrimaryDosePrescription: ts_prescription = TS_PR.TSPrescription(beam_set.Prescription, ts_beam_set=ts_beam_set) po = RSU.plan_optimization(plan, beam_set) if po: ts_optimization = TS_O.TSOptimization(po, ts_beam_set=ts_beam_set) for beam in beam_set.Beams: ts_beam = TS_B.TSBeam(beam, ts_beam_set=ts_beam_set) for segment in beam.Segments: ts_segment = TS_S.TSSegment(segment, ts_beam=ts_beam) # Store the patient test results: self.result = ts_patient.param # Run tests: # Patient tests: ts_patient.id_length_test() ts_patient.id_space_test()