def create_couch(patient_db, pm, ss, examination): for pm_roi in pm.RegionsOfInterest: if pm_roi.Name == 'Couch': pm_roi.DeleteRoi() break templateInfo = patient_db.GetPatientModelTemplateInfo() for i in range(0, len(templateInfo)): template = patient_db.LoadTemplatePatientModel( templateName=templateInfo[i]['Name'], lockMode='Read') if template.Name == 'Bordtopp tykk': pm.CreateStructuresFromTemplate( SourceTemplate=template, SourceExaminationName='CT 1', SourceRoiNames=[ROIS.couch.name], SourcePoiNames=[], AssociateStructuresByName=False, TargetExamination=examination, InitializationOption='AlignImageCenters') # Get the box coordinates of the couch: ss = pm.StructureSets[examination.Name] couch_geometry = ss.RoiGeometries['Couch'] couch_box = couch_geometry.GetBoundingBox() # Box coordinates of examination: examination_box = examination.Series[0].ImageStack.GetBoundingBox() # Slice thickness: slice_thickness = abs( examination.Series[0].ImageStack.SlicePositions[1] - examination.Series[0].ImageStack.SlicePositions[0]) # Aim to apply a margin which extends the couch geometry to within one slice from the ends of the CT scan: # Inferior/caudal margin (must be minimum 0): margin_inferior = couch_box[0].z - (examination_box[0].z + slice_thickness) margin_inferior = max(margin_inferior, 0) # Superior/cranial margin (must be minimum 0): margin_superior = examination_box[1].z - (couch_box[1].z + slice_thickness) margin_superior = max(margin_superior, 0) # Create corresponding margin object: couch_margin = MARGIN.Expansion(margin_superior, margin_inferior, 0.0, 0.0, 0.0, 0.0) # Create extended couch ROI recipe object: couch_extended = ROI.ROIExpanded('Couch_extended', 'Support', COLORS.couch, ROIS.couch, margins=couch_margin) # Create extended couch ROI in RayStation: create_expanded_roi(pm, examination, ss, couch_extended) # Set the material of the extended couch ROI ('Bordtopp (tykk)'): pm.RegionsOfInterest['Couch_extended'].SetRoiMaterial( Material=pm.Materials[0]) # Delete the original Couch ROI: pm.RegionsOfInterest['Couch'].DeleteRoi() # Rename the extended Couch: pm.RegionsOfInterest['Couch_extended'].Name = 'Couch'
import colors as COLORS import margins as MARGINS import roi as ROI # External: external = ROI.ROI('External', 'External', COLORS.external) body = ROI.ROI('Body', 'Organ', COLORS.external) # Support: couch = ROI.ROI('Couch', 'Support', COLORS.couch) # Target volumes: gtv = ROI.ROI('GTV', 'Gtv', COLORS.gtv) ctv = ROI.ROIExpanded('CTV', 'Ctv', COLORS.ctv, gtv, margins=MARGINS.uniform_5mm_expansion) ptv = ROI.ROIExpanded('PTV', 'Ptv', COLORS.ptv, ctv, margins=MARGINS.uniform_5mm_expansion) ctv_ext = ROI.ROIAlgebra('CTV', 'Ctv', COLORS.ctv, sourcesA=[gtv], sourcesB=[external], operator='Intersection', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.uniform_5mm_contraction)
def __init__(self, pm, examination, ss, choices, site): # Choice 1: Scope (whole brain, part or stereotactic). region = choices[1] # Region: if region == 'whole': # Whole brain: # Choice 2: Involvement of menignes. meninges = choices[2] if meninges == 'yes': brain_margin = MARGINS.uniform_1mm_expansion else: brain_margin = MARGINS.zero # Targets: ctv = ROI.ROIExpanded(ROIS.ctv.name, ROIS.ctv.type, COLORS.ctv, ROIS.brain, margins=brain_margin) ptv = ROI.ROIExpanded(ROIS.ptv.name, ROIS.ptv.type, COLORS.ptv, ctv, margins=MARGINS.uniform_3mm_expansion) site.add_targets([ctv, ptv]) # OARs: site.add_oars(DEF.brain_whole_oars) elif region == 'part': # Partial Brain: # Targets: ctv = ROI.ROIAlgebra(ROIS.ctv.name, ROIS.ctv.type, COLORS.ctv, sourcesA=[ROIS.gtv], sourcesB=[ROIS.brain], operator='Intersection', marginsA=MARGINS.uniform_20mm_expansion, marginsB=MARGINS.uniform_1mm_expansion) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, COLORS.ptv, sourcesA=[ctv], sourcesB=[ROIS.body], operator='Intersection', marginsA=MARGINS.uniform_3mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) site.add_targets([ROIS.gtv, ctv, ptv]) # OARs: brain_gtv = ROI.ROIAlgebra(ROIS.brain_gtv.name, ROIS.brain_gtv.type, ROIS.brain.color, sourcesA=[ROIS.brain], sourcesB=[ROIS.gtv], operator='Subtraction') brain_ptv = ROI.ROIAlgebra(ROIS.brain_ptv.name, ROIS.brain_ptv.type, ROIS.other_ptv.color, sourcesA=[ROIS.brain], sourcesB=[ptv], operator='Subtraction') site.add_oars(DEF.brain_partial_oars + [brain_gtv, brain_ptv]) elif region == 'stereotactic': # Stereotactic brain: # Choice 2: Nr of targets. nr_targets = int(choices[2]) gtvs = [] ptvs = [] walls = [] # How many targets? if nr_targets == 1: # Single target: gtv = ROI.ROI('GTV', 'Gtv', ROIS.gtv.color) ptv = ROI.ROIExpanded(ROIS.ptv.name, ROIS.ptv.type, COLORS.ptv, gtv, margins=MARGINS.uniform_2mm_expansion) gtvs.append(gtv) ptvs.append(ptv) walls.append( ROI.ROIWall(ROIS.z_ptv_wall.name, ROIS.z_ptv_wall.type, COLORS.wall, ptvs[-1], 1, 0)) else: # Multiple targets (2, 3 or 4): for i in range(0, nr_targets): # Targets: gtvs.append( ROI.ROI('GTV' + str(i + 1), 'Gtv', ROIS.gtv.color)) ptvs.append( ROI.ROIExpanded(ROIS.ptv.name + str(i + 1), ROIS.ptv.type, COLORS.ptv, gtvs[-1], margins=MARGINS.uniform_2mm_expansion)) # OARs: walls.append( ROI.ROIWall("zPTV" + str(i + 1) + "_Wall", ROIS.z_ptv_wall.type, COLORS.wall, ptvs[-1], 1, 0)) # Union target volumes: gtv = ROI.ROIAlgebra(ROIS.gtv.name, ROIS.gtv.type, ROIS.gtv.color, sourcesA=[gtvs[0]], sourcesB=gtvs[1:]) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ptvs[0]], sourcesB=ptvs[1:]) gtvs.append(gtv) ptvs.append(ptv) # Common for single or multiple SRT targets: # Brain with targets excluded: brain_gtv = ROI.ROIAlgebra(ROIS.brain_gtv.name, ROIS.brain_gtv.type, ROIS.brain.color, sourcesA=[ROIS.brain], sourcesB=[gtv], operator='Subtraction') brain_ptv = ROI.ROIAlgebra(ROIS.brain_ptv.name, ROIS.brain_ptv.type, ROIS.other_ptv.color, sourcesA=[ROIS.brain], sourcesB=[ptv], operator='Subtraction') # Add to site: site.add_targets(gtvs + ptvs) site.add_oars(DEF.brain_stereotactic_oars + [brain_gtv, brain_ptv] + walls) # Create all targets and OARs in RayStation: site.create_rois()
def __init__(self, pm, examination, ss, choices, site): # Choice 1: Stereotactic or not? stereotactic = choices[1] # Choice 2: Region region = choices[2] # Stereotactic: if stereotactic == 'yes': if region in ['col thorax', 'col pelvis']: if region == 'col thorax': site.add_oars(DEF.palliative_stereotactic_thorax_oars) elif region == 'col pelvis': site.add_oars(DEF.palliative_stereotactic_spine_pelvis_oars) ctv = ROI.ROIExpanded(ROIS.ctv.name, ROIS.ctv.type, COLORS.ctv_med, ROIS.gtv, margins = MARGINS.uniform_3mm_expansion) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ctv], sourcesB=[ROIS.vb]) ptv_gtv = ROI.ROIAlgebra(ROIS.ptv_gtv.name, ROIS.ptv_gtv.type, COLORS.ptv_med, sourcesA = [ptv], sourcesB = [ROIS.gtv], operator='Subtraction') ptv_spinal = ROI.ROIAlgebra(ROIS.ptv_spinal.name, ROIS.ptv_spinal.type, COLORS.ptv_med, sourcesA = [ptv], sourcesB = [ROIS.spinal_cord_prv], operator='Subtraction', marginsA = MARGINS.zero, marginsB = MARGINS.uniform_1mm_expansion) wall_ptv = ROI.ROIWall(ROIS.wall_ptv.name, ROIS.wall_ptv.type, COLORS.wall, ptv, 1, 0) site.add_oars([ROIS.spinal_cord_prv, wall_ptv]) site.add_targets([ROIS.gtv, ROIS.vb, ptv_gtv, ptv_spinal, ctv, ptv]) else: site.add_oars(DEF.palliative_stereotactic_pelvis_oars) ptv = ROI.ROIExpanded(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, ROIS.gtv, margins = MARGINS.uniform_3mm_expansion) wall_ptv = ROI.ROIWall(ROIS.wall_ptv.name, ROIS.wall_ptv.type, COLORS.wall, ptv, 1, 0) site.add_oars([wall_ptv]) site.add_targets([ROIS.gtv, ptv]) # Not stereotactic: else: # Region: if region == 'head': site.add_oars(DEF.palliative_head_oars) elif region == 'neck': site.add_oars(DEF.palliative_neck_oars) elif region == 'thorax': site.add_oars(DEF.palliative_thorax_oars) elif region == 'thorax_abdomen': site.add_oars(DEF.palliative_thorax_abdomen_oars) elif region == 'abdomen': site.add_oars(DEF.palliative_abdomen_oars) elif region == 'abdomen_pelvis': site.add_oars(DEF.palliative_abdomen_pelvis_oars) elif region == 'pelvis': site.add_oars(DEF.palliative_pelvis_oars) # Choice 3: Number of targets: nr_targets = choices[3] # Choice 4: GTV included? with_gtv = choices[4] # Nr of target volumes: if nr_targets == '1': if with_gtv == 'with': site.add_targets([ROIS.gtv, ROIS.ctv_ext]) else: site.add_targets([ROIS.ctv_underived]) if region == 'other': ROIS.ptv_ext.sourcesA = [ROIS.ctv_underived] site.add_targets([ROIS.ptv_ext_7]) else: ROIS.ptv_ext.sourcesA = [ROIS.ctv_underived] site.add_targets([ROIS.ptv_ext]) # 2 or 3 targets: else: # With GTV: if with_gtv=='with': ctv1 = ROI.ROIAlgebra(ROIS.ctv1.name, ROIS.ctv1.type, ROIS.ctv.color, sourcesA = [ROIS.gtv1], sourcesB = [ROIS.external], operator = 'Intersection', marginsA = MARGINS.uniform_5mm_expansion, marginsB = MARGINS.uniform_5mm_contraction) ctv2 = ROI.ROIAlgebra(ROIS.ctv2.name, ROIS.ctv2.type, ROIS.ctv.color, sourcesA = [ROIS.gtv2], sourcesB = [ROIS.external], operator = 'Intersection', marginsA = MARGINS.uniform_5mm_expansion, marginsB = MARGINS.uniform_5mm_contraction) ptv1 = ROI.ROIAlgebra(ROIS.ptv1.name, ROIS.ptv1.type, ROIS.ptv.color, sourcesA = [ROIS.ctv1], sourcesB = [ROIS.external], operator = 'Intersection', marginsA = MARGINS.uniform_5mm_expansion, marginsB = MARGINS.uniform_5mm_contraction) ptv2 = ROI.ROIAlgebra(ROIS.ptv2.name, ROIS.ptv2.type, ROIS.ptv.color, sourcesA = [ROIS.ctv2], sourcesB = [ROIS.external], operator = 'Intersection', marginsA = MARGINS.uniform_5mm_expansion, marginsB = MARGINS.uniform_5mm_contraction) gtv = ROI.ROIAlgebra(ROIS.gtv.name, ROIS.gtv.type, ROIS.gtv.color, sourcesA=[ROIS.gtv1], sourcesB=[ROIS.gtv2]) ctv = ROI.ROIAlgebra(ROIS.ctv.name, ROIS.ctv.type, ROIS.ctv.color, sourcesA=[ctv1], sourcesB=[ctv2]) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ptv1], sourcesB=[ptv2]) site.add_targets([ROIS.gtv1, ROIS.gtv2, gtv, ctv1, ctv2, ctv, ptv1, ptv2, ptv]) if nr_targets == '3': ctv3 = ROI.ROIAlgebra(ROIS.ctv3.name, ROIS.ctv3.type, ROIS.ctv.color, sourcesA = [ROIS.gtv3], sourcesB = [ROIS.external], operator = 'Intersection', marginsA = MARGINS.uniform_5mm_expansion, marginsB = MARGINS.uniform_5mm_contraction) ptv3 = ROI.ROIAlgebra(ROIS.ptv3.name, ROIS.ptv3.type, ROIS.ptv.color, sourcesA = [ROIS.ctv3], sourcesB = [ROIS.external], operator = 'Intersection', marginsA = MARGINS.uniform_5mm_expansion, marginsB = MARGINS.uniform_5mm_contraction) gtv.sourcesB.extend([ROIS.gtv3]) ctv.sourcesB.extend([ctv3]) ptv.sourcesB.extend([ptv3]) site.add_targets([ROIS.gtv3, ctv3, ptv3]) # Without GTV: else: if region == 'other': ptv1 = ROI.ROIAlgebra(ROIS.ptv1.name, ROIS.ptv1.type, ROIS.ptv.color, sourcesA = [ROIS.ctv1], sourcesB = [ROIS.external], operator = 'Intersection', marginsA = MARGINS.uniform_7mm_expansion, marginsB = MARGINS.uniform_5mm_contraction) ptv2 = ROI.ROIAlgebra(ROIS.ptv2.name, ROIS.ptv2.type, ROIS.ptv.color, sourcesA = [ROIS.ctv2], sourcesB = [ROIS.external], operator = 'Intersection', marginsA = MARGINS.uniform_7mm_expansion, marginsB = MARGINS.uniform_5mm_contraction) else: ptv1 = ROI.ROIAlgebra(ROIS.ptv1.name, ROIS.ptv1.type, ROIS.ptv.color, sourcesA = [ROIS.ctv1], sourcesB = [ROIS.external], operator = 'Intersection', marginsA = MARGINS.uniform_5mm_expansion, marginsB = MARGINS.uniform_5mm_contraction) ptv2 = ROI.ROIAlgebra(ROIS.ptv2.name, ROIS.ptv2.type, ROIS.ptv.color, sourcesA = [ROIS.ctv2], sourcesB = [ROIS.external], operator = 'Intersection', marginsA = MARGINS.uniform_5mm_expansion, marginsB = MARGINS.uniform_5mm_contraction) ctv = ROI.ROIAlgebra(ROIS.ctv.name, ROIS.ctv.type, ROIS.ctv.color, sourcesA=[ROIS.ctv1], sourcesB=[ROIS.ctv2]) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ptv1], sourcesB=[ptv2]) site.add_targets([ROIS.ctv1, ROIS.ctv2, ctv, ptv1, ptv2, ptv]) if nr_targets == '3': if region == 'other': ptv3 = ROI.ROIAlgebra(ROIS.ptv3.name, ROIS.ptv3.type, ROIS.ptv.color, sourcesA = [ROIS.ctv3], sourcesB = [ROIS.external], operator = 'Intersection', marginsA = MARGINS.uniform_5mm_expansion, marginsB = MARGINS.uniform_7mm_contraction) else: ptv3 = ROI.ROIAlgebra(ROIS.ptv3.name, ROIS.ptv3.type, ROIS.ptv.color, sourcesA = [ROIS.ctv3], sourcesB = [ROIS.external], operator = 'Intersection', marginsA = MARGINS.uniform_5mm_expansion, marginsB = MARGINS.uniform_5mm_contraction) ctv.sourcesB.extend([ROIS.ctv3]) ptv.sourcesB.extend([ptv3]) site.add_targets([ROIS.ctv3, ptv3]) # Create all targets and OARs in RayStation: site.create_rois()
def __init__(self, pm, examination, ss, choices, site): # Choice 1: Stereotactic or not? stereotactic = choices[1] # Choice 2: Region region = choices[2] if stereotactic == 'yes': # Stereotactic: if region in ['col thorax', 'col pelvis']: # Targets: ctv = ROI.ROIExpanded(ROIS.ctv.name, ROIS.ctv.type, COLORS.ctv_med, ROIS.gtv, margins=MARGINS.uniform_3mm_expansion) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ctv], sourcesB=[ROIS.vb]) ptv_gtv = ROI.ROIAlgebra(ROIS.ptv_gtv.name, ROIS.ptv_gtv.type, COLORS.ptv_med, sourcesA=[ptv], sourcesB=[ROIS.gtv], operator='Subtraction') ptv_spinal = ROI.ROIAlgebra( ROIS.ptv_spinal.name, ROIS.ptv_spinal.type, COLORS.ptv_med, sourcesA=[ptv], sourcesB=[ROIS.spinal_cord_prv], operator='Subtraction', marginsA=MARGINS.zero, marginsB=MARGINS.uniform_1mm_expansion) site.add_targets( [ROIS.gtv, ROIS.vb, ptv_gtv, ptv_spinal, ctv, ptv]) # OARs: if region == 'col thorax': site.add_oars(DEF.palliative_stereotactic_thorax_oars) elif region == 'col pelvis': site.add_oars( DEF.palliative_stereotactic_spine_pelvis_oars) wall_ptv = ROI.ROIWall(ROIS.wall_ptv.name, ROIS.wall_ptv.type, COLORS.wall, ptv, 1, 0) site.add_oars([ROIS.spinal_cord_prv, wall_ptv]) else: # Non-columna SBRT (assumed pelvis): # Targets: ptv = ROI.ROIExpanded(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, ROIS.gtv, margins=MARGINS.uniform_3mm_expansion) site.add_targets([ROIS.gtv, ptv]) # OARs: wall_ptv = ROI.ROIWall(ROIS.wall_ptv.name, ROIS.wall_ptv.type, COLORS.wall, ptv, 1, 0) site.add_oars(DEF.palliative_stereotactic_pelvis_oars + [wall_ptv]) else: # Non-stereotactic: # Region: if region == 'head': site.add_oars(DEF.palliative_head_oars) elif region == 'neck': site.add_oars(DEF.palliative_neck_oars) elif region == 'thorax': site.add_oars(DEF.palliative_thorax_oars) elif region == 'costa': site.add_oars(DEF.palliative_thorax_abdomen_oars) elif region == 'thorax_abdomen': site.add_oars(DEF.palliative_thorax_abdomen_oars) elif region == 'abdomen': site.add_oars(DEF.palliative_abdomen_oars) elif region == 'abdomen_pelvis': site.add_oars(DEF.palliative_abdomen_pelvis_oars) elif region == 'pelvis': site.add_oars(DEF.palliative_pelvis_oars) # Choice 3: Number of targets: nr_targets = int(choices[3]) # Choice 4: GTV included? with_gtv = choices[4] # Determine PTV margins: if with_gtv == 'with': # Soft tissue target: if region in ['head']: # Head: 3 mm ptv_margin = MARGINS.uniform_3mm_expansion elif region in ['neck']: # Neck: 3 mm (mask) or 5 mm (no mask) # Choice 5: Mask? mask = choices[5] if mask == 'mask': ptv_margin = MARGINS.uniform_3mm_expansion else: ptv_margin = MARGINS.uniform_5mm_expansion elif region in ['thorax_abdomen']: # Near lung (affected by breathing motion): ptv_margin = MARGINS.abdomen_near_lung_soft_tissue_expansion else: # All others: 7 mm ptv_margin = MARGINS.uniform_7mm_expansion else: # Bone target: if region in ['head']: # Head: 3 mm ptv_margin = MARGINS.uniform_3mm_expansion elif region in ['neck']: # Neck: 3 mm (mask) or 5 mm (no mask) # Choice 5: Mask? mask = choices[5] if mask == 'mask': ptv_margin = MARGINS.uniform_3mm_expansion else: ptv_margin = MARGINS.uniform_5mm_expansion elif region in ['costa', 'other']: # Costa/Extremities: 7 mm ptv_margin = MARGINS.uniform_7mm_expansion else: # Other torso: 5 mm ptv_margin = MARGINS.uniform_5mm_expansion # Set up target volumes: if nr_targets == 1: # A single target: if with_gtv == 'with': site.add_targets([ROIS.gtv, ROIS.ctv_ext]) else: site.add_targets([ROIS.ctv_underived]) site.add_targets([ ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ROIS.ctv], sourcesB=[ROIS.external], operator='Intersection', marginsA=ptv_margin, marginsB=MARGINS.uniform_5mm_contraction) ]) else: # Multiple targets (2 or 3): gtvs = [] ctvs = [] ptvs = [] if with_gtv == 'with': # With GTV: for i in range(0, nr_targets): gtvs.append( ROI.ROI('GTV' + str(i + 1), 'Gtv', COLORS.gtv)) ctvs.append( ROI.ROIAlgebra( ROIS.ctv.name + str(i + 1), ROIS.ctv1.type, ROIS.ctv.color, sourcesA=[gtvs[-1]], sourcesB=[ROIS.external], operator='Intersection', marginsA=ptv_margin, marginsB=MARGINS.uniform_5mm_contraction)) ptvs.append( ROI.ROIAlgebra( ROIS.ptv.name + str(i + 1), ROIS.ptv1.type, ROIS.ptv.color, sourcesA=[ctvs[-1]], sourcesB=[ROIS.external], operator='Intersection', marginsA=ptv_margin, marginsB=MARGINS.uniform_5mm_contraction)) # GTV union target volume: gtvs.append( ROI.ROIAlgebra(ROIS.gtv.name, ROIS.gtv.type, ROIS.gtv.color, sourcesA=[gtvs[0]], sourcesB=gtvs[1:])) site.add_targets(gtvs) else: # Without GTV: for i in range(0, nr_targets): ctvs.append( ROI.ROI('CTV' + str(i + 1), 'Ctv', COLORS.ctv)) ptvs.append( ROI.ROIAlgebra( ROIS.ptv.name + str(i + 1), ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ctvs[-1]], sourcesB=[ROIS.external], operator='Intersection', marginsA=ptv_margin, marginsB=MARGINS.uniform_5mm_contraction)) # Union target volumes: ctv = ROI.ROIAlgebra(ROIS.ctv.name, ROIS.ctv.type, ROIS.ctv.color, sourcesA=[ctvs[0]], sourcesB=ctvs[1:]) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ptvs[0]], sourcesB=ptvs[1:]) ctvs.append(ctv) ptvs.append(ptv) site.add_targets(ctvs + ptvs) # Create all targets and OARs in RayStation: site.create_rois()
def __init__(self, pm, examination, ss, choices, site): # Choice 1: Scope (whole brain, part or stereotactic). region = choices[1] # Region: # Whole brain: if region == 'whole': site.add_oars(DEF.brain_whole_oars) ctv = ROI.ROIExpanded(ROIS.ctv.name, ROIS.ctv.type, COLORS.ctv, ROIS.brain) ptv = ROI.ROIExpanded(ROIS.ptv.name, ROIS.ptv.type, COLORS.ptv, ctv, margins=MARGINS.uniform_3mm_expansion) site.add_targets([ctv, ptv]) # Partial Brain: elif region == 'part': ctv = ROI.ROIExpanded(ROIS.ctv.name, ROIS.ctv.type, COLORS.ctv, ROIS.gtv, margins=MARGINS.uniform_20mm_expansion) brain_gtv = ROI.ROIAlgebra(ROIS.brain_gtv.name, ROIS.brain_gtv.type, ROIS.brain.color, sourcesA=[ROIS.brain], sourcesB=[ROIS.gtv], operator='Subtraction') site.add_oars([brain_gtv]) site.add_targets([ROIS.gtv, ctv]) # Common for all diagnoses of partial brain: site.add_oars(DEF.brain_partial_oars) ptv = ROI.ROIExpanded(ROIS.ptv.name, ROIS.ptv.type, COLORS.ptv, ctv, margins=MARGINS.uniform_3mm_expansion) brain_ptv = ROI.ROIAlgebra(ROIS.brain_ptv.name, ROIS.brain_ptv.type, ROIS.other_ptv.color, sourcesA=[ROIS.brain], sourcesB=[ptv], operator='Subtraction') site.add_oars([brain_ptv]) site.add_targets([ptv]) # Stereotactic brain: elif region == 'stereotactic': site.add_oars(DEF.brain_stereotactic_oars) # Choice 2: Nr of targets. nr_targets = choices[2] # One target: if nr_targets == 'one': gtv = ROI.ROI('GTV', 'Gtv', ROIS.gtv.color) ptv = ROI.ROIExpanded(ROIS.ptv.name, ROIS.ptv.type, COLORS.ptv, gtv, margins=MARGINS.uniform_2mm_expansion) wall_ptv = ROI.ROIWall(ROIS.z_ptv_wall.name, ROIS.z_ptv_wall.type, COLORS.wall, ptv, 1, 0) site.add_targets([wall_ptv]) # Multiple targets (2, 3 or 4): elif nr_targets in ['two', 'three', 'four']: gtv = ROI.ROIAlgebra(ROIS.gtv.name, ROIS.gtv.type, ROIS.gtv.color, sourcesA=[ROIS.gtv1], sourcesB=[ROIS.gtv2]) ptv1 = ROI.ROIExpanded(ROIS.ptv1.name, ROIS.ptv1.type, COLORS.ptv, ROIS.gtv1, margins=MARGINS.uniform_2mm_expansion) ptv2 = ROI.ROIExpanded(ROIS.ptv2.name, ROIS.ptv2.type, COLORS.ptv, ROIS.gtv2, margins=MARGINS.uniform_2mm_expansion) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ptv1], sourcesB=[ptv2]) wall_ptv1 = ROI.ROIWall(ROIS.z_ptv1_wall.name, ROIS.z_ptv1_wall.type, COLORS.wall, ptv1, 1, 0) wall_ptv2 = ROI.ROIWall(ROIS.z_ptv2_wall.name, ROIS.z_ptv2_wall.type, COLORS.wall, ptv2, 1, 0) site.add_targets([wall_ptv1, wall_ptv2]) site.add_targets([ROIS.gtv1, ROIS.gtv2, ptv1, ptv2]) # 3 or 4 targets: if nr_targets in ['three', 'four']: ptv3 = ROI.ROIExpanded( ROIS.ptv3.name, ROIS.ptv3.type, COLORS.ptv, ROIS.gtv3, margins=MARGINS.uniform_2mm_expansion) wall_ptv3 = ROI.ROIWall(ROIS.z_ptv3_wall.name, ROIS.z_ptv3_wall.type, COLORS.wall, ptv3, 1, 0) ptv.sourcesB.extend([ptv3]) gtv.sourcesB.extend([ROIS.gtv3]) site.add_targets([ROIS.gtv3, ptv3]) site.add_targets([wall_ptv3]) # 4 targets: if nr_targets in ['four']: ptv4 = ROI.ROIExpanded( ROIS.ptv4.name, ROIS.ptv4.type, COLORS.ptv, ROIS.gtv4, margins=MARGINS.uniform_2mm_expansion) wall_ptv4 = ROI.ROIWall(ROIS.z_ptv4_wall.name, ROIS.z_ptv4_wall.type, COLORS.wall, ptv4, 1, 0) ptv.sourcesB.extend([ptv4]) gtv.sourcesB.extend([ROIS.gtv4]) site.add_targets([ROIS.gtv4, ptv4]) site.add_targets([wall_ptv4]) # Common for stereotactic: brain_ptv = ROI.ROIAlgebra(ROIS.brain_ptv.name, ROIS.brain_ptv.type, ROIS.other_ptv.color, sourcesA=[ROIS.brain], sourcesB=[ptv], operator='Subtraction') brain_gtv = ROI.ROIAlgebra(ROIS.brain_gtv.name, ROIS.brain_gtv.type, ROIS.brain.color, sourcesA=[ROIS.brain], sourcesB=[gtv], operator='Subtraction') site.add_targets([gtv, ptv]) site.add_oars([brain_ptv, brain_gtv]) # Create all targets and OARs in RayStation: site.create_rois()
def __init__(self, pm, examination, ss, choices, site): # Default OARs: site.add_oars(DEF.lung_oars) # Choice 1: Intent (curative or palliative) intent = choices[1] if intent == 'curative': # Curative: # Choice 2: Diagnosis diagnosis = choices[2] if diagnosis == '4dct': # Non small cell lung cancer (with 4DCT) or small cell lung cancer (with 4DCT): # Targets: igtv = ROI.ROIAlgebra(ROIS.igtv.name, ROIS.igtv.type, ROIS.gtv.color, sourcesA=[ROIS.igtv_p], sourcesB=[ROIS.igtv_n]) ictv_p = ROI.ROIExpanded( ROIS.ictv_p.name, ROIS.ictv_p.type, COLORS.ctv_high, source=ROIS.igtv_p, margins=MARGINS.uniform_10mm_expansion) ictv_n = ROI.ROIExpanded(ROIS.ictv_n.name, ROIS.ictv_n.type, COLORS.ctv_high, source=ROIS.igtv_n, margins=MARGINS.uniform_5mm_expansion) ictv = ROI.ROIAlgebra(ROIS.ictv.name, ROIS.ictv.type, ROIS.ctv.color, sourcesA=[ictv_p, ictv_n], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.zero, marginsB=MARGINS.uniform_5mm_contraction) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, COLORS.ptv_high, sourcesA=[ictv], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) site.add_targets([ ROIS.igtv_p, ROIS.igtv_n, igtv, ictv_p, ictv_n, ictv, ptv ]) # OARs / others: lungs_igtv = ROI.ROIAlgebra(ROIS.lungs_igtv.name, ROIS.lungs_igtv.type, COLORS.lungs, sourcesA=[ROIS.lungs], sourcesB=[igtv], operator='Subtraction') water = ROI.ROIAlgebra(ROIS.z_water.name, ROIS.z_water.type, COLORS.other_ptv, sourcesA=[ROIS.lungs, ptv], sourcesB=[igtv], operator='Subtraction', operatorA='Intersection') site.add_oars([lungs_igtv, water]) elif diagnosis == 'sclc': # Small cell lung cancer (without 4DCT): # Targets: ctv = ROI.ROIAlgebra(ROIS.ctv.name, ROIS.ctv.type, ROIS.ctv.color, sourcesA=[ROIS.ctv_p, ROIS.ctv_n], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.zero, marginsB=MARGINS.uniform_5mm_contraction) ptv_p = ROI.ROIAlgebra( ROIS.ptv_p.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ROIS.ctv_p], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.lung_sclc_without_4dct, marginsB=MARGINS.uniform_5mm_contraction) ptv_n = ROI.ROIAlgebra( ROIS.ptv_n.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ROIS.ctv_n], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_10mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ptv_p], sourcesB=[ptv_n]) site.add_targets( [ROIS.ctv_p, ROIS.ctv_n, ctv, ptv_p, ptv_n, ptv]) # OARs / others: water = ROI.ROIAlgebra(ROIS.z_water.name, ROIS.z_water.type, COLORS.other_ptv, sourcesA=[ROIS.lungs, ptv], sourcesB=[ctv], operator='Subtraction', operatorA='Intersection') site.add_oars([water]) elif diagnosis == 'pancoast': # Pancoast tumor (with 4DCT): # Targets: igtv = ROI.ROI(ROIS.igtv.name, ROIS.igtv.type, COLORS.gtv) ictv = ROI.ROIAlgebra(ROIS.ictv.name, ROIS.ictv.type, ROIS.ctv.color, sourcesA=[igtv], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_10mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ictv], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) site.add_targets([igtv, ictv, ptv]) # OARs / others: lungs_igtv = ROI.ROIAlgebra(ROIS.lungs_igtv.name, ROIS.lungs_igtv.type, COLORS.lungs, sourcesA=[ROIS.lungs], sourcesB=[igtv], operator='Subtraction') water = ROI.ROIAlgebra(ROIS.z_water.name, ROIS.z_water.type, COLORS.other_ptv, sourcesA=[ROIS.lungs, ptv], sourcesB=[igtv], operator='Subtraction', operatorA='Intersection') site.add_oars([lungs_igtv, water]) elif diagnosis == 'postop': # Post operative treatment: # Targets: ctv = ROI.ROI(ROIS.ctv.name, ROIS.ctv.type, COLORS.ctv) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ctv], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_10mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) site.add_targets([ctv, ptv]) # OARs / others: water = ROI.ROIAlgebra(ROIS.z_water.name, ROIS.z_water.type, COLORS.other_ptv, sourcesA=[ROIS.lungs, ptv], sourcesB=[ctv], operator='Subtraction', operatorA='Intersection') site.add_oars([water]) # Common structures for all curative cases: heart_ptv = ROI.ROIAlgebra(ROIS.z_heart.name, ROIS.z_heart.type, COLORS.heart, sourcesA=[ROIS.heart], sourcesB=[ptv], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) esophagus_ptv = ROI.ROIAlgebra( ROIS.z_esophagus.name, ROIS.z_esophagus.type, COLORS.esophagus, sourcesA=[ROIS.esophagus], sourcesB=[ptv], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) site.add_oars([heart_ptv, esophagus_ptv]) elif intent == 'palliative': # Palliative: # Choice 2: 4DCT - with or without? with_4dct = choices[2] if with_4dct == 'with': # 4DCT: # Targets: ictv = ROI.ROIAlgebra(ROIS.ictv.name, ROIS.ictv.type, ROIS.ctv.color, sourcesA=[ROIS.igtv], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ictv], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) site.add_targets([ROIS.igtv, ictv, ptv]) # OARs / others: lungs_gtv = ROI.ROIAlgebra(ROIS.lungs_igtv.name, ROIS.lungs_igtv.type, COLORS.lungs, sourcesA=[ROIS.lungs], sourcesB=[ROIS.igtv], operator='Subtraction') water = ROI.ROIAlgebra(ROIS.z_water.name, ROIS.z_water.type, COLORS.other_ptv, sourcesA=[ROIS.lungs, ptv], sourcesB=[ROIS.igtv], operator='Subtraction', operatorA='Intersection') site.add_oars([lungs_gtv, water]) else: # Non-4DCT: # Targets: ctv = ROI.ROIAlgebra(ROIS.ctv.name, ROIS.ctv.type, ROIS.ctv.color, sourcesA=[ROIS.gtv], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ctv], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_10mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) site.add_targets([ROIS.gtv, ctv, ptv]) # OARs / others: lungs_gtv = ROI.ROIAlgebra(ROIS.lungs_gtv.name, ROIS.lungs_gtv.type, COLORS.lungs, sourcesA=[ROIS.lungs], sourcesB=[ROIS.gtv], operator='Subtraction') water = ROI.ROIAlgebra(ROIS.z_water.name, ROIS.z_water.type, COLORS.other_ptv, sourcesA=[ROIS.lungs, ptv], sourcesB=[ROIS.gtv], operator='Subtraction', operatorA='Intersection') site.add_oars([lungs_gtv, water]) # Common for all palliative cases: heart_ptv = ROI.ROIAlgebra(ROIS.z_heart.name, ROIS.z_heart.type, COLORS.heart, sourcesA=[ROIS.heart], sourcesB=[ptv], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) esophagus_ptv = ROI.ROIAlgebra( ROIS.z_esophagus.name, ROIS.z_esophagus.type, COLORS.esophagus, sourcesA=[ROIS.esophagus], sourcesB=[ptv], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) site.add_oars([heart_ptv, esophagus_ptv]) elif intent == 'stereotactic': # Stereotactic treatment: # Slice thickness quality control: DEFQC.test_slice_thickness(examination, 0.2, "Lunge SBRT") # Add a POI for breath hold measurement: PMF.create_poi(pm, examination, 'Pust', 'Marker', 'Magenta') # Choice 2: Side - left or right? side = choices[2] if side == 'right': site.add_oars([ROIS.rib_x_r, ROIS.rib_y_r, ROIS.ribs_r]) elif side == 'left': site.add_oars([ROIS.rib_x_l, ROIS.rib_y_l, ROIS.ribs_l]) # Choice 3: Number of target volumes? nr_targets = int(choices[3]) if nr_targets == 1: # Single target: site.add_targets( [ROIS.igtv, ROIS.ictv, ROIS.iptv, ROIS.wall_ptv]) site.add_oars([ROIS.lungs_igtv]) else: # Multiple targets: igtvs = [] ictvs = [] ptvs = [] walls = [] for i in range(0, nr_targets): # Targets: igtvs.append( ROI.ROI('IGTV' + str(i + 1), 'Gtv', ROIS.igtv.color)) ictvs.append( ROI.ROIExpanded(ROIS.ictv.name + str(i + 1), ROIS.ictv.type, COLORS.ctv, igtvs[-1], margins=MARGINS.uniform_5mm_expansion)) ptvs.append( ROI.ROIExpanded(ROIS.ptv.name + str(i + 1), ROIS.ptv.type, COLORS.ptv, ictvs[-1], margins=MARGINS.uniform_5mm_expansion)) # OARs / others: walls.append( ROI.ROIWall("zPTV" + str(i + 1) + "_Wall", ROIS.z_ptv_wall.type, COLORS.wall, ptvs[-1], 1, 0)) # Union target volumes: igtv = ROI.ROIAlgebra(ROIS.igtv.name, ROIS.igtv.type, ROIS.igtv.color, sourcesA=[igtvs[0]], sourcesB=igtvs[1:]) ictv = ROI.ROIAlgebra(ROIS.ictv.name, ROIS.ictv.type, ROIS.ictv.color, sourcesA=[ictvs[0]], sourcesB=ictvs[1:]) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ptvs[0]], sourcesB=ptvs[1:]) igtvs.append(igtv) ictvs.append(ictv) ptvs.append(ptv) # Targets: site.add_targets(igtvs + ictvs + ptvs) # OARs / others: lungs_igtv = ROI.ROIAlgebra(ROIS.lungs_igtv.name, 'Organ', COLORS.lungs, sourcesA=[ROIS.lungs], sourcesB=[igtv], operator='Subtraction') site.add_oars([lungs_igtv] + walls) # Common for single or multiple targets: site.add_oars(DEF.lung_stereotactic_oars) # Create all targets and OARs in RayStation: site.create_rois()
def __init__(self, pm, examination, ss, choices, site): # Choice 1: Region - prostate or bed? region = choices[1] # Prostate: if region == 'prostate': # Choice 2: Fractionation - normo or hypo? frac = choices[2] if frac == 'palliative': site.add_oars(DEF.prostate_palliative_oars) else: site.add_oars(DEF.prostate_oars) # Conventionally fractionated prostate with vesicles (2.2Gy x 35): if frac == 'normo': # Choice 3: Nodes - included or not? nodes = choices[3] ptv_77 = ROI.ROIExpanded(ROIS.ptv_77.name, ROIS.ptv_77.type, COLORS.ptv_high, source = ROIS.prostate, margins = MARGINS.prostate_seed_expansion) ctv_77 = ROI.ROIExpanded(ROIS.ctv_77.name, ROIS.ctv_77.type, COLORS.ctv_high, source = ROIS.prostate) bladder_ptv = ROI.ROIAlgebra(ROIS.z_bladder.name, ROIS.z_bladder.type, COLORS.bladder, sourcesA = [ROIS.bladder], sourcesB = [ptv_77], operator='Subtraction', marginsB = MARGINS.uniform_3mm_expansion) rectum_ptv = ROI.ROIAlgebra(ROIS.z_rectum.name, ROIS.z_rectum.type, COLORS.rectum, sourcesA = [ROIS.rectum], sourcesB = [ptv_77], operator='Subtraction', marginsB = MARGINS.uniform_2mm_expansion) wall_ptv_77 = ROI.ROIWall(ROIS.z_ptv_77_wall.name, ROIS.z_ptv_77_wall.type, COLORS.wall, ptv_77, 0.5, 0) # With nodes: if nodes == 'without': ctv_70 = ROI.ROIAlgebra(ROIS.ctv_70_sib.name, ROIS.ctv_70.type, COLORS.ctv_med, sourcesA = [ROIS.vesicles], sourcesB = [ptv_77], operator = 'Subtraction', marginsA = MARGINS.zero, marginsB = MARGINS.zero) ptv_70 = ROI.ROIAlgebra(ROIS.ptv_70_sib.name, ROIS.ptv_70.type, COLORS.ptv_med, sourcesA = [ROIS.vesicles], sourcesB = [ptv_77], operator = 'Subtraction', marginsA = MARGINS.uniform_10mm_expansion, marginsB = MARGINS.zero) ptv_70_77 = ROI.ROIAlgebra(ROIS.ptv_70_77.name, ROIS.ptv_70_77.type, COLORS.ptv_low, sourcesA = [ROIS.prostate], sourcesB = [ROIS.vesicles], marginsA = MARGINS.prostate_seed_expansion, marginsB = MARGINS.uniform_10mm_expansion) bladder_ptv.sourcesB.extend([ptv_70]) rectum_ptv.sourcesB.extend([ptv_70]) site.add_targets([ptv_70_77]) elif nodes == 'with_node': ctv_n = ROI.ROIExpanded(ROIS.ctv_n.name, ROIS.ctv_n.type, COLORS.pelvic_nodes, source = ROIS.gtv_n, margins = MARGINS.uniform_5mm_expansion) ptv_n = ROI.ROIExpanded(ROIS.ptv_n.name, ROIS.ptv_n.type, ROIS.ptv_n.color, source = ctv_n, margins = MARGINS.prostate_lymph_nodes_seed_expansion) ctv_70 = ROI.ROIAlgebra(ROIS.ctv_70_sib.name, ROIS.ctv_70.type, COLORS.ctv_med, sourcesA = [ROIS.vesicles, ctv_n], sourcesB = [ptv_77], operator = 'Subtraction', marginsA = MARGINS.zero, marginsB = MARGINS.zero) ptv_semves = ROI.ROIAlgebra(ROIS.ptv_semves.name, ROIS.ptv_semves.type, COLORS.ptv_med, sourcesA = [ROIS.vesicles], sourcesB = [ptv_77], operator = 'Subtraction', marginsA = MARGINS.uniform_10mm_expansion, marginsB = MARGINS.zero) ptv_70 = ROI.ROIAlgebra(ROIS.ptv_70_sib.name, ROIS.ptv_70_sib.type, ROIS.ptv_70_sib.color, sourcesA = [ptv_semves, ptv_n], sourcesB = [ptv_77], operator = 'Subtraction', marginsA = MARGINS.zero, marginsB = MARGINS.zero) ptv_70_77 = ROI.ROIAlgebra(ROIS.ptv_70_77.name, ROIS.ptv_70_77.type, COLORS.ptv_low, sourcesA = [ptv_70], sourcesB = [ptv_77], marginsA = MARGINS.zero, marginsB = MARGINS.zero) ptv_56 = ROI.ROIAlgebra(ROIS.ptv_56.name, ROIS.ptv_56.type, COLORS.ptv_low, sourcesA = [ROIS.pelvic_nodes], sourcesB = [ptv_77, ptv_70], operator = 'Subtraction', marginsA = MARGINS.prostate_lymph_nodes_seed_expansion, marginsB = MARGINS.zero) ctv_56 = ROI.ROIAlgebra(ROIS.ctv_56.name, ROIS.ctv_56.type, COLORS.ctv_low, sourcesA = [ROIS.pelvic_nodes], sourcesB = [ptv_77, ptv_70], operator = 'Subtraction', marginsA = MARGINS.zero, marginsB = MARGINS.zero) ptv_56_70_77 = ROI.ROIAlgebra(ROIS.ptv_56_70_77.name, ROIS.ptv_56_70_77.type, COLORS.ptv_low, sourcesA = [ptv_56, ptv_70], sourcesB = [ptv_77], marginsA = MARGINS.zero, marginsB = MARGINS.zero) bladder_ptv.sourcesB.extend([ptv_70, ptv_56]) rectum_ptv.sourcesB.extend([ptv_70, ptv_56]) bowel_ptv = ROI.ROIAlgebra(ROIS.z_spc_bowel.name, ROIS.z_spc_bowel.type, COLORS.bowel_space, sourcesA = [ROIS.bowel_space], sourcesB = [ptv_77, ptv_70, ptv_56], operator='Subtraction', marginsB = MARGINS.uniform_3mm_expansion) wall_ptv_70_77 = ROI.ROIWall(ROIS.z_ptv_70_77_wall.name, ROIS.z_ptv_70_77_wall.type, COLORS.wall, ptv_70_77, 1, 0) site.add_oars([bowel_ptv, wall_ptv_70_77]) site.add_targets([ROIS.gtv_n, ctv_n, ptv_n, ptv_semves, ptv_56, ctv_56, ROIS.pelvic_nodes, ptv_70_77, ptv_56_70_77]) elif nodes == 'with': ctv_70 = ROI.ROIAlgebra(ROIS.ctv_70_sib.name, ROIS.ctv_70.type, COLORS.ctv_med, sourcesA = [ROIS.vesicles], sourcesB = [ptv_77], operator = 'Subtraction', marginsA = MARGINS.zero, marginsB = MARGINS.zero) ptv_70 = ROI.ROIAlgebra(ROIS.ptv_70_sib.name, ROIS.ptv_70.type, COLORS.ptv_med, sourcesA = [ROIS.vesicles], sourcesB = [ptv_77], operator = 'Subtraction', marginsA = MARGINS.uniform_10mm_expansion, marginsB = MARGINS.zero) ptv_70_77 = ROI.ROIAlgebra(ROIS.ptv_70_77.name, ROIS.ptv_70_77.type, COLORS.ptv_low, sourcesA = [ROIS.prostate], sourcesB = [ROIS.vesicles], marginsA = MARGINS.prostate_seed_expansion, marginsB = MARGINS.uniform_10mm_expansion) ptv_56 = ROI.ROIAlgebra(ROIS.ptv_56.name, ROIS.ptv_56.type, COLORS.ptv_low, sourcesA = [ROIS.pelvic_nodes], sourcesB = [ptv_77, ptv_70], operator = 'Subtraction', marginsA = MARGINS.prostate_lymph_nodes_seed_expansion, marginsB = MARGINS.zero) ctv_56 = ROI.ROIAlgebra(ROIS.ctv_56.name, ROIS.ctv_56.type, COLORS.ctv_low, sourcesA = [ROIS.pelvic_nodes], sourcesB = [ptv_77, ptv_70], operator = 'Subtraction', marginsA = MARGINS.zero, marginsB = MARGINS.zero) ptv_56_70_77 = ROI.ROIAlgebra(ROIS.ptv_56_70_77.name, ROIS.ptv_56_70_77.type, COLORS.ptv_low, sourcesA = [ptv_56, ptv_70], sourcesB = [ptv_77], marginsA = MARGINS.zero, marginsB = MARGINS.zero) bladder_ptv.sourcesB.extend([ptv_70, ptv_56]) rectum_ptv.sourcesB.extend([ptv_70, ptv_56]) bowel_ptv = ROI.ROIAlgebra(ROIS.z_spc_bowel.name, ROIS.z_spc_bowel.type, COLORS.bowel_space, sourcesA = [ROIS.bowel_space], sourcesB = [ptv_77, ptv_70, ptv_56], operator='Subtraction', marginsB = MARGINS.uniform_3mm_expansion) wall_ptv_70_77 = ROI.ROIWall(ROIS.z_ptv_70_77_wall.name, ROIS.z_ptv_70_77_wall.type, COLORS.wall, ptv_70_77, 1, 0) site.add_oars([bowel_ptv, wall_ptv_70_77]) site.add_targets([ptv_56, ctv_56, ROIS.pelvic_nodes, ptv_70_77, ptv_56_70_77]) # Common for conventional fractionation: site.add_oars([bladder_ptv, rectum_ptv, wall_ptv_77]) site.add_targets([ctv_77, ctv_70, ptv_77, ptv_70, ROIS.prostate, ROIS.vesicles]) # Hypofractionated prostate with vesicles (3 Gy x 20): elif frac == 'hypo_60': ptv_57_60 = ROI.ROIAlgebra(ROIS.ptv_57_60.name, ROIS.ptv_57_60.type, COLORS.ptv_low, sourcesA = [ROIS.prostate], sourcesB = [ROIS.vesicles], marginsA = MARGINS.prostate_seed_expansion, marginsB = MARGINS.uniform_10mm_expansion) ptv_60 = ROI.ROIExpanded(ROIS.ptv_60.name, ROIS.ptv_60.type, COLORS.ptv_high, source = ROIS.prostate, margins = MARGINS.prostate_seed_expansion) ptv_57 = ROI.ROIAlgebra(ROIS.ptv_57.name, ROIS.ptv_57.type, COLORS.ptv_med, sourcesA = [ptv_57_60], sourcesB = [ptv_60], operator = 'Subtraction', marginsA = MARGINS.zero, marginsB = MARGINS.zero) ctv_57_60 = ROI.ROIAlgebra(ROIS.ctv_57_60.name, ROIS.ctv_57_60.type, COLORS.ctv_low, sourcesA = [ROIS.prostate], sourcesB = [ROIS.vesicles], marginsA = MARGINS.zero, marginsB = MARGINS.zero) ctv_60 = ROI.ROIExpanded(ROIS.ctv_60.name, ROIS.ctv_60.type, COLORS.ctv_high, source = ROIS.prostate) ctv_57 = ROI.ROIAlgebra(ROIS.ctv_57.name, ROIS.ctv_57.type, COLORS.ctv_med, sourcesA = [ctv_57_60], sourcesB = [ptv_60], operator = 'Subtraction', marginsA = MARGINS.zero, marginsB = MARGINS.zero) bladder_ptv = ROI.ROIAlgebra(ROIS.z_bladder.name, ROIS.z_bladder.type, COLORS.bladder, sourcesA = [ROIS.bladder], sourcesB = [ptv_60, ptv_57], operator='Subtraction', marginsB = MARGINS.uniform_3mm_expansion) rectum_ptv = ROI.ROIAlgebra(ROIS.z_rectum.name, ROIS.z_rectum.type, COLORS.rectum, sourcesA = [ROIS.rectum], sourcesB = [ptv_60, ptv_57], operator='Subtraction', marginsB = MARGINS.uniform_2mm_expansion) wall_ptv_60 = ROI.ROIWall(ROIS.z_ptv_60_wall.name, ROIS.z_ptv_60_wall.type, COLORS.wall, ptv_60, 0.5, 0) wall_ptv_57_60 = ROI.ROIWall(ROIS.z_ptv_57_60_wall.name, ROIS.z_ptv_57_60_wall.type, COLORS.wall, ptv_57_60, 1, 0) site.add_oars([bladder_ptv, rectum_ptv, wall_ptv_60, wall_ptv_57_60]) site.add_targets([ptv_57_60, ptv_60, ptv_57, ctv_60, ctv_57, ctv_57_60, ROIS.prostate, ROIS.vesicles]) elif frac in ['hypo_55','palliative']: ctv = ROI.ROIAlgebra(ROIS.ctv.name, ROIS.ctv.type, COLORS.ctv_low, sourcesA = [ROIS.prostate], sourcesB = [ROIS.vesicles], marginsA = MARGINS.zero, marginsB = MARGINS.zero) if frac == 'hypo_55': ptv = ROI.ROIExpanded(ROIS.ptv.name, ROIS.ptv.type, COLORS.ptv_high, source = ctv, margins = MARGINS.prostate_seed_expansion) elif frac == 'palliative': ptv = ROI.ROIExpanded(ROIS.ptv.name, ROIS.ptv.type, COLORS.ptv_high, source = ctv, margins = MARGINS.prostate_bone_match_expansion) bladder_ptv = ROI.ROIAlgebra(ROIS.z_bladder.name, ROIS.z_bladder.type, COLORS.bladder, sourcesA = [ROIS.bladder], sourcesB = [ptv], operator='Subtraction', marginsB = MARGINS.uniform_3mm_expansion) rectum_ptv = ROI.ROIAlgebra(ROIS.z_rectum.name, ROIS.z_rectum.type, COLORS.rectum, sourcesA = [ROIS.rectum], sourcesB = [ptv], operator='Subtraction', marginsB = MARGINS.uniform_2mm_expansion) wall_ptv_55 = ROI.ROIWall(ROIS.z_ptv_wall.name, ROIS.z_ptv_wall.type, COLORS.wall, ptv, 1, 0) site.add_oars([bladder_ptv, rectum_ptv, wall_ptv_55]) site.add_targets([ptv, ctv, ROIS.prostate, ROIS.vesicles]) # Prostate bed: else: # Choice 2: Nodes - included or not? frac = choices[2] site.add_oars(DEF.prostate_bed_oars) # With nodes: if frac == 'normo': nodes = choices[3] if nodes == 'without': ctv_70 = ROI.ROIExpanded(ROIS.ctv_70.name, ROIS.ctv_70.type, COLORS.ctv_high, source = ROIS.ctv_sb) ptv_70 = ROI.ROIExpanded(ROIS.ptv_70.name, ROIS.ptv_70.type, COLORS.ptv, source = ctv_70, margins = MARGINS.prostate_bone_match_expansion) bladder_ptv = ROI.ROIAlgebra(ROIS.z_bladder.name, ROIS.z_bladder.type, COLORS.bladder, sourcesA = [ROIS.bladder], sourcesB = [ptv_70], operator='Subtraction', marginsB = MARGINS.uniform_3mm_expansion) rectum_ptv = ROI.ROIAlgebra(ROIS.z_rectum.name, ROIS.z_rectum.type, COLORS.rectum, sourcesA = [ROIS.rectum], sourcesB = [ptv_70], operator='Subtraction', marginsB = MARGINS.uniform_2mm_expansion) else: if nodes == 'with': ctv_70 = ROI.ROIExpanded(ROIS.ctv_70.name, ROIS.ctv_70.type, COLORS.ctv_high, source = ROIS.ctv_sb) ptv_70 = ROI.ROIExpanded(ROIS.ptv_70.name, ROIS.ptv_70.type, COLORS.ptv, source = ctv_70, margins = MARGINS.prostate_bone_match_expansion) else: ctv_n = ROI.ROIExpanded(ROIS.ctv_n.name, ROIS.ctv_n.type, COLORS.pelvic_nodes, source = ROIS.gtv_n, margins = MARGINS.uniform_5mm_expansion) ptv_n = ROI.ROIExpanded(ROIS.ptv_n.name, ROIS.ptv_n.type, ROIS.ptv_n.color, source = ctv_n, margins = MARGINS.uniform_5mm_expansion) ptv_sb = ROI.ROIExpanded(ROIS.ptv_sb.name, ROIS.ptv_sb.type, ROIS.ptv_sb.color, source = ROIS.ctv_sb, margins = MARGINS.prostate_bone_match_expansion) ctv_70 = ROI.ROIAlgebra(ROIS.ctv_70.name, ROIS.ctv_70.type, COLORS.ctv_med, sourcesA = [ROIS.ctv_sb], sourcesB = [ctv_n], operator = 'Union') ptv_70 = ROI.ROIAlgebra(ROIS.ptv_70.name, ROIS.ptv_70.type, COLORS.ptv, sourcesA = [ptv_sb], sourcesB = [ptv_n], operator = 'Union', marginsA = MARGINS.zero , marginsB = MARGINS.zero) site.add_targets([ROIS.gtv_n, ctv_n, ptv_n, ptv_sb]) ctv_56 = ROI.ROIAlgebra(ROIS.ctv_56.name, ROIS.ctv_56.type, COLORS.ctv_low, sourcesA = [ROIS.pelvic_nodes], sourcesB = [ptv_70], operator = 'Subtraction', marginsA = MARGINS.zero, marginsB = MARGINS.zero) ptv_56 = ROI.ROIAlgebra(ROIS.ptv_56.name, ROIS.ptv_56.type, COLORS.ptv_low, sourcesA = [ROIS.pelvic_nodes], sourcesB = [ptv_70], operator = 'Subtraction', marginsA = MARGINS.uniform_5mm_expansion, marginsB = MARGINS.zero) ptv_56_70 = ROI.ROIAlgebra(ROIS.ptv_56_70.name, ROIS.ptv_56_70.type, COLORS.ptv_low, sourcesA = [ptv_56], sourcesB = [ptv_70], marginsA = MARGINS.zero, marginsB = MARGINS.zero) bladder_ptv = ROI.ROIAlgebra(ROIS.z_bladder.name, ROIS.z_bladder.type, COLORS.bladder, sourcesA = [ROIS.bladder], sourcesB = [ptv_70, ptv_56], operator='Subtraction', marginsB = MARGINS.uniform_3mm_expansion) rectum_ptv = ROI.ROIAlgebra(ROIS.z_rectum.name, ROIS.z_rectum.type, COLORS.rectum, sourcesA = [ROIS.rectum], sourcesB = [ptv_70, ptv_56], operator='Subtraction', marginsB = MARGINS.uniform_2mm_expansion) bowel_ptv = ROI.ROIAlgebra(ROIS.z_spc_bowel.name, ROIS.z_spc_bowel.type, COLORS.bowel_space, sourcesA = [ROIS.bowel_space], sourcesB = [ptv_70, ptv_56], operator='Subtraction', marginsB = MARGINS.uniform_3mm_expansion) wall_ptv_70 = ROI.ROIWall(ROIS.z_ptv_70_wall.name, ROIS.z_ptv_70_wall.type, COLORS.wall, ptv_70, 1, 0) wall_ptv_56_temp = ROI.ROIWall(ROIS.z_ptv_56_temp.name, ROIS.z_ptv_56_temp.type, COLORS.wall, ptv_56, 1, 0) wall_ptv_56 = ROI.ROIAlgebra(ROIS.z_ptv_56_wall.name, ROIS.z_ptv_56_wall.type, COLORS.wall, sourcesA = [wall_ptv_56_temp], sourcesB = [ptv_70, wall_ptv_70], operator='Subtraction', marginsB = MARGINS.zero) site.add_oars([bowel_ptv, ROIS.bowel_space, wall_ptv_70, wall_ptv_56_temp, wall_ptv_56]) site.add_targets([ctv_56, ptv_56, ROIS.pelvic_nodes, ptv_56_70]) # Common for bed (with or without nodes): site.add_oars([bladder_ptv, rectum_ptv]) site.add_targets([ctv_70, ptv_70, ROIS.ctv_sb]) else: ptv = ROI.ROIExpanded(ROIS.ptv_sb.name, ROIS.ptv_sb.type, COLORS.ptv_high, source = ROIS.ctv_sb, margins = MARGINS.prostate_bone_match_expansion) bladder_ptv = ROI.ROIAlgebra(ROIS.z_bladder.name, ROIS.z_bladder.type, COLORS.bladder, sourcesA = [ROIS.bladder], sourcesB = [ptv], operator='Subtraction', marginsB = MARGINS.uniform_3mm_expansion) rectum_ptv = ROI.ROIAlgebra(ROIS.z_rectum.name, ROIS.z_rectum.type, COLORS.rectum, sourcesA = [ROIS.rectum], sourcesB = [ptv], operator='Subtraction', marginsB = MARGINS.uniform_2mm_expansion) wall_ptv = ROI.ROIWall(ROIS.z_ptv_wall.name, ROIS.z_ptv_wall.type, COLORS.wall, ptv, 1, 0) site.add_oars([bladder_ptv, rectum_ptv, wall_ptv]) site.add_targets([ptv, ROIS.ctv_sb]) # Create all targets and OARs in RayStation: site.create_rois()
def __init__(self, pm, examination, ss, choices, site): # Choice 1: Fractionation - normo or hypofractionated? frac = choices[1] site.add_oars(DEF.rectum_oars) # Conventionally fractionated (2 Gy x 25): if frac == 'normo': # Choice 2: Groin target volume - included or not? groin = choices[2] # Groin targets included: if groin == 'with': gtv = ROI.ROIAlgebra( ROIS.gtv.name, ROIS.gtv.type, ROIS.gtv.color, sourcesA=[ROIS.gtv_p], sourcesB=[ROIS.gtv_n1, ROIS.gtv_groin_l, ROIS.gtv_groin_r]) site.add_targets([ ROIS.gtv_p, ROIS.gtv_n1, ROIS.gtv_groin_l, ROIS.gtv_groin_r, gtv ]) # Without groin targets: else: gtv = ROI.ROIAlgebra(ROIS.gtv.name, ROIS.gtv.type, ROIS.gtv.color, sourcesA=[ROIS.gtv_p], sourcesB=[ROIS.gtv_n1]) site.add_targets([ROIS.gtv_p, ROIS.gtv_n1, gtv]) # Common for groin included or not: ctv_50 = ROI.ROIExpanded(ROIS.ctv_50.name, ROIS.ctv_50.type, COLORS.ctv_high, source=gtv, margins=MARGINS.uniform_10mm_expansion) ptv_50 = ROI.ROIExpanded(ROIS.ptv_50.name, ROIS.ptv_50.type, COLORS.ptv_high, source=ctv_50, margins=MARGINS.rectum_ptv_50_expansion) if groin == 'with': ctv_47 = ROI.ROIAlgebra( ROIS.ctv_47.name, ROIS.ctv_47.type, COLORS.ctv_low, sourcesA=[ROIS.ctv_e, ROIS.ctv_groin_l, ROIS.ctv_groin_r], sourcesB=[ptv_50], operator='Subtraction', marginsA=MARGINS.zero, marginsB=MARGINS.zero) ptv_47_tot = ROI.ROIAlgebra( ROIS.ptv_47_tot.name, ROIS.ptv_47.type, COLORS.ptv_med, sourcesA=[ROIS.ctv_e], sourcesB=[ROIS.ctv_groin_l, ROIS.ctv_groin_r], operator='Union', marginsA=MARGINS.rectum_ctv_primary_risk_expansion, marginsB=MARGINS.uniform_5mm_expansion) ptv_47 = ROI.ROIAlgebra(ROIS.ptv_47.name, ROIS.ptv_47.type, COLORS.ptv_med, sourcesA=[ptv_47_tot], sourcesB=[ptv_50], operator='Subtraction', marginsA=MARGINS.zero, marginsB=MARGINS.zero) site.add_targets([ ctv_47, ptv_47_tot, ptv_47, ROIS.ctv_groin_l, ROIS.ctv_groin_r, ctv_47, ptv_47_tot, ptv_47 ]) else: ctv_47 = ROI.ROIAlgebra(ROIS.ctv_47.name, ROIS.ctv_47.type, COLORS.ctv_low, sourcesA=[ROIS.ctv_e], sourcesB=[ptv_50], operator='Subtraction', marginsA=MARGINS.zero, marginsB=MARGINS.zero) ptv_47 = ROI.ROIAlgebra( ROIS.ptv_47.name, ROIS.ptv_47.type, COLORS.ptv_med, sourcesA=[ctv_47], sourcesB=[ptv_50], operator='Subtraction', marginsA=MARGINS.rectum_ctv_primary_risk_expansion, marginsB=MARGINS.zero) site.add_targets([ctv_47, ptv_47]) ctv_47_50 = ROI.ROIAlgebra(ROIS.ctv_47_50.name, ROIS.ctv_47_50.type, COLORS.ctv_alt, sourcesA=[ctv_47], sourcesB=[ctv_50], operator='Union', marginsA=MARGINS.zero, marginsB=MARGINS.zero) ptv_47_50 = ROI.ROIAlgebra(ROIS.ptv_47_50.name, ROIS.ptv_47_50.type, COLORS.ptv_low, sourcesA=[ptv_47], sourcesB=[ptv_50], operator='Union', marginsA=MARGINS.zero, marginsB=MARGINS.zero) bladder_ptv = ROI.ROIAlgebra( ROIS.z_bladder.name, ROIS.z_bladder.type, COLORS.bladder, sourcesA=[ROIS.bladder], sourcesB=[ptv_47_50], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) bowel_ptv = ROI.ROIAlgebra(ROIS.z_spc_bowel.name, ROIS.z_spc_bowel.type, COLORS.bowel_space, sourcesA=[ROIS.bowel_space], sourcesB=[ptv_47_50], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) wall_ptv_50 = ROI.ROIWall(ROIS.z_ptv_50_wall.name, ROIS.z_ptv_50_wall.type, COLORS.wall, ptv_50, 0.5, 0) site.add_oars([bladder_ptv, bowel_ptv, wall_ptv_50]) site.add_targets( [ROIS.ctv_e, ctv_50, ptv_50, ctv_47_50, ptv_47_50]) # Hypofractionated treatment (5 Gy x 5): else: ctv_p = ROI.ROIExpanded(ROIS.ctv_p.name, ROIS.ctv_p.type, COLORS.ctv_high, source=ROIS.gtv_p, margins=MARGINS.uniform_10mm_expansion) ctv = ROI.ROIAlgebra(ROIS.ctv.name, ROIS.ctv.type, COLORS.ctv_low, sourcesA=[ROIS.ctv_e], sourcesB=[ctv_p]) ptv = ROI.ROIAlgebra( ROIS.ptv.name, ROIS.ptv.type, COLORS.ptv_med, sourcesA=[ctv_p], sourcesB=[ROIS.ctv_e], marginsA=MARGINS.rectum_ptv_50_expansion, marginsB=MARGINS.rectum_ctv_primary_risk_expansion) bladder_ptv = ROI.ROIAlgebra( ROIS.z_bladder.name, ROIS.z_bladder.type, COLORS.bladder, sourcesA=[ROIS.bladder], sourcesB=[ptv], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) bowel_ptv = ROI.ROIAlgebra(ROIS.z_spc_bowel.name, ROIS.z_spc_bowel.type, COLORS.bowel_space, sourcesA=[ROIS.bowel_space], sourcesB=[ptv], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) site.add_oars([bladder_ptv, bowel_ptv]) site.add_targets([ROIS.gtv_p, ctv_p, ROIS.ctv_e, ctv, ptv]) # Create all targets and OARs in RayStation: site.create_rois()
def __init__(self, pm, examination, ss, choices, site): site.add_oars(DEF.lung_oars) # Choice 1: Intent (curative or palliative) intent = choices[1] # Curative: if intent == 'curative': # Choice 2: Diagnosis diagnosis = choices[2] # Non small cell lung cancer (with 4DCT) or small cell lung cancer (with 4DCT): if diagnosis == '4dct': igtv = ROI.ROIAlgebra(ROIS.igtv.name, ROIS.igtv.type, ROIS.gtv.color, sourcesA=[ROIS.igtv_p], sourcesB=[ROIS.igtv_n]) ictv_p = ROI.ROIExpanded( ROIS.ictv_p.name, ROIS.ictv_p.type, COLORS.ctv_high, source=ROIS.igtv_p, margins=MARGINS.uniform_10mm_expansion) ictv_n = ROI.ROIExpanded(ROIS.ictv_n.name, ROIS.ictv_n.type, COLORS.ctv_high, source=ROIS.igtv_n, margins=MARGINS.uniform_5mm_expansion) ictv = ROI.ROIAlgebra(ROIS.ictv.name, ROIS.ictv.type, ROIS.ctv.color, sourcesA=[ictv_p, ictv_n], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.zero, marginsB=MARGINS.uniform_5mm_contraction) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, COLORS.ptv_high, sourcesA=[ictv], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) lungs_igtv = ROI.ROIAlgebra(ROIS.lungs_igtv.name, ROIS.lungs_igtv.type, COLORS.lungs, sourcesA=[ROIS.lungs], sourcesB=[igtv], operator='Subtraction') water = ROI.ROIAlgebra(ROIS.z_water.name, ROIS.z_water.type, COLORS.other_ptv, sourcesA=[ROIS.lungs, ptv], sourcesB=[igtv], operator='Subtraction', operatorA='Intersection') site.add_targets([ ROIS.igtv_p, ROIS.igtv_n, igtv, ictv_p, ictv_n, ictv, ptv ]) site.add_oars([lungs_igtv, water]) # Small cell lung cancer (without 4DCT): elif diagnosis == 'sclc': ctv = ROI.ROIAlgebra(ROIS.ctv.name, ROIS.ctv.type, ROIS.ctv.color, sourcesA=[ROIS.ctv_p, ROIS.ctv_n], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.zero, marginsB=MARGINS.uniform_5mm_contraction) ptv_p = ROI.ROIAlgebra( ROIS.ptv_p.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ROIS.ctv_p], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.lung_sclc_without_4dct, marginsB=MARGINS.uniform_5mm_contraction) ptv_n = ROI.ROIAlgebra( ROIS.ptv_n.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ROIS.ctv_n], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_10mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ptv_p], sourcesB=[ptv_n]) water = ROI.ROIAlgebra(ROIS.z_water.name, ROIS.z_water.type, COLORS.other_ptv, sourcesA=[ROIS.lungs, ptv], sourcesB=[ctv], operator='Subtraction', operatorA='Intersection') site.add_oars([water]) site.add_targets( [ROIS.ctv_p, ROIS.ctv_n, ctv, ptv_p, ptv_n, ptv]) # Pancoast tumor (with 4DCT): elif diagnosis == 'pancoast': igtv = ROI.ROI(ROIS.igtv.name, ROIS.igtv.type, COLORS.gtv) ictv = ROI.ROIAlgebra(ROIS.ictv.name, ROIS.ictv.type, ROIS.ctv.color, sourcesA=[igtv], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_10mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ictv], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) lungs_igtv = ROI.ROIAlgebra(ROIS.lungs_igtv.name, ROIS.lungs_igtv.type, COLORS.lungs, sourcesA=[ROIS.lungs], sourcesB=[igtv], operator='Subtraction') water = ROI.ROIAlgebra(ROIS.z_water.name, ROIS.z_water.type, COLORS.other_ptv, sourcesA=[ROIS.lungs, ptv], sourcesB=[igtv], operator='Subtraction', operatorA='Intersection') site.add_oars([lungs_igtv, water]) site.add_targets([igtv, ictv, ptv]) # Post operative treatment: elif diagnosis == 'postop': ctv = ROI.ROI(ROIS.ctv.name, ROIS.ctv.type, COLORS.ctv) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ctv], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_10mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) water = ROI.ROIAlgebra(ROIS.z_water.name, ROIS.z_water.type, COLORS.other_ptv, sourcesA=[ROIS.lungs, ptv], sourcesB=[ctv], operator='Subtraction', operatorA='Intersection') site.add_oars([water]) site.add_targets([ctv, ptv]) # Common for all curative cases: heart_ptv = ROI.ROIAlgebra(ROIS.z_heart.name, ROIS.z_heart.type, COLORS.heart, sourcesA=[ROIS.heart], sourcesB=[ptv], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) esophagus_ptv = ROI.ROIAlgebra( ROIS.z_esophagus.name, ROIS.z_esophagus.type, COLORS.esophagus, sourcesA=[ROIS.esophagus], sourcesB=[ptv], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) site.add_oars([heart_ptv, esophagus_ptv]) # Palliative: elif intent == 'palliative': # Choice 2: 4DCT - with or without? # With 4DCT: if choices[2]: ictv = ROI.ROIAlgebra(ROIS.ictv.name, ROIS.ictv.type, ROIS.ctv.color, sourcesA=[ROIS.igtv], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ictv], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) lungs_gtv = ROI.ROIAlgebra(ROIS.lungs_igtv.name, ROIS.lungs_igtv.type, COLORS.lungs, sourcesA=[ROIS.lungs], sourcesB=[ROIS.igtv], operator='Subtraction') water = ROI.ROIAlgebra(ROIS.z_water.name, ROIS.z_water.type, COLORS.other_ptv, sourcesA=[ROIS.lungs, ptv], sourcesB=[ROIS.igtv], operator='Subtraction', operatorA='Intersection') site.add_oars([lungs_gtv, water]) site.add_targets([ROIS.igtv, ictv, ptv]) # Without 4DCT: else: ctv = ROI.ROIAlgebra(ROIS.ctv.name, ROIS.ctv.type, ROIS.ctv.color, sourcesA=[ROIS.gtv], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) ptv = ROI.ROIAlgebra(ROIS.ptv.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ctv], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_10mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) lungs_gtv = ROI.ROIAlgebra(ROIS.lungs_gtv.name, ROIS.lungs_gtv.type, COLORS.lungs, sourcesA=[ROIS.lungs], sourcesB=[ROIS.gtv], operator='Subtraction') water = ROI.ROIAlgebra(ROIS.z_water.name, ROIS.z_water.type, COLORS.other_ptv, sourcesA=[ROIS.lungs, ptv], sourcesB=[ROIS.gtv], operator='Subtraction', operatorA='Intersection') site.add_oars([lungs_gtv, water]) site.add_targets([ROIS.gtv, ctv, ptv]) # Common for all palliative cases: heart_ptv = ROI.ROIAlgebra(ROIS.z_heart.name, ROIS.z_heart.type, COLORS.heart, sourcesA=[ROIS.heart], sourcesB=[ptv], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) esophagus_ptv = ROI.ROIAlgebra( ROIS.z_esophagus.name, ROIS.z_esophagus.type, COLORS.esophagus, sourcesA=[ROIS.esophagus], sourcesB=[ptv], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) site.add_oars([heart_ptv, esophagus_ptv]) # Stereotactic treatment: elif intent == 'stereotactic': # Choice 2: Side - left or right? side = choices[2] if side == 'right': site.add_oars([ROIS.rib_x_r, ROIS.rib_y_r, ROIS.ribs_r]) elif side == 'left': site.add_oars([ROIS.rib_x_l, ROIS.rib_y_l, ROIS.ribs_l]) nr_targets = choices[3] # Choice 3: Number of target volumes? if nr_targets == 'one': site.add_targets( [ROIS.igtv, ROIS.ictv, ROIS.iptv, ROIS.wall_ptv]) site.add_oars([ROIS.lungs_igtv]) elif nr_targets in ['two', 'three']: igtv = ROI.ROIAlgebra(ROIS.igtv.name, ROIS.igtv.type, ROIS.gtv.color, sourcesA=[ROIS.igtv1], sourcesB=[ROIS.igtv2]) site.add_targets([ ROIS.igtv1, ROIS.igtv2, igtv, ROIS.ictv1, ROIS.ictv2, ROIS.iptv1, ROIS.iptv2, ROIS.wall_ptv1, ROIS.wall_ptv2 ]) if nr_targets == 'three': igtv.sourcesB.extend([ROIS.igtv3]) site.add_targets( [ROIS.igtv3, ROIS.ictv3, ROIS.iptv3, ROIS.wall_ptv3]) lungs_igtv = ROI.ROIAlgebra(ROIS.lungs_igtv.name, 'Organ', COLORS.lungs, sourcesA=[ROIS.lungs], sourcesB=[igtv], operator='Subtraction') site.add_oars([lungs_igtv]) site.add_oars(DEF.lung_stereotactic_oars) # Create all targets and OARs in RayStation: site.create_rois()
def __init__(self, pm, examination, ss, choices, site): # Choice 1: Local/Regional/Regional with IMN region = choices[1] # Choice 2: Side - Left or right? side = choices[2] # Region: if region == 'partial': # Partial breast only: if side == 'right': # Right: breast_draft = ROIS.breast_r_draft breast = ROI.ROIAlgebra( ROIS.breast_r.name, ROIS.breast_r.type, ROIS.breast_r.color, sourcesA=[breast_draft], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.zero, marginsB=MARGINS.uniform_5mm_contraction) else: # Left: breast_draft = ROIS.breast_l_draft breast = ROI.ROIAlgebra( ROIS.breast_l.name, ROIS.breast_l.type, ROIS.breast_l.color, sourcesA=[breast_draft], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.zero, marginsB=MARGINS.uniform_5mm_contraction) # Targets: ctv_sb = ROI.ROIAlgebra(ROIS.ctv_sb.name, ROIS.ctv.type, ROIS.ctv.color, sourcesA=[ROIS.surgical_bed], sourcesB=[breast], operator='Intersection', marginsA=MARGINS.uniform_15mm_expansion, marginsB=MARGINS.zero) ptv_sbc = ROI.ROIAlgebra(ROIS.ptv_sbc.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ctv_sb], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) site.add_targets([ctv_sb, ptv_sbc]) # OARs: site.add_oars(DEF.breast_part_oars + [breast_draft, breast]) else: # Whole breast (with or without regional nodes): # Choice 3: With our without boost? boost = choices[3] if region == 'whole': # Whole breast: if side == 'right': breast_draft = ROIS.breast_r_draft # OARs: site.add_oars(DEF.breast_whole_oars + [ROIS.breast_r_draft]) else: breast_draft = ROIS.breast_l_draft # Left side: Use DL model: examination.RunOarSegmentation( ModelName="St. Olavs-Ă…lesund Breast CT", ExaminationsAndRegistrations={examination.Name: None}, RoisToInclude=[ "A_LAD", "BreastString_L", "Breast_L_Draft", "Clips_L", "Breast_R_Draft", "Esophagus", "Heart", "Lung_L", "Lung_R", "SpinalCanalFull", "Sternum", "SurgicalBed_L", "Trachea" ]) # Rename DL ROI(s): pm.RegionsOfInterest[ 'SpinalCanalFull'].Name = 'SpinalCanal' # Change type to 'Other' for selected ROIs: for roi_name in [ 'Clips_L', 'BreastString_L', 'Breast_L_Draft', 'Breast_R_Draft', 'SurgicalBed_L' ]: pm.RegionsOfInterest[ roi_name].OrganData.OrganType = "Other" # OARs: site.add_oars([ROIS.breast_r, ROIS.lungs]) # Targets: ctv = ROI.ROIAlgebra(ROIS.ctv.name, ROIS.ctv.type, ROIS.ctv.color, sourcesA=[breast_draft], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.zero, marginsB=MARGINS.uniform_5mm_contraction) ptv = ROI.ROIAlgebra(ROIS.ptv_c.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ctv], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) # Robustness evaluation volume: if side == 'right': ptv_robustness = ROI.ROIExpanded( 'PTV_robustness', ROIS.ptv.type, COLORS.ptv_high, ptv, margins=MARGINS.breast_right_robustness) else: ptv_robustness = ROI.ROIExpanded( 'PTV_robustness', ROIS.ptv.type, COLORS.ptv_high, ptv, margins=MARGINS.breast_left_robustness) # Targets for whole breast: site.add_targets([ctv, ptv, ptv_robustness]) elif region in ['regional', 'regional_imn']: # Regional breast (with or without IMN): # Side dependent OARs and support structures for regional treatment: if side == 'right': # Targets: ctv_p = ROI.ROIAlgebra( ROIS.ctv_p.name, ROIS.ctv_p.type, ROIS.ctv.color, sourcesA=[ROIS.breast_r_draft], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.zero, marginsB=MARGINS.uniform_5mm_contraction) ctv_n = ROI.ROIAlgebra(ROIS.ctv_n.name, ROIS.ctv_n.type, ROIS.ctv.color, sourcesA=[ ROIS.level_r, ROIS.level1_r, ROIS.level2_r, ROIS.level3_r, ROIS.level4_r ], sourcesB=[ctv_p], operator='Subtraction', marginsA=MARGINS.zero, marginsB=MARGINS.zero) if region == 'regional_imn': imn = ROIS.imn_r site.add_targets([imn]) # Others: site.add_oars([ ROIS.breast_r_draft, ROIS.breast_l, ROIS.level_r, ROIS.level1_r, ROIS.level2_r, ROIS.level3_r, ROIS.level4_r ]) # OARs: site.add_oars(DEF.breast_reg_oars + [ ROIS.humeral_r, ROIS.scalene_muscle_r, ROIS.artery1_r, ROIS.artery2_r, ROIS.artery3_r, ROIS.vein1_r, ROIS.vein2_r, ROIS.vein3_r, ROIS.liver ]) else: # Left side: Use DL model: examination.RunOarSegmentation( ModelName="St. Olavs-Ă…lesund Breast CT", ExaminationsAndRegistrations={examination.Name: None}, RoisToInclude=[ "A_Carotid_L", "A_LAD", "A_Subclavian_L+A_Axillary_L", "BreastString_L", "Breast_L_Draft", "Clips_L", "Breast_R_Draft", "Esophagus", "Heart", "HumeralHead_L", "LN_Ax_L1_L", "LN_Ax_L2_L", "LN_Ax_L3_L", "LN_Ax_L4_L", "LN_Ax_Pectoral_L", "LN_IMN_L", "Lung_L", "Lung_R", "ScaleneMusc_Ant_L", "SpinalCanalFull", "Sternum", "SurgicalBed_L", "ThyroidGland", "Trachea", "V_Brachioceph_L", "V_Jugular_L", "V_Subclavian_L+V_Axillary_L" ]) # Rename DL ROI(s): pm.RegionsOfInterest[ 'SpinalCanalFull'].Name = 'SpinalCanal' # Change type to 'Other' for selected ROIs: for roi_name in [ 'Clips_L', 'BreastString_L', 'Breast_L_Draft', 'LN_Ax_Pectoral_L', 'LN_Ax_L1_L', 'LN_Ax_L2_L', 'LN_Ax_L3_L', 'LN_Ax_L4_L', 'Breast_R_Draft', 'ScaleneMusc_Ant_L', 'A_Subclavian_L+A_Axillary_L', 'A_Carotid_L', 'V_Brachioceph_L', 'V_Subclavian_L+V_Axillary_L', 'V_Jugular_L', 'LN_IMN_L', 'SurgicalBed_L' ]: pm.RegionsOfInterest[ roi_name].OrganData.OrganType = "Other" # Targets: ctv_p = ROI.ROIAlgebra( ROIS.ctv_p.name, ROIS.ctv_p.type, ROIS.ctv.color, sourcesA=[ROIS.breast_l_draft], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.zero, marginsB=MARGINS.uniform_5mm_contraction) ctv_n = ROI.ROIAlgebra(ROIS.ctv_n.name, ROIS.ctv_n.type, ROIS.ctv.color, sourcesA=[ ROIS.level_l, ROIS.level1_l, ROIS.level2_l, ROIS.level3_l, ROIS.level4_l ], sourcesB=[ctv_p], operator='Subtraction', marginsA=MARGINS.zero, marginsB=MARGINS.zero) if region == 'regional_imn': imn = ROIS.imn_l # OARs: site.add_oars([ROIS.breast_r, ROIS.lungs]) # Common targets for left and right: ctv = ROI.ROIAlgebra(ROIS.ctv.name, ROIS.ctv.type, ROIS.ctv.color, sourcesA=[ctv_n], sourcesB=[ctv_p], operator='Union', marginsA=MARGINS.zero, marginsB=MARGINS.zero) ptv_p = ROI.ROIAlgebra( ROIS.ptv_pc.name, ROIS.ptv_pc.type, ROIS.ptv.color, sourcesA=[ctv_p], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) ptv_n = ROI.ROIAlgebra( ROIS.ptv_nc.name, ROIS.ptv_nc.type, ROIS.ptv.color, sourcesA=[ctv_n], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) ptv = ROI.ROIAlgebra(ROIS.ptv_c.name, ROIS.ptv.type, ROIS.ptv.color, sourcesA=[ptv_n], sourcesB=[ptv_p], operator='Union', marginsA=MARGINS.zero, marginsB=MARGINS.zero) # IMN: if region == 'regional_imn': ctv_n.sourcesA.extend([imn]) # Robustness evaluation volume: if side == 'right': ptv_robustness = ROI.ROIExpanded( 'PTV_robustness', ROIS.ptv.type, COLORS.ptv_high, ptv_p, margins=MARGINS.breast_right_robustness) else: ptv_robustness = ROI.ROIExpanded( 'PTV_robustness', ROIS.ptv.type, COLORS.ptv_high, ptv_p, margins=MARGINS.breast_left_robustness) # Common targets for all regional: site.add_targets( [ctv_p, ctv_n, ctv, ptv_p, ptv_n, ptv, ptv_robustness]) # Add targets for boost (2 Gy x 8) if selected: if boost == 'with': if side == 'right': sb = ROIS.surgical_bed_r site.add_targets([sb]) else: sb = ROIS.surgical_bed_l ctv_sb = ROI.ROIAlgebra(ROIS.ctv_sb.name, ROIS.ctv.type, ROIS.ctv.color, sourcesA=[sb], sourcesB=[ctv], operator='Intersection', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.zero) ptv_sbc = ROI.ROIAlgebra( ROIS.ptv_sbc.name, ROIS.ptv_sb.type, ROIS.ptv.color, sourcesA=[ctv_sb], sourcesB=[ROIS.external], operator='Intersection', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.uniform_5mm_contraction) site.add_targets([ctv_sb, ptv_sbc]) # Create all targets and OARs in RayStation: site.create_rois() if 'ptv_robustness' in locals(): # Change type of robustness volume to avoid problems with dose grid and dose calculation: pm.RegionsOfInterest['PTV_robustness'].Type = "Control" pm.RegionsOfInterest[ 'PTV_robustness'].OrganData.OrganType = "Other"
def __init__(self, pm, examination, ss, choices, site): # Choice 1: Region - prostate or bed? region = choices[1] if region == 'prostate': # Prostate: # Choice 2: Fractionation - normo or hypo? frac = choices[2] if frac == 'normo': # Conventionally fractionated prostate with vesicles (2.2Gy x 35): # Choice 3: Nodes - included or not? nodes = choices[3] # Targets: ctv_77 = ROI.ROIExpanded(ROIS.ctv_77.name, ROIS.ctv_77.type, COLORS.ctv_high, source=ROIS.prostate) ptv_77 = ROI.ROIExpanded( ROIS.ptv_77.name, ROIS.ptv_77.type, COLORS.ptv_high, source=ROIS.prostate, margins=MARGINS.prostate_seed_expansion) # OARs: bladder_ptv = ROI.ROIAlgebra( ROIS.z_bladder.name, ROIS.z_bladder.type, COLORS.bladder, sourcesA=[ROIS.bladder], sourcesB=[ptv_77], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) rectum_ptv = ROI.ROIAlgebra( ROIS.z_rectum.name, ROIS.z_rectum.type, COLORS.rectum, sourcesA=[ROIS.rectum], sourcesB=[ptv_77], operator='Subtraction', marginsB=MARGINS.uniform_2mm_expansion) wall_ptv_77 = ROI.ROIWall(ROIS.z_ptv_77_wall.name, ROIS.z_ptv_77_wall.type, COLORS.wall, ptv_77, 0.5, 0) if nodes == 'no': # Prostate only: # Targets: ctv_70 = ROI.ROIAlgebra(ROIS.ctv_70_sib.name, ROIS.ctv_70.type, COLORS.ctv_med, sourcesA=[ROIS.vesicles], sourcesB=[ptv_77], operator='Subtraction', marginsA=MARGINS.zero, marginsB=MARGINS.zero) ptv_70 = ROI.ROIAlgebra( ROIS.ptv_70_sib.name, ROIS.ptv_70.type, COLORS.ptv_med, sourcesA=[ROIS.vesicles], sourcesB=[ptv_77], operator='Subtraction', marginsA=MARGINS.uniform_8mm_expansion, marginsB=MARGINS.zero) ptv_70_77 = ROI.ROIAlgebra( ROIS.ptv_70_77.name, ROIS.ptv_70_77.type, COLORS.ptv_low, sourcesA=[ROIS.prostate], sourcesB=[ROIS.vesicles], marginsA=MARGINS.prostate_seed_expansion, marginsB=MARGINS.uniform_8mm_expansion) site.add_targets([ptv_70_77]) # OARs: bladder_ptv.sourcesB.extend([ptv_70]) rectum_ptv.sourcesB.extend([ptv_70]) site.add_oars(DEF.prostate_oars + [bladder_ptv, rectum_ptv, wall_ptv_77]) elif nodes == 'with_node': # Elective nodes (with positive node): # Targets: ctv_n = ROI.ROIExpanded( ROIS.ctv_n.name, ROIS.ctv_n.type, COLORS.pelvic_nodes, source=ROIS.gtv_n, margins=MARGINS.uniform_5mm_expansion) ptv_n = ROI.ROIExpanded( ROIS.ptv_n.name, ROIS.ptv_n.type, ROIS.ptv_n.color, source=ctv_n, margins=MARGINS.prostate_lymph_nodes_seed_expansion) ctv_70 = ROI.ROIAlgebra(ROIS.ctv_70_sib.name, ROIS.ctv_70.type, COLORS.ctv_med, sourcesA=[ROIS.vesicles, ctv_n], sourcesB=[ptv_77], operator='Subtraction', marginsA=MARGINS.zero, marginsB=MARGINS.zero) ptv_semves = ROI.ROIAlgebra( ROIS.ptv_semves.name, ROIS.ptv_semves.type, COLORS.ptv_med, sourcesA=[ROIS.vesicles], sourcesB=[ptv_77], operator='Subtraction', marginsA=MARGINS.uniform_8mm_expansion, marginsB=MARGINS.zero) ptv_70 = ROI.ROIAlgebra(ROIS.ptv_70_sib.name, ROIS.ptv_70_sib.type, ROIS.ptv_70_sib.color, sourcesA=[ptv_semves, ptv_n], sourcesB=[ptv_77], operator='Subtraction', marginsA=MARGINS.zero, marginsB=MARGINS.zero) ptv_70_77 = ROI.ROIAlgebra(ROIS.ptv_70_77.name, ROIS.ptv_70_77.type, COLORS.ptv_low, sourcesA=[ptv_70], sourcesB=[ptv_77], marginsA=MARGINS.zero, marginsB=MARGINS.zero) ptv_56 = ROI.ROIAlgebra( ROIS.ptv_56.name, ROIS.ptv_56.type, COLORS.ptv_low, sourcesA=[ROIS.pelvic_nodes], sourcesB=[ptv_77, ptv_70], operator='Subtraction', marginsA=MARGINS.prostate_lymph_nodes_seed_expansion, marginsB=MARGINS.zero) ctv_56 = ROI.ROIAlgebra(ROIS.ctv_56.name, ROIS.ctv_56.type, COLORS.ctv_low, sourcesA=[ROIS.pelvic_nodes], sourcesB=[ptv_77, ptv_70], operator='Subtraction', marginsA=MARGINS.zero, marginsB=MARGINS.zero) ptv_56_70_77 = ROI.ROIAlgebra(ROIS.ptv_56_70_77.name, ROIS.ptv_56_70_77.type, COLORS.ptv_low, sourcesA=[ptv_56, ptv_70], sourcesB=[ptv_77], marginsA=MARGINS.zero, marginsB=MARGINS.zero) site.add_targets([ ROIS.gtv_n, ROIS.pelvic_nodes, ctv_n, ctv_56, ptv_n, ptv_semves, ptv_56, ptv_70_77, ptv_56_70_77 ]) # OARs: bladder_ptv.sourcesB.extend([ptv_70, ptv_56]) rectum_ptv.sourcesB.extend([ptv_70, ptv_56]) bowel_ptv = ROI.ROIAlgebra( ROIS.z_spc_bowel.name, ROIS.z_spc_bowel.type, COLORS.bowel_space, sourcesA=[ROIS.bowel_space], sourcesB=[ptv_77, ptv_70, ptv_56], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) wall_ptv_70_77 = ROI.ROIWall(ROIS.z_ptv_70_77_wall.name, ROIS.z_ptv_70_77_wall.type, COLORS.wall, ptv_70_77, 1, 0) site.add_oars(DEF.prostate_nodes_oars + [bladder_ptv, rectum_ptv, wall_ptv_77] + [bowel_ptv, wall_ptv_70_77]) elif nodes == 'with': # Elective nodes: # Targets: ctv_70 = ROI.ROIAlgebra(ROIS.ctv_70_sib.name, ROIS.ctv_70.type, COLORS.ctv_med, sourcesA=[ROIS.vesicles], sourcesB=[ptv_77], operator='Subtraction', marginsA=MARGINS.zero, marginsB=MARGINS.zero) ptv_70 = ROI.ROIAlgebra( ROIS.ptv_70_sib.name, ROIS.ptv_70.type, COLORS.ptv_med, sourcesA=[ROIS.vesicles], sourcesB=[ptv_77], operator='Subtraction', marginsA=MARGINS.uniform_8mm_expansion, marginsB=MARGINS.zero) ptv_70_77 = ROI.ROIAlgebra( ROIS.ptv_70_77.name, ROIS.ptv_70_77.type, COLORS.ptv_low, sourcesA=[ROIS.prostate], sourcesB=[ROIS.vesicles], marginsA=MARGINS.prostate_seed_expansion, marginsB=MARGINS.uniform_8mm_expansion) ptv_56 = ROI.ROIAlgebra( ROIS.ptv_56.name, ROIS.ptv_56.type, COLORS.ptv_low, sourcesA=[ROIS.pelvic_nodes], sourcesB=[ptv_77, ptv_70], operator='Subtraction', marginsA=MARGINS.prostate_lymph_nodes_seed_expansion, marginsB=MARGINS.zero) ctv_56 = ROI.ROIAlgebra(ROIS.ctv_56.name, ROIS.ctv_56.type, COLORS.ctv_low, sourcesA=[ROIS.pelvic_nodes], sourcesB=[ptv_77, ptv_70], operator='Subtraction', marginsA=MARGINS.zero, marginsB=MARGINS.zero) ptv_56_70_77 = ROI.ROIAlgebra(ROIS.ptv_56_70_77.name, ROIS.ptv_56_70_77.type, COLORS.ptv_low, sourcesA=[ptv_56, ptv_70], sourcesB=[ptv_77], marginsA=MARGINS.zero, marginsB=MARGINS.zero) site.add_targets([ ROIS.pelvic_nodes, ctv_56, ptv_56, ptv_70_77, ptv_56_70_77 ]) # OARs: bladder_ptv.sourcesB.extend([ptv_70, ptv_56]) rectum_ptv.sourcesB.extend([ptv_70, ptv_56]) bowel_ptv = ROI.ROIAlgebra( ROIS.z_spc_bowel.name, ROIS.z_spc_bowel.type, COLORS.bowel_space, sourcesA=[ROIS.bowel_space], sourcesB=[ptv_77, ptv_70, ptv_56], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) wall_ptv_70_77 = ROI.ROIWall(ROIS.z_ptv_70_77_wall.name, ROIS.z_ptv_70_77_wall.type, COLORS.wall, ptv_70_77, 1, 0) site.add_oars(DEF.prostate_nodes_oars + [bladder_ptv, rectum_ptv, wall_ptv_77] + [bowel_ptv, wall_ptv_70_77]) # Common ROIs for all conventional fractionation: site.add_targets([ ROIS.prostate, ROIS.vesicles, ctv_77, ctv_70, ptv_77, ptv_70 ]) elif frac == 'hypo_60': # Hypofractionated prostate with vesicles (3 Gy x 20): # Targets: ptv_57_60 = ROI.ROIAlgebra( ROIS.ptv_57_60.name, ROIS.ptv_57_60.type, COLORS.ptv_low, sourcesA=[ROIS.prostate], sourcesB=[ROIS.vesicles], marginsA=MARGINS.prostate_seed_expansion, marginsB=MARGINS.uniform_8mm_expansion) ptv_60 = ROI.ROIExpanded( ROIS.ptv_60.name, ROIS.ptv_60.type, COLORS.ptv_high, source=ROIS.prostate, margins=MARGINS.prostate_seed_expansion) ptv_57 = ROI.ROIAlgebra(ROIS.ptv_57.name, ROIS.ptv_57.type, COLORS.ptv_med, sourcesA=[ptv_57_60], sourcesB=[ptv_60], operator='Subtraction', marginsA=MARGINS.zero, marginsB=MARGINS.zero) ctv_57_60 = ROI.ROIAlgebra(ROIS.ctv_57_60.name, ROIS.ctv_57_60.type, COLORS.ctv_low, sourcesA=[ROIS.prostate], sourcesB=[ROIS.vesicles], marginsA=MARGINS.zero, marginsB=MARGINS.zero) ctv_60 = ROI.ROIExpanded(ROIS.ctv_60.name, ROIS.ctv_60.type, COLORS.ctv_high, source=ROIS.prostate) ctv_57 = ROI.ROIAlgebra(ROIS.ctv_57.name, ROIS.ctv_57.type, COLORS.ctv_med, sourcesA=[ctv_57_60], sourcesB=[ptv_60], operator='Subtraction', marginsA=MARGINS.zero, marginsB=MARGINS.zero) site.add_targets([ ROIS.prostate, ROIS.vesicles, ctv_60, ctv_57, ctv_57_60, ptv_57_60, ptv_60, ptv_57 ]) # OARs: bladder_ptv = ROI.ROIAlgebra( ROIS.z_bladder.name, ROIS.z_bladder.type, COLORS.bladder, sourcesA=[ROIS.bladder], sourcesB=[ptv_60, ptv_57], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) rectum_ptv = ROI.ROIAlgebra( ROIS.z_rectum.name, ROIS.z_rectum.type, COLORS.rectum, sourcesA=[ROIS.rectum], sourcesB=[ptv_60, ptv_57], operator='Subtraction', marginsB=MARGINS.uniform_2mm_expansion) wall_ptv_60 = ROI.ROIWall(ROIS.z_ptv_60_wall.name, ROIS.z_ptv_60_wall.type, COLORS.wall, ptv_60, 0.5, 0) wall_ptv_57_60 = ROI.ROIWall(ROIS.z_ptv_57_60_wall.name, ROIS.z_ptv_57_60_wall.type, COLORS.wall, ptv_57_60, 1, 0) site.add_oars( DEF.prostate_oars + [bladder_ptv, rectum_ptv, wall_ptv_60, wall_ptv_57_60]) elif frac in ['hypo_55', 'palliative']: # STAMPEDE (2.75 Gy x 20) or palliative prostate (e.q. 3 Gy x 13): # Targets: ctv = ROI.ROIExpanded(ROIS.ctv.name, ROIS.ctv.type, COLORS.ctv_low, source=ROIS.prostate, margins=MARGINS.zero) if frac == 'hypo_55': # Choice 3: Seed match or bone match? match = choices[3] if match == 'seeds': # Seed match: ptv = ROI.ROIExpanded( ROIS.ptv.name, ROIS.ptv.type, COLORS.ptv_high, source=ctv, margins=MARGINS.prostate_seed_expansion) else: # Bone match: ptv = ROI.ROIExpanded( ROIS.ptv.name, ROIS.ptv.type, COLORS.ptv_high, source=ctv, margins=MARGINS.prostate_bone_match_expansion) elif frac == 'palliative': # Assuming no markers: ptv = ROI.ROIExpanded( ROIS.ptv.name, ROIS.ptv.type, COLORS.ptv_high, source=ctv, margins=MARGINS.prostate_bone_match_expansion) site.add_targets([ROIS.prostate, ctv, ptv]) # OARs: bladder_ptv = ROI.ROIAlgebra( ROIS.z_bladder.name, ROIS.z_bladder.type, COLORS.bladder, sourcesA=[ROIS.bladder], sourcesB=[ptv], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) rectum_ptv = ROI.ROIAlgebra( ROIS.z_rectum.name, ROIS.z_rectum.type, COLORS.rectum, sourcesA=[ROIS.rectum], sourcesB=[ptv], operator='Subtraction', marginsB=MARGINS.uniform_2mm_expansion) wall_ptv_55 = ROI.ROIWall(ROIS.z_ptv_wall.name, ROIS.z_ptv_wall.type, COLORS.wall, ptv, 1, 0) site.add_oars(DEF.prostate_palliative_oars + [bladder_ptv, rectum_ptv, wall_ptv_55]) else: # Prostate bed: # Choice 2: Fractionation - normo or hypo? frac = choices[2] # Fractionation: if frac == 'normo': # Conventional fractionation (2 Gy): # Choice 3: Nodes - included or not? nodes = choices[3] if nodes == 'no': # Prostate bed only: # Targets: ctv_70 = ROI.ROIExpanded(ROIS.ctv_70.name, ROIS.ctv_70.type, COLORS.ctv_high, source=ROIS.ctv_sb) ptv_70 = ROI.ROIExpanded( ROIS.ptv_70.name, ROIS.ptv_70.type, COLORS.ptv, source=ctv_70, margins=MARGINS.prostate_bone_match_expansion) # OARs: bladder_ptv = ROI.ROIAlgebra( ROIS.z_bladder.name, ROIS.z_bladder.type, COLORS.bladder, sourcesA=[ROIS.bladder], sourcesB=[ptv_70], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) rectum_ptv = ROI.ROIAlgebra( ROIS.z_rectum.name, ROIS.z_rectum.type, COLORS.rectum, sourcesA=[ROIS.rectum], sourcesB=[ptv_70], operator='Subtraction', marginsB=MARGINS.uniform_2mm_expansion) site.add_oars(DEF.prostate_bed_oars + [bladder_ptv, rectum_ptv]) else: # Elective nodes: if nodes == 'with': # Targets: ctv_70 = ROI.ROIExpanded(ROIS.ctv_70.name, ROIS.ctv_70.type, COLORS.ctv_high, source=ROIS.ctv_sb) ptv_70 = ROI.ROIExpanded( ROIS.ptv_70.name, ROIS.ptv_70.type, COLORS.ptv, source=ctv_70, margins=MARGINS.prostate_bone_match_expansion) else: # Elective nodes (with positive node): # Targets: ctv_n = ROI.ROIExpanded( ROIS.ctv_n.name, ROIS.ctv_n.type, COLORS.pelvic_nodes, source=ROIS.gtv_n, margins=MARGINS.uniform_5mm_expansion) ptv_n = ROI.ROIExpanded( ROIS.ptv_n.name, ROIS.ptv_n.type, ROIS.ptv_n.color, source=ctv_n, margins=MARGINS.uniform_5mm_expansion) ptv_sb = ROI.ROIExpanded( ROIS.ptv_sb.name, ROIS.ptv_sb.type, ROIS.ptv_sb.color, source=ROIS.ctv_sb, margins=MARGINS.prostate_bone_match_expansion) ctv_70 = ROI.ROIAlgebra(ROIS.ctv_70.name, ROIS.ctv_70.type, COLORS.ctv_med, sourcesA=[ROIS.ctv_sb], sourcesB=[ctv_n], operator='Union') ptv_70 = ROI.ROIAlgebra(ROIS.ptv_70.name, ROIS.ptv_70.type, COLORS.ptv, sourcesA=[ptv_sb], sourcesB=[ptv_n], operator='Union', marginsA=MARGINS.zero, marginsB=MARGINS.zero) site.add_targets([ROIS.gtv_n, ctv_n, ptv_n, ptv_sb]) # Common for elective nodes (with or without positive node): # Targets: ctv_56 = ROI.ROIAlgebra(ROIS.ctv_56.name, ROIS.ctv_56.type, COLORS.ctv_low, sourcesA=[ROIS.pelvic_nodes], sourcesB=[ptv_70], operator='Subtraction', marginsA=MARGINS.zero, marginsB=MARGINS.zero) ptv_56 = ROI.ROIAlgebra( ROIS.ptv_56.name, ROIS.ptv_56.type, COLORS.ptv_low, sourcesA=[ROIS.pelvic_nodes], sourcesB=[ptv_70], operator='Subtraction', marginsA=MARGINS.uniform_5mm_expansion, marginsB=MARGINS.zero) ptv_56_70 = ROI.ROIAlgebra(ROIS.ptv_56_70.name, ROIS.ptv_56_70.type, COLORS.ptv_low, sourcesA=[ptv_56], sourcesB=[ptv_70], marginsA=MARGINS.zero, marginsB=MARGINS.zero) site.add_targets( [ROIS.pelvic_nodes, ctv_56, ptv_56, ptv_56_70]) # OARs: bladder_ptv = ROI.ROIAlgebra( ROIS.z_bladder.name, ROIS.z_bladder.type, COLORS.bladder, sourcesA=[ROIS.bladder], sourcesB=[ptv_70, ptv_56], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) rectum_ptv = ROI.ROIAlgebra( ROIS.z_rectum.name, ROIS.z_rectum.type, COLORS.rectum, sourcesA=[ROIS.rectum], sourcesB=[ptv_70, ptv_56], operator='Subtraction', marginsB=MARGINS.uniform_2mm_expansion) bowel_ptv = ROI.ROIAlgebra( ROIS.z_spc_bowel.name, ROIS.z_spc_bowel.type, COLORS.bowel_space, sourcesA=[ROIS.bowel_space], sourcesB=[ptv_70, ptv_56], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) wall_ptv_70 = ROI.ROIWall(ROIS.z_ptv_70_wall.name, ROIS.z_ptv_70_wall.type, COLORS.wall, ptv_70, 1, 0) wall_ptv_56_temp = ROI.ROIWall(ROIS.z_ptv_56_temp.name, ROIS.z_ptv_56_temp.type, COLORS.wall, ptv_56, 1, 0) wall_ptv_56 = ROI.ROIAlgebra( ROIS.z_ptv_56_wall.name, ROIS.z_ptv_56_wall.type, COLORS.wall, sourcesA=[wall_ptv_56_temp], sourcesB=[ptv_70, wall_ptv_70], operator='Subtraction', marginsB=MARGINS.zero) site.add_oars(DEF.prostate_bed_nodes_oars + [bladder_ptv, rectum_ptv] + [ bowel_ptv, ROIS.bowel_space, wall_ptv_70, wall_ptv_56_temp, wall_ptv_56 ]) # Common for all prostate bed (with or without nodes): site.add_targets([ROIS.ctv_sb, ctv_70, ptv_70]) else: # Hypofractionated (palliative): # Targets: ptv = ROI.ROIExpanded( ROIS.ptv_sb.name, ROIS.ptv_sb.type, COLORS.ptv_high, source=ROIS.ctv_sb, margins=MARGINS.prostate_bone_match_expansion) site.add_targets([ROIS.ctv_sb, ptv]) # OARs: bladder_ptv = ROI.ROIAlgebra( ROIS.z_bladder.name, ROIS.z_bladder.type, COLORS.bladder, sourcesA=[ROIS.bladder], sourcesB=[ptv], operator='Subtraction', marginsB=MARGINS.uniform_3mm_expansion) rectum_ptv = ROI.ROIAlgebra( ROIS.z_rectum.name, ROIS.z_rectum.type, COLORS.rectum, sourcesA=[ROIS.rectum], sourcesB=[ptv], operator='Subtraction', marginsB=MARGINS.uniform_2mm_expansion) wall_ptv = ROI.ROIWall(ROIS.z_ptv_wall.name, ROIS.z_ptv_wall.type, COLORS.wall, ptv, 1, 0) site.add_oars([bladder_ptv, rectum_ptv, wall_ptv]) # Create all targets and OARs in RayStation: site.create_rois()