Beispiel #1
0
def check_input(ss, region_code, nr_fractions, fraction_dose):
  if region_code in RC.brain_codes:
    if region_code in RC.brain_whole_codes:
      error(nr_fractions, fraction_dose, [5, 10], [2.5, 3, 4])
    else:
      if fraction_dose > 6:
        error(nr_fractions, fraction_dose, [1, 3], [7, 8, 9, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25])
  elif region_code in RC.lung_codes:
    if nr_fractions in [3, 8] or nr_fractions == 5 and fraction_dose == 11:
      error(nr_fractions, fraction_dose, [3, 5, 8], [15, 11, 7])
    else:
      error(nr_fractions, fraction_dose, [2, 5, 10, 11, 12, 13, 15, 16, 17, 25, 30, 33, 35], [1.5, 1.8, 2, 2.8, 3, 4, 8.5])
  elif region_code in RC.breast_codes:
    if SSF.has_roi_with_shape(ss, ROIS.ctv_p.name):
      error(nr_fractions, fraction_dose, [15], [2.67])
    else:
      error(nr_fractions, fraction_dose, [25, 15], [2, 2.67])
  elif region_code in RC.bladder_codes:
    error(nr_fractions, fraction_dose, [3, 5, 6, 7, 10, 11, 12, 13, 25, 32], [2, 3, 3.5, 4, 7])
  elif region_code in RC.prostate_codes:
    if region_code in RC.prostate_bed_codes and SSF.has_roi_with_shape(ss, ROIS.ptv_70.name):
      error(nr_fractions, fraction_dose, [35], [2])
    elif SSF.has_roi_with_shape(ss, ROIS.ptv_77.name):
      error(nr_fractions, fraction_dose, [35], [2.2])
    elif SSF.has_roi_with_shape(ss, ROIS.ptv_60.name):
      error(nr_fractions, fraction_dose, [20], [3])
  elif region_code in RC.rectum_codes:
    if SSF.has_roi_with_shape(ss, ROIS.ctv_50.name):
      error(nr_fractions, fraction_dose, [25], [2])
    else:
      error(nr_fractions, fraction_dose, [30, 5], [1.5, 5]) # Added 1.5 Gy*30, which was used in a rectum case.
  elif region_code in RC.palliative_codes:
    if fraction_dose > 8:
      error(nr_fractions, fraction_dose, [1, 3], [9, 16])
Beispiel #2
0
def collect_target_strategy_and_region_codes(ss, nr_targets, region_code,
                                             prescription):
    region_codes = []
    target = None
    palliative_choices = None
    if nr_targets > 1:
        if region_code in RC.brain_codes + RC.lung_codes:
            if prescription.is_stereotactic():
                region_codes = multiple_beamset_form(ss, Toplevel())
                check_region_codes(region_code, region_codes)
        elif region_code in RC.palliative_codes:
            # For palliative cases with multiple targets:
            palliative_choices = palliative_beamset_form(ss, Toplevel())
            if palliative_choices[0] in [
                    'sep_beamset_iso', 'sep_beamset_sep_iso'
            ]:
                region_codes = multiple_beamset_form(ss, Toplevel())
                check_region_codes(region_code, region_codes)
                if SSF.has_roi_with_shape(ss, ROIS.ctv1.name):
                    target = ROIS.ctv1.name
                elif SSF.has_roi_with_shape(ss, ROIS.ctv2.name):
                    target = ROIS.ctv2.name
                elif SSF.has_roi_with_shape(ss, ROIS.ctv3.name):
                    target = ROIS.ctv3.name
                elif SSF.has_roi_with_shape(ss, ROIS.ctv4.name):
                    target = ROIS.ctv4.name
            elif palliative_choices[0] == 'sep_plan':
                target = palliative_choices[1]
    return target, palliative_choices, region_codes
Beispiel #3
0
def create_prostate_bed_objectives(ss, plan, total_dose):
    if SSF.has_roi_with_shape(ss, ROIS.ptv_56.name):  # With lymph node volume
        OF.uniform_dose(ss, plan, ROIS.ctv_70.name, total_dose * 100, 20)
        OF.uniform_dose(ss, plan, ROIS.ctv_56.name, 56 * 100, 20)
        OF.min_dose(ss, plan, ROIS.ptv_70.name, 67 * 100, 150)
        OF.min_dose(ss, plan, ROIS.ptv_56.name, 54 * 100, 150)
        OF.max_dose(ss, plan, ROIS.ptv_70.name, total_dose * 100 * 1.045, 70)
        OF.fall_off(ss, plan, ROIS.external.name, 70 * 100, 35 * 100, 3, 15)
        OF.max_dose(ss, plan, ROIS.external.name, total_dose * 100 * 1.05, 20)
        OF.max_dvh(ss, plan, ROIS.femoral_l.name, 35 * 100, 2, 10)
        OF.max_dvh(ss, plan, ROIS.femoral_r.name, 35 * 100, 2, 10)
        OF.max_dvh(ss, plan, ROIS.rectum.name, 72.5 * 100, 5, 10)
        OF.max_eud(ss, plan, ROIS.z_rectum.name, 35 * 100, 1, 1)
        OF.max_eud(ss, plan, ROIS.z_bladder.name, 44 * 100, 1, 2)
        OF.max_eud(ss, plan, ROIS.z_spc_bowel.name, 28 * 100, 1, 2)
        OF.fall_off(ss, plan, ROIS.z_ptv_70_wall.name, total_dose * 100,
                    56 * 100, 1, 1)
        OF.fall_off(ss, plan, ROIS.z_ptv_56_wall.name, 56 * 100, 42 * 100, 1,
                    1)
    else:  # Without lymph node volume
        OF.uniform_dose(ss, plan, ROIS.ctv_70.name, total_dose * 100, 25)
        OF.min_dose(ss, plan, ROIS.ptv_70.name, total_dose * 100 * 0.96, 100)
        OF.max_dose(ss, plan, ROIS.ptv_70.name, total_dose * 100 * 1.03, 50)
        OF.fall_off(ss, plan, ROIS.external.name, total_dose * 100,
                    total_dose * 100 / 2, 2, 20)
        OF.max_dose(ss, plan, ROIS.external.name, total_dose * 100 * 1.05, 40)
        OF.max_dvh(ss, plan, ROIS.femoral_l.name, 35 * 100, 2, 15)
        OF.max_dvh(ss, plan, ROIS.femoral_r.name, 35 * 100, 2, 15)
        OF.max_eud(ss, plan, ROIS.rectum.name, 40 * 100, 1, 2)
        OF.max_dvh(ss, plan, ROIS.z_rectum.name, 60 * 100, 3, 10)
        OF.max_eud(ss, plan, ROIS.z_rectum.name, 29.5 * 100, 1, 1)
        OF.max_eud(ss, plan, ROIS.z_rectum.name, 30 * 100, 5, 1)
        OF.max_dvh(ss, plan, ROIS.z_rectum.name, 51 * 100, 1, 10)
        OF.max_eud(ss, plan, ROIS.z_bladder.name, 25 * 100, 1, 3)
Beispiel #4
0
def create_lung_objectives(ss, plan, target, total_dose):
    if total_dose > 40:
        # Curative fractionation:
        OF.uniform_dose(ss, plan, target, total_dose * 100, 25)
        OF.max_dose(ss, plan, target, total_dose * 100 * 1.05, 5)
        OF.min_dvh(ss, plan, target, total_dose * 0.95 * 100, 98, 100)
        OF.min_dvh(ss, plan, ROIS.ptv.name, total_dose * 0.95 * 100, 95, 80)
        OF.max_dose(ss, plan, ROIS.ptv.name, total_dose * 100 * 1.05, 50)
        OF.max_eud(ss, plan, ROIS.esophagus.name, 0.51 * total_dose * 100, 1,
                   1)  # (~34 Gy for 66 Gy total dose)
        OF.max_dose(ss, plan, ROIS.external.name, total_dose * 100 * 1.05, 80)
        OF.fall_off(ss, plan, ROIS.external.name, total_dose * 100,
                    total_dose * 100 / 2, 3, 2)
        OF.max_eud(ss, plan, ROIS.heart.name, 0.53 * total_dose * 100, 1,
                   10)  # (~35 Gy for 66 Gy total dose)
        OF.max_eud(ss, plan, ROIS.spinal_canal.name, 0.6818 * total_dose * 100,
                   1, 10)  # (~45 Gy for 66 Gy total dose)
        match = False
        if SSF.has_roi_with_shape(ss, ROIS.lungs_gtv.name):
            l = ROIS.lungs_gtv.name
        elif SSF.has_roi_with_shape(ss, ROIS.lungs_igtv.name):
            l = ROIS.lungs_igtv.name
        else:
            l = ROIS.lungs.name
        OF.max_eud(ss, plan, l, 0.29 * total_dose * 100, 1,
                   15)  # (~19 Gy for 66 Gy total dose)
        OF.max_dvh(ss, plan, l, total_dose * 0.07575 * 100, 55,
                   70)  # (~5 Gy for 66 Gy total dose)
        OF.max_dvh(ss, plan, l, total_dose * 0.3030 * 100, 30,
                   80)  # (~5 Gy for 66 Gy total dose)
    elif total_dose < 40:
        # Palliative fractionation:
        OF.uniform_dose(ss, plan, target, total_dose * 100, 35)
        OF.max_dose(ss, plan, ROIS.ptv.name, total_dose * 100 * 1.05, 120)
        OF.min_dose(ss, plan, ROIS.ptv.name, total_dose * 100 * 0.95, 150)
        OF.max_dose(ss, plan, ROIS.external.name, total_dose * 100 * 1.05, 80)
        OF.fall_off(ss, plan, ROIS.external.name, total_dose * 100,
                    total_dose * 100 / 2, 3, 2)
        OF.max_eud(ss, plan, ROIS.heart.name, 0.29 * total_dose * 100, 1, 10)
        OF.max_eud(ss, plan, ROIS.lungs.name, 0.23 * total_dose * 100, 1, 15)
        OF.max_eud(ss, plan, ROIS.spinal_canal.name, 0.9 * total_dose * 100, 1,
                   5)
Beispiel #5
0
def create_breast_reg_objectives(ss, plan, region_code, total_dose,
                                 technique_name):
    if SSF.has_roi_with_shape(ss, ROIS.ctv_p.name):
        OF.fall_off(ss, plan, ROIS.external.name, total_dose * 100,
                    total_dose * 100 / 2, 2.5, 30)
        OF.max_dose(ss, plan, ROIS.external.name, total_dose * 100 * 1.05, 30)
        OF.max_eud(ss, plan, ROIS.heart.name, 2 * 100, 1, 5)
        OF.uniform_dose(ss, plan, ROIS.ctv.name, total_dose * 0.998 * 100, 15)
        OF.max_dvh(ss, plan, ROIS.ptv_c.name, total_dose * 1.044 * 100, 2, 100)
        if technique_name == 'VMAT':
            OF.min_dvh_robust(ss, plan, ROIS.ptv_pc.name,
                              total_dose * 0.97 * 100, 99, 100)
            OF.min_dvh(ss, plan, ROIS.ptv_c.name, total_dose * 0.97 * 100, 99,
                       100)
            if region_code in RC.breast_reg_l_codes:  # Left
                OF.max_eud(ss, plan, ROIS.breast_r.name, 3 * 100, 1, 1)
            else:
                OF.max_eud(ss, plan, ROIS.breast_l.name, 3 * 100, 1, 1)
        else:
            OF.min_dvh(ss, plan, ROIS.ptv_c.name, total_dose * 0.97 * 100, 99,
                       100)
    else:
        OF.fall_off(ss, plan, ROIS.external.name, total_dose * 100,
                    total_dose * 100 / 2, 2.5, 30)
        OF.max_dose(ss, plan, ROIS.external.name, total_dose * 100 * 1.05, 30)
        OF.max_eud(ss, plan, ROIS.heart.name, 2 * 100, 1, 5)
        OF.uniform_dose(ss, plan, ROIS.ctv_50.name, total_dose * 0.998 * 100,
                        15)
        OF.uniform_dose(ss, plan, ROIS.ctv_47.name, total_dose * 0.94 * 100, 5)
        OF.min_dvh(ss, plan, ROIS.ptv_47c.name, total_dose * 0.9 * 100, 99,
                   100)
        OF.max_dvh(ss, plan, ROIS.ptv_47c.name, total_dose * 0.95 * 100, 2,
                   100)
        OF.max_dvh(ss, plan, ROIS.ptv_50c.name, total_dose * 1.044 * 100, 2,
                   100)
        if technique_name == 'VMAT':
            OF.min_dvh_robust(ss, plan, ROIS.ptv_50c.name,
                              total_dose * 0.97 * 100, 99, 100)
            if region_code in RC.breast_reg_l_codes:  # Left
                OF.max_eud(ss, plan, ROIS.breast_r.name, 3 * 100, 1, 1)
            else:
                OF.max_eud(ss, plan, ROIS.breast_l.name, 3 * 100, 1, 1)
        else:
            OF.min_dvh(ss, plan, ROIS.ptv_50c.name, total_dose * 0.97 * 100,
                       99, 100)
Beispiel #6
0
def setup_beams(ss, examination, beam_set, isocenter, region_code, fraction_dose, technique_name, energy_name, iso_index = 1, beam_index=1):
  if technique_name == '3D-CRT':
    # 3D-CRT:
    if region_code in RC.breast_partial_l_codes:
      # Partial breast, left sided:
      BSF.create_three_beams(beam_set, isocenter, energy = energy_name, name1 = 'LPO', name2 = 'LAO', name3 = 'RAO', gantry_angle1 = '110', gantry_angle2 = '35', gantry_angle3 = '350', collimator_angle1 = '343', collimator_angle2 = '17', collimator_angle3 = '17', iso_index=iso_index, beam_index=beam_index)
      BSF.set_MU(beam_set,['LPO','LAO','RAO'], [90, 15, 90] )
    elif region_code in RC.breast_tang_l_codes:
      # Whole breast, left sided:
      BSF.create_two_beams(beam_set, isocenter, energy = energy_name, name1 = 'LPO', name2 = 'RAO', gantry_angle1 = '130', gantry_angle2 = '310', collimator_angle1 = '343', collimator_angle2 = '17', iso_index=iso_index, beam_index=beam_index)
      BSF.set_MU(beam_set,['LPO','RAO'], [110, 110] )
    elif region_code in RC.breast_partial_r_codes:
      # Partial breast, right sided:
      BSF.create_three_beams(beam_set, isocenter, energy = energy_name, name1 = 'RPO', name2 = 'RAO', name3 = 'LAO', gantry_angle1 = '250', gantry_angle2 = '325', gantry_angle3 = '10', collimator_angle1 = '9', collimator_angle2 = '352', collimator_angle3 = '352', iso_index=iso_index, beam_index=beam_index)
      BSF.set_MU(beam_set,['RPO','RAO','LAO'], [90, 15, 90] )
    elif region_code in RC.breast_tang_r_codes:
      # Whole breast, right sided:
      BSF.create_two_beams(beam_set, isocenter, energy = energy_name, name1 = 'RPO', name2 = 'LAO', gantry_angle1 = '230', gantry_angle2 = '50', collimator_angle1 = '9', collimator_angle2 = '352', iso_index=iso_index, beam_index=beam_index)
      BSF.set_MU(beam_set,['RPO','LAO'], [110, 110] )
    elif region_code in RC.breast_reg_l_codes:
      # Breast with regional lymph nodes, left sided:
      BSF.create_four_beams(beam_set, isocenter, energy = energy_name, name1 = 'LPO', name2 = 'Venstre', name3 = 'Forfra', name4 = 'RAO', gantry_angle1 = '130', gantry_angle2 = '90', gantry_angle3 = '0', gantry_angle4 = '309', iso_index=iso_index, beam_index=beam_index)
      if fraction_dose == 2:
        BSF.set_MU(beam_set,['LPO','Venstre','Forfra','RAO'], [25, 15, 100, 90] )
      elif fraction_dose == 2.67:
        BSF.set_MU(beam_set,['LPO','Venstre','Forfra','RAO'], [40, 25, 115, 105] )
    elif region_code in RC.breast_reg_r_codes:
      # Breast with regional lymph nodes, right sided:
      BSF.create_four_beams(beam_set, isocenter, energy = energy_name, name1 = 'RPO', name2 = 'Høyre', name3 = 'Forfra', name4 = 'LAO', gantry_angle1 = '235', gantry_angle2 = '270', gantry_angle3 = '0', gantry_angle4 = '55', iso_index=iso_index, beam_index=beam_index)
      if fraction_dose == 2:
        BSF.set_MU(beam_set,['RPO','Høyre','Forfra','LAO'], [25, 15, 100, 90] )
      elif fraction_dose == 2.67:
        BSF.set_MU(beam_set,['RPO','Høyre','Forfra','LAO'], [40, 25, 115, 105] )
    elif region_code in RC.brain_whole_codes:
      # Whole brain:
      BSF.create_two_beams(beam_set, isocenter, energy = '10', name1 = 'Høyre', name2 = 'Venstre', gantry_angle1 = '270', gantry_angle2 = '90', collimator_angle1 = '295', collimator_angle2 = '63', iso_index=iso_index, beam_index=beam_index)
      BSF.set_MU(beam_set,['Høyre','Venstre'], [130, 130] )
  elif technique_name == 'VMAT':
    # VMAT:
    # Brain:
    if region_code in RC.brain_whole_codes:
      # Whole brain:
      BSF.create_single_arc(beam_set, isocenter)
    elif region_code in RC.brain_partial_codes:
      # Partial brain:
      if fraction_dose > 15:
        BSF.create_single_arc(beam_set, isocenter, energy = energy_name, collimator_angle = '5', iso_index=iso_index, beam_index=beam_index)
      elif fraction_dose > 6: # Stereotactic brain
        BSF.create_single_arc(beam_set, isocenter, energy = energy_name, collimator_angle = '5', iso_index=iso_index, beam_index=beam_index)
      else:
        # Partial brain (ordinary fractionation):
        if SSF.partial_brain_conflict_oars(ss):
          BSF.create_single_arc(beam_set, isocenter, energy = energy_name, collimator_angle = '45', iso_index=iso_index, beam_index=beam_index)
        else:
          BSF.create_single_arc(beam_set, isocenter, energy = energy_name, collimator_angle = '5', iso_index=iso_index, beam_index=beam_index)
    # Breast with regional lymph nodes:
    elif region_code in RC.breast_reg_l_codes:
      BSF.create_single_arc(beam_set, isocenter, energy = energy_name, gantry_stop_angle = '300', gantry_start_angle = '179', collimator_angle = '5', iso_index=iso_index, beam_index=beam_index)
    elif region_code in RC.breast_reg_r_codes:
      BSF.create_single_arc(beam_set, isocenter, energy = energy_name, gantry_stop_angle = '60', gantry_start_angle = '181', collimator_angle = '5', iso_index=iso_index, beam_index=beam_index)
    # Lung:
    elif region_code in RC.lung_and_mediastinum_codes:
      if region_code in RC.lung_r_codes:
        # Right:
        BSF.create_single_arc(beam_set, isocenter, energy = energy_name, gantry_stop_angle = '30', gantry_start_angle = '181', collimator_angle = '5', iso_index=iso_index, beam_index=beam_index)
      elif region_code in RC.lung_l_codes:
        # Left:
        BSF.create_single_arc(beam_set, isocenter, energy = energy_name, gantry_stop_angle = '330', gantry_start_angle = '179', collimator_angle = '5', iso_index=iso_index, beam_index=beam_index)
      else:
        # Mediastinum or both lungs:
        BSF.create_single_arc(beam_set, isocenter, energy = energy_name, collimator_angle = '5', iso_index=iso_index, beam_index=beam_index)
    elif region_code in RC.bladder_codes:
      # Bladder:
      BSF.create_single_arc(beam_set, isocenter, energy = energy_name, iso_index=iso_index, beam_index=beam_index)
    elif region_code in RC.prostate_codes:
      # Prostate:
      if SSF.has_roi_with_shape(ss, ROIS.ptv_56.name):
        # With lymph nodes:
        BSF.create_single_arc(beam_set, isocenter, energy = energy_name, collimator_angle = '5', iso_index=iso_index, beam_index=beam_index)
      else:
        # Without lymph nodes:
        BSF.create_single_arc(beam_set, isocenter, energy = energy_name, iso_index=iso_index, beam_index=beam_index)
    elif region_code in RC.rectum_codes:
      # Rectum:
      BSF.create_single_arc(beam_set, isocenter, energy = energy_name, collimator_angle = '5', iso_index=iso_index, beam_index=beam_index)
    elif region_code in RC.palliative_codes:
      # Palliative treatment:
      if fraction_dose > 8:
        # Stereotactic fractionation:
        BSF.create_single_arc(beam_set, isocenter, energy = energy_name, collimator_angle = '5', iso_index=iso_index, beam_index=beam_index)
      else:
        # 'Normal' fractionation:
        if region_code in RC.whole_pelvis_codes:
          BSF.create_single_arc(beam_set, isocenter, energy = energy_name, collimator_angle = '5', iso_index=iso_index, beam_index=beam_index)
        else:
          if abs(isocenter.x) > 5:
            # Lateral treatment volume:
            if isocenter.x > 5 and CF.is_head_first_supine(examination) or not CF.is_head_first_supine(examination) and isocenter.x < -5:
              BSF.create_single_arc(beam_set, isocenter, energy = energy_name, gantry_stop_angle = '330', gantry_start_angle = '179', collimator_angle = '5', iso_index=iso_index, beam_index=beam_index)
            else:
              BSF.create_single_arc(beam_set, isocenter, energy = energy_name, gantry_stop_angle = '30', gantry_start_angle = '181', collimator_angle = '5', iso_index=iso_index, beam_index=beam_index)
          elif abs(isocenter.y) + 5 < abs(SSF.roi_center_y(ss, "External")):
            # Anterior treatment volume:
            BSF.create_single_arc(beam_set, isocenter, energy = energy_name, gantry_stop_angle = '250', gantry_start_angle = '110', collimator_angle = '5', iso_index=iso_index, beam_index=beam_index)
          else:
            BSF.create_single_arc(beam_set, isocenter, energy = energy_name, iso_index=iso_index, beam_index=beam_index)
  # Return the number of beams created:
  return len(list(beam_set.Beams))
Beispiel #7
0
class Plan(object):
    def __init__(self, patient, case, mq_patient):
        self.patient = patient
        self.case = case
        self.mq_patient = mq_patient

        # Load patient model, examination and structure set:
        pm = case.PatientModel
        examination = get_current("Examination")
        ss = PMF.get_structure_set(pm, examination)

        # Determine if a target volume is present (raises error if not):
        if not PMF.has_defined_ctv_or_ptv(pm, examination):
            GUIF.handle_missing_ctv_or_ptv()

        # Check if the last CT has been set as primary, and display a warning if not.
        success = TS_C.TSCase(case).last_examination_used_test()
        if not success:
            GUIF.handle_primary_is_not_most_recent_ct()

        # Setup and run GUI:
        my_window = Tk()
        (region_code, fraction_dose, nr_fractions, initials,
         total_dose) = GUIF.collect_fractionation_choices(my_window)

        # Load list of region codes and corresponding region names and get the region name for our particular region code (raise error if a name is not retrieved):
        regions = REGIONS.RegionList(
            "C:\\temp\\raystation-scripts\\settings\\regions.tsv")
        region_text = regions.get_text(region_code)
        assert region_text != None

        # For SBRT brain or lung, if there are multiple targets, an extra form appear where
        # the user has to type region code of the other targets.
        # FIXME: Bruke funksjon for test fx?
        # FIXME: Vurder hvor denne koden bør ligge.
        target = None
        palliative_choices = None
        nr_targets = SSF.determine_nr_of_indexed_ptvs(ss)
        if nr_targets > 1:
            if region_code in RC.brain_codes + RC.lung_codes:
                if PF.is_stereotactic(nr_fractions, fraction_dose):
                    region_codes = GUIF.multiple_beamset_form(ss, Toplevel())
                    GUIF.check_region_codes(region_code, region_codes)
            elif region_code in RC.palliative_codes:
                # For palliative cases with multiple targets:
                palliative_choices = GUIF.palliative_beamset_form(
                    ss, Toplevel())
                if palliative_choices[0] in [
                        'sep_beamset_iso', 'sep_beamset_sep_iso'
                ]:
                    region_codes = GUIF.multiple_beamset_form(ss, Toplevel())
                    GUIF.check_region_codes(region_code, region_codes)
                    if SSF.has_roi_with_shape(ss, ROIS.ctv1.name):
                        target = ROIS.ctv1.name
                    elif SSF.has_roi_with_shape(ss, ROIS.ctv2.name):
                        target = ROIS.ctv2.name
                    elif SSF.has_roi_with_shape(ss, ROIS.ctv3.name):
                        target = ROIS.ctv3.name
                    elif SSF.has_roi_with_shape(ss, ROIS.ctv4.name):
                        target = ROIS.ctv4.name
                elif palliative_choices[0] == 'sep_plan':
                    target = palliative_choices[1]

        # Set up plan, making sure the plan name does not already exist. If the plan name exists, (1), (2), (3) etc is added behind the name.
        plan = CF.create_plan(case, examination, region_text)

        # Check that the number of fractions and fraction dose is among those expected for the given region code
        GUIF.check_input(ss, region_code, nr_fractions, fraction_dose)

        # Set planners initials
        plan.PlannedBy = initials

        # Set dose grid, 0.2x0.2x0.2 cm3 for stereotactic treatments and for prostate and 0.3x03x0.3 cm3 otherwise
        PF.set_dose_grid(plan, region_code, nr_fractions, fraction_dose)

        my_window = Toplevel()
        # Determine which technique and optimization choices which will appear in the form
        results = GUIF.determine_choices(region_code, nr_fractions,
                                         fraction_dose, my_window, [])
        # Chosen technique value, 'VMAT' or 'Conformal'
        technique = results[0]
        # Chosen technique name, 'VMAT' or '3D-CRT'
        technique_name = results[1]
        # Chosen optimization value
        opt = results[2]

        # Determine prescription target:
        if not target:
            roi_dict = SSF.create_roi_dict(ss)
            target = SSF.determine_target(ss, roi_dict, nr_fractions,
                                          fraction_dose)

        # Translate the couch in the longitudinal direction according to the target position
        if SSF.has_roi_with_shape(ss, ROIS.couch.name):
            PMF.translate_couch_long(pm, ss, examination, target)

        # Create 'Mask_PTV' for partial brain and stereotactic brain
        if region_code in RC.brain_codes and region_code not in RC.brain_whole_codes:
            if nr_targets > 1:
                targets = [ROIS.ptv1, ROIS.ptv2, ROIS.ptv3, ROIS.ptv4]
                for i in range(nr_targets):
                    SSF.create_expanded_and_intersected_volume(
                        pm, examination, ss, targets[i], ROIS.external,
                        ROIS.mask_ptv.name + str(i + 1), 1600)
                    patient.SetRoiVisibility(RoiName=ROIS.mask_ptv.name +
                                             str(i + 1),
                                             IsVisible=False)
            else:
                SSF.create_expanded_and_intersected_volume(
                    pm, examination, ss, ROIS.ptv, ROIS.external,
                    ROIS.mask_ptv.name, 1600)
                patient.SetRoiVisibility(RoiName=ROIS.mask_ptv.name,
                                         IsVisible=False)

        # Create 'Mask_PTV' for stereotactic lung
        if region_code in RC.lung_codes and PF.is_stereotactic(
                nr_fractions, fraction_dose):
            if nr_targets > 1:
                targets = [ROIS.ptv1, ROIS.ptv2, ROIS.ptv3]
                for i in range(nr_targets):
                    created = SSF.create_roi_subtraction(
                        pm, examination, ss, targets[i], ROIS.chestwall,
                        ROIS.mask_ptv.name + str(i + 1), 0)
                    if created:
                        patient.SetRoiVisibility(RoiName=ROIS.mask_ptv.name +
                                                 str(i + 1),
                                                 IsVisible=False)
            else:
                created = SSF.create_roi_subtraction(pm, examination, ss,
                                                     ROIS.ptv, ROIS.chestwall,
                                                     ROIS.mask_ptv.name, 0)
                if created:
                    patient.SetRoiVisibility(RoiName=ROIS.mask_ptv.name,
                                             IsVisible=False)

        # Determine name of the body contour ('External' or 'Body'):
        external = SSF.body_roi_name(ss)
        if not external:
            GUIF.handle_missing_external()

        # Determine the machine name from the size of the target volume, only one target is taken into consideration here.
        # For those situations where you have two targets and you want to have separate isocenters, then you what to evaluate the targets separately.
        if target in [
                ROIS.ctv1.name, ROIS.ctv2.name, ROIS.ctv3.name, ROIS.ctv4.name
        ] and palliative_choices[0] in ['sep_beamset_sep_iso', 'sep_plan']:
            energy_name = SSF.determine_energy_single_target(ss, target)
        elif region_code in RC.breast_codes:
            energy_name = '6'
        else:
            # Determine the machine name from the size of the target volume:
            energy_name = SSF.determine_energy(ss, target)

        # Create the name of the beamset
        beam_set_name = BSF.label(region_code, fraction_dose, nr_fractions,
                                  technique)

        # Create primary beam set:
        beam_set = PF.create_beam_set(plan, beam_set_name, examination,
                                      technique, nr_fractions)
        # Add prescription:
        BSF.add_prescription(beam_set, nr_fractions, fraction_dose, target)
        # Determine the point which will be our isocenter:
        if nr_targets > 1:
            if palliative_choices and palliative_choices[0] in [
                    'sep_beamset_iso', 'beamset'
            ]:
                # Consider all targets when determining isocenter:
                isocenter = SSF.determine_isocenter(examination,
                                                    ss,
                                                    region_code,
                                                    technique_name,
                                                    target,
                                                    external,
                                                    multiple_targets=True)
            else:
                # Set isocenter for PTV1:
                isocenter = SSF.determine_isocenter(examination, ss,
                                                    region_code,
                                                    technique_name, target,
                                                    external)
        else:
            # Consider all targets when determining isocenter:
            isocenter = SSF.determine_isocenter(examination,
                                                ss,
                                                region_code,
                                                technique_name,
                                                target,
                                                external,
                                                multiple_targets=True)
        # Determine if this patient has any previous beams in Mosaiq (which impacts which beam number is to be used with this plan):
        beam_nr = 1
        if self.mq_patient:
            beam_nr = self.mq_patient.next_available_field_number()
        # Setup beams or arcs
        nr_beams = BEAMS.setup_beams(ss,
                                     examination,
                                     beam_set,
                                     isocenter,
                                     region_code,
                                     fraction_dose,
                                     technique_name,
                                     energy_name,
                                     beam_index=beam_nr)

        # For SBRT brain or lung, if there are multiple targets, create beam sets for all targets
        # FIXME: Bruke funksjon for test fx?
        if nr_targets > 1:
            if region_code in RC.brain_codes + RC.lung_codes and region_code not in RC.brain_whole_codes:
                if PF.is_stereotactic(nr_fractions, fraction_dose):
                    PF.create_additional_stereotactic_beamsets_prescriptions_and_beams(
                        plan,
                        examination,
                        ss,
                        region_codes,
                        fraction_dose,
                        nr_fractions,
                        external,
                        energy_name,
                        nr_existing_beams=nr_beams)
            elif region_code in RC.palliative_codes:
                # Palliative cases with multiple targets:
                if palliative_choices[0] in [
                        'sep_beamset_iso', 'sep_beamset_sep_iso'
                ]:
                    if palliative_choices[0] == 'sep_beamset_iso':
                        PF.create_additional_palliative_beamsets_prescriptions_and_beams(
                            plan,
                            examination,
                            ss,
                            region_codes,
                            fraction_dose,
                            nr_fractions,
                            external,
                            energy_name,
                            nr_existing_beams=nr_beams,
                            isocenter=isocenter)
                    else:
                        PF.create_additional_palliative_beamsets_prescriptions_and_beams(
                            plan,
                            examination,
                            ss,
                            region_codes,
                            fraction_dose,
                            nr_fractions,
                            external,
                            energy_name,
                            nr_existing_beams=nr_beams)

        # If there is a 2Gy x 8 boost for breast patients
        if SSF.has_roi_with_shape(
                ss, ROIS.ctv_sb.name) and SSF.has_roi_with_shape(
                    ss, ROIS.ptv_c.name) and region_code in RC.breast_codes:
            PF.create_breast_boost_beamset(
                ss,
                plan,
                examination,
                isocenter,
                region_code,
                ROIS.ctv_sb.name,
                background_dose=int(round(fraction_dose * nr_fractions)))
            # Make sure that the original beam set (not this boost beam set) is loaded in the GUI:
            infos = plan.QueryBeamSetInfo(
                Filter={'Name': '^' + beam_set_name + '$'})
            plan.LoadBeamSet(BeamSetInfo=infos[0])

        # Determines and sets up isodoses based on region code and fractionation
        CF.determine_isodoses(case, ss, region_code, nr_fractions,
                              fraction_dose)

        # Determine site
        site = SF.site(pm, examination, ss, plan, nr_fractions, total_dose,
                       region_code, target, technique_name)

        # Set up Clinical Goals:
        es = plan.TreatmentCourse.EvaluationSetup
        CG.setup_clinical_goals(ss, es, site, total_dose, nr_fractions, target)
        # Loads the plan, done after beam set is created, as this is the only way the CT-images appears in Plan Design and Plan Optimization when the plan is loaded
        CF.load_plan(case, plan)

        # Set up beams and optimization for breast patients
        if technique_name == 'VMAT' and region_code in RC.breast_reg_codes:
            # Use robust optimization for VMAT breast:
            OBJF.set_robustness_breast(plan, region_code)
        elif technique_name == '3D-CRT' and region_code in RC.breast_codes:
            if region_code in RC.breast_reg_codes:
                BSF.set_up_beams_and_optimization_for_regional_breast(
                    plan, beam_set, ROIS.ptv_c.name, region_code)
            else:
                BSF.set_up_beams_and_optimization_for_tangential_breast(
                    plan, beam_set, plan.PlanOptimizations[0],
                    target.replace("C", "P") + "c")
                # If there is a 2Gy x 8 boost for breast patients
                if SSF.has_roi_with_shape(
                        ss, ROIS.ctv_sb.name) and SSF.has_roi_with_shape(
                            ss, ROIS.ptv_c.name):
                    BSF.set_up_beams_and_optimization_for_tangential_breast(
                        plan, plan.BeamSets[1], plan.PlanOptimizations[1],
                        ROIS.ptv_sbc.name)

        # Set up treat and protect for stereotactic lung
        #if region_code in RC.lung_codes and PF.is_stereotactic(nr_fractions, fraction_dose):
        #  BSF.set_up_treat_and_protect_for_stereotactic_lung(beam_set, target, 0.5)

        # Run first optimization on each beam set:
        for po in plan.PlanOptimizations:
            po.OptimizationParameters.DoseCalculation.ComputeFinalDose = True
            # Set 'Constrain leaf motion' to 0.3 for stereotactic patients
            if PF.is_stereotactic(nr_fractions, fraction_dose):
                acp = po.OptimizationParameters.TreatmentSetupSettings[
                    0].SegmentConversion.ArcConversionProperties
                acp.UseMaxLeafTravelDistancePerDegree = True
                acp.MaxLeafTravelDistancePerDegree = 0.3
            po.RunOptimization()

        # Start adaptive optimization if indicated
        if opt == 'oar':
            OBJF.adapt_optimization_oar(ss, plan, site.oar_objectives,
                                        region_code)
            if region_code in RC.breast_codes:
                if region_code in RC.breast_reg_codes:
                    # Need to close leafs behind jaw for breast regional patients
                    BSF.close_leaves_behind_jaw_for_regional_breast(beam_set)
                # Create 2.5 cm margin to air for breast patient planned with a 3D-CRT technique for robustness purpuses
                BSF.create_margin_air_for_3dcrt_breast(ss, beam_set,
                                                       region_code)
                # Compute dose
                beam_set.ComputeDose(DoseAlgorithm='CCDose')
            # Auto scale to prescription
            for po in plan.PlanOptimizations:
                po.AutoScaleToPrescription = True
        # Load plan
        CF.load_plan(case, plan)

        # Save
        patient.Save()
Beispiel #8
0
def create_prostate_objectives(ss, plan, total_dose):
    if total_dose == 60:  # Hypofractionation
        OF.uniform_dose(ss, plan, ROIS.ctv_60.name, total_dose * 100, 40)
        OF.uniform_dose(ss, plan, ROIS.ctv_57.name, total_dose * 0.95 * 100,
                        40)
        OF.min_dose(ss, plan, ROIS.ptv_60.name, 57.1 * 100, 150)
        OF.min_dose(ss, plan, ROIS.ptv_57.name, total_dose * 100 * 0.91, 170)
        OF.min_dose(ss, plan, ROIS.ctv_57.name, total_dose * 100 * 0.93, 35)
        OF.max_dose(ss, plan, ROIS.ptv_60.name, total_dose * 100 * 1.02, 60)
        OF.max_dvh(ss, plan, ROIS.ptv_57.name, total_dose * 0.978 * 100, 1, 50)
        OF.fall_off(ss, plan, ROIS.external.name, total_dose * 100,
                    total_dose * 100 / 2, 1.5, 30)
        OF.max_dose(ss, plan, ROIS.external.name, total_dose * 100 * 1.038, 25)
        OF.max_dvh(ss, plan, ROIS.femoral_l.name, 20 * 100, 2, 10)
        OF.max_dvh(ss, plan, ROIS.femoral_r.name, 20 * 100, 2, 10)
        OF.max_eud(ss, plan, ROIS.rectum.name, 22.6 * 100, 1, 2)
        OF.max_dvh(ss, plan, ROIS.rectum.name, total_dose * 0.975 * 100, 3, 4)
        OF.max_eud(ss, plan, ROIS.z_rectum.name, 18 * 100, 1, 1)
        OF.max_eud(ss, plan, ROIS.z_rectum.name, 28 * 100, 3, 1)
        OF.max_dvh(ss, plan, ROIS.z_rectum.name, 51 * 100, 1, 10)
        OF.max_eud(ss, plan, ROIS.z_bladder.name, 12.4 * 100, 1, 1)
        OF.fall_off(ss, plan, ROIS.z_ptv_60_wall.name, total_dose * 100,
                    57 * 100, 0.3, 1)
        OF.fall_off(ss, plan, ROIS.z_ptv_57_60_wall.name, total_dose * 100,
                    42 * 100, 0.8, 12)
    elif total_dose == 55:  # Hypofractionation
        OF.uniform_dose(ss, plan, ROIS.ctv.name, total_dose * 100, 40)
        OF.min_dose(ss, plan, ROIS.ptv.name, 52.3 * 100, 150)
        OF.max_dose(ss, plan, ROIS.ptv.name, total_dose * 100 * 1.02, 60)
        OF.fall_off(ss, plan, ROIS.external.name, total_dose * 100,
                    total_dose * 100 / 2, 1.5, 30)
        OF.max_dose(ss, plan, ROIS.external.name, total_dose * 100 * 1.038, 25)
        OF.max_dvh(ss, plan, ROIS.femoral_l.name, 20 * 100, 2, 10)
        OF.max_dvh(ss, plan, ROIS.femoral_r.name, 20 * 100, 2, 10)
        OF.max_eud(ss, plan, ROIS.rectum.name, 22.6 * 100, 1, 2)
        OF.max_dvh(ss, plan, ROIS.rectum.name, total_dose * 0.975 * 100, 3, 4)
        OF.max_eud(ss, plan, ROIS.z_rectum.name, 18 * 100, 1, 1)
        OF.max_eud(ss, plan, ROIS.z_rectum.name, 28 * 100, 3, 1)
        OF.max_dvh(ss, plan, ROIS.z_rectum.name, 51 * 100, 1, 10)
        OF.max_eud(ss, plan, ROIS.z_bladder.name, 12.4 * 100, 1, 1)
        OF.fall_off(ss, plan, ROIS.z_ptv_wall.name, total_dose * 100, 42 * 100,
                    1, 1)
    elif total_dose == 77 and SSF.has_roi_with_shape(
            ss, ROIS.ptv_56.name):  # Normo-fractionation and lymph node volume
        OF.uniform_dose(ss, plan, ROIS.ctv_56.name, 56 * 100, 15)
        OF.uniform_dose(ss, plan, ROIS.ctv_70_sib.name, 70 * 100, 25)
        OF.uniform_dose(ss, plan, ROIS.ctv_77.name, 77 * 100, 20)
        OF.min_dose(ss, plan, ROIS.ptv_56.name, 55 * 100, 100)
        OF.max_dvh(ss, plan, ROIS.ptv_56.name, 58.5 * 100, 5, 5)
        OF.min_dose(ss, plan, ROIS.ptv_70_sib.name, total_dose * 100 * 0.88,
                    100)
        OF.max_dvh(ss, plan, ROIS.ptv_70_sib.name, total_dose * 0.95 * 100, 5,
                   50)
        OF.min_dose(ss, plan, ROIS.ptv_77.name, total_dose * 100 * 0.98, 100)
        OF.max_dose(ss, plan, ROIS.ptv_77.name, total_dose * 100 * 1.02, 70)
        OF.max_dose(ss, plan, ROIS.external.name, total_dose * 100 * 1.05, 20)
        OF.fall_off(ss, plan, ROIS.external.name, 56 * 100, 28 * 100, 2, 15)
        OF.max_dvh(ss, plan, ROIS.femoral_l.name, 35 * 100, 2, 10)
        OF.max_dvh(ss, plan, ROIS.femoral_r.name, 35 * 100, 2, 10)
        OF.max_dvh(ss, plan, ROIS.rectum.name, 72.5 * 100, 5, 10)
        OF.max_eud(ss, plan, ROIS.z_rectum.name, 31 * 100, 1, 1)
        OF.max_eud(ss, plan, ROIS.z_bladder.name, 34 * 100, 1, 2)
        OF.max_eud(ss, plan, ROIS.z_spc_bowel.name, 14.2 * 100, 1, 2)
        OF.fall_off(ss, plan, ROIS.z_ptv_77_wall.name, total_dose * 100,
                    71 * 100, 0.3, 10)
        OF.fall_off(ss, plan, ROIS.z_ptv_70_77_wall.name, total_dose * 100,
                    56 * 100, 0.5, 5)
    elif total_dose == 77:  # Normo-fractionation
        OF.uniform_dose(ss, plan, ROIS.ctv_77.name, total_dose * 100, 40)
        OF.uniform_dose(ss, plan, ROIS.ctv_70_sib.name, 70 * 100, 40)
        OF.min_dose(ss, plan, ROIS.ctv_70_sib.name, total_dose * 100 * 0.89,
                    25)
        OF.min_dose(ss, plan, ROIS.ptv_77.name, total_dose * 100 * 0.98, 150)
        OF.min_dvh(ss, plan, ROIS.ptv_70_sib.name, total_dose * 100 * 0.89, 98,
                   150)
        OF.max_dose(ss, plan, ROIS.ptv_77.name, total_dose * 100 * 1.02, 70)
        OF.max_dose(ss, plan, ROIS.ptv_70_sib.name, total_dose * 0.935 * 100,
                    50)
        OF.fall_off(ss, plan, ROIS.external.name, total_dose * 100,
                    total_dose * 100 / 2, 1.5, 30)
        OF.max_dose(ss, plan, ROIS.external.name, total_dose * 100 * 1.038, 25)
        OF.max_dvh(ss, plan, ROIS.femoral_l.name, 35 * 100, 2, 10)
        OF.max_dvh(ss, plan, ROIS.femoral_r.name, 35 * 100, 2, 10)
        OF.max_eud(ss, plan, ROIS.rectum.name, 40 * 100, 1, 2)
        OF.max_dvh(ss, plan, ROIS.rectum.name, 72.4 * 100, 5, 15)
        OF.max_dvh(ss, plan, ROIS.z_rectum.name, 60 * 100, 3, 10)
        OF.max_eud(ss, plan, ROIS.z_rectum.name, 29.5 * 100, 1, 1)
        OF.max_eud(ss, plan, ROIS.z_rectum.name, 30 * 100, 5, 1)
        OF.max_dvh(ss, plan, ROIS.z_rectum.name, 51 * 100, 1, 10)
        OF.max_eud(ss, plan, ROIS.z_bladder.name, 25 * 100, 1, 3)
        OF.fall_off(ss, plan, ROIS.z_ptv_77_wall.name, total_dose * 100,
                    68 * 100, 0.3, 15)
Beispiel #9
0
def load_plan(case, plan):
    current_plan = case.QueryPlanInfo(Filter={'Name': plan.Name})
    case.LoadPlan(PlanInfo=current_plan[0])


# Set isodose lines:
def determine_isodoses(case, ss, region_code, nr_fractions, fraction_dose):
    case.CaseSettings.DoseColorMap.PresentationType = 'Relative'
    case.CaseSettings.DoseColorMap.ReferenceValue = nr_fractions * fraction_dose * 100

    if region_code in RC.breast_codes and fraction_dose == 2 or region_code in RC.rectum_codes and fraction_dose == 2:
        ISODOSES.sib_47_50.apply_to(case)
    elif region_code in RC.prostate_codes:
        if fraction_dose in [2.0, 2.2]:
            if region_code in RC.prostate_bed_codes:
                if SSF.has_roi_with_shape(ss, ROIS.ctv_56.name):
                    ISODOSES.prostate_bed_56_70.apply_to(case)
                else:
                    ISODOSES.standard.apply_to(case)
            else:
                if SSF.has_roi_with_shape(ss, ROIS.ctv_56.name):
                    ISODOSES.prostate_56_70_77.apply_to(case)
                else:
                    ISODOSES.prostate_70_77.apply_to(case)
        elif fraction_dose == 3 and SSF.has_roi_with_shape(
                ss, ROIS.ctv_57.name):
            ISODOSES.prostate_57_60.apply_to(case)
        else:
            ISODOSES.standard.apply_to(case)
    elif PF.is_stereotactic(nr_fractions, fraction_dose):
        ISODOSES.stereotactic.apply_to(case)